From 368ef242ff59b6556e155ba4007630991c328cff Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 18 Jan 2020 18:49:55 +0100 Subject: [PATCH 001/653] CCSDSTime bugfix for atmel Possible good for other cases too? --- timemanager/CCSDSTime.cpp | 43 +++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/timemanager/CCSDSTime.cpp b/timemanager/CCSDSTime.cpp index 32032716..2eb6c4b5 100644 --- a/timemanager/CCSDSTime.cpp +++ b/timemanager/CCSDSTime.cpp @@ -154,32 +154,41 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* if (length < 19) { return RETURN_FAILED; } - uint16_t year; - uint8_t month; - uint16_t day; - uint8_t hour; - uint8_t minute; - float second; -//try Code A (yyyy-mm-dd) - int count = sscanf((char *) from, "%4hi-%2hhi-%2hiT%2hhi:%2hhi:%fZ", &year, - &month, &day, &hour, &minute, &second); - if (count == 6) { + // In the size optimized nano library used by ATMEL, floating point conversion + // is not allowed. There is a linker flag to allow it apparently, but I + // could not manage to make it run (removing -specs=nano.specs in linker flags works though, + // but we propably should include this). Using floats with sscanf is also expensive. + // Furthermore, the stdio.c library by ATMEL can't resolve the %hhi specifiers + // Therefore, I adapted this function. + int year; + int month; + int day; + int hour; + int minute; + int second; + int usecond; + // try Code A (yyyy-mm-dd) + //int count = sscanf((char *) from, "%4hi-%2hi-%2hiT%2hi:%2hi:%fZ", &year, + // &month, &day, &hour, &minute, &second); + int count = sscanf((char *) from, "%4d-%2d-%2dT%2d:%2d:%2d.%dZ", &year, + &month, &day, &hour, &minute, &second, &usecond); + if (count == 7) { to->year = year; to->month = month; to->day = day; to->hour = hour; to->minute = minute; to->second = second; - to->usecond = (second - floor(second)) * 1000000; + to->usecond = usecond;//(second - floor(second)) * 1000000; return RETURN_OK; } - //try Code B (yyyy-ddd) - count = sscanf((char *) from, "%4hi-%3hiT%2hhi:%2hhi:%fZ", &year, &day, - &hour, &minute, &second); - if (count == 5) { + // try Code B (yyyy-ddd) + count = sscanf((char *) from, "%4i-%3iT%2i:%2i:%2i.%iZ", &year, &day, + &hour, &minute, &second, &usecond); + if (count == 6) { uint8_t tempDay; - ReturnValue_t result = CCSDSTime::convertDaysOfYear(day, year, &month, + ReturnValue_t result = CCSDSTime::convertDaysOfYear((uint16_t)day,(uint16_t) year,(uint8_t *) &month, &tempDay); if (result != RETURN_OK) { return RETURN_FAILED; @@ -190,7 +199,7 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* to->hour = hour; to->minute = minute; to->second = second; - to->usecond = (second - floor(second)) * 1000000; + to->usecond = usecond; return RETURN_OK; } From e03aff373156245fbad37bebda646f3be535aaae Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 3 Feb 2020 22:34:15 +0100 Subject: [PATCH 002/653] Device Handler Base Proposals 1. Interface functions moved closer to top (and functions which should be implemented) 2. ioBoardAddress renamed to logicalAddress. getter FUnction added. 3. debug interface for easier debugging of device handlers 4. new documentation 5. new return value for scanForReply to ignore full packet --- devicehandlers/DeviceHandlerBase.cpp | 220 +++++------ devicehandlers/DeviceHandlerBase.h | 540 +++++++++++++++------------ 2 files changed, 417 insertions(+), 343 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index ae9199f2..c4f7465d 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -16,32 +16,32 @@ 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) { - commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize, - CommandMessage::MAX_MESSAGE_SIZE); + 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; insertInCommandMap(RAW_COMMAND_ID); if (this->fdirInstance == NULL) { - this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, - defaultFDIRParentId); + this->fdirInstance = + new DeviceHandlerFailureIsolation(setObjectId, defaultFDIRParentId); } } @@ -55,7 +55,6 @@ DeviceHandlerBase::~DeviceHandlerBase() { ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { this->pstStep = counter; - if (counter == 0) { cookieInfo.state = COOKIE_UNUSED; readCommandQueue(); @@ -91,6 +90,85 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { return RETURN_OK; } +ReturnValue_t DeviceHandlerBase::initialize() { + ReturnValue_t result = SystemObject::initialize(); + if (result != RETURN_OK) { + return result; + } + + communicationInterface = objectManager->get( + deviceCommunicationId); + if (communicationInterface == NULL) { + return RETURN_FAILED; + } + + result = communicationInterface->open(&cookie, logicalAddress, + maxDeviceReplyLen); + if (result != RETURN_OK) { + return result; + } + + IPCStore = objectManager->get(objects::IPC_STORE); + if (IPCStore == NULL) { + return RETURN_FAILED; + } + + AcceptsDeviceResponsesIF *rawReceiver = objectManager->get< + AcceptsDeviceResponsesIF>(rawDataReceiverId); + + if (rawReceiver == NULL) { + return RETURN_FAILED; + } + + defaultRawReceiver = rawReceiver->getDeviceQueue(); + + powerSwitcher = objectManager->get(powerSwitcherId); + if (powerSwitcher == NULL) { + return RETURN_FAILED; + } + + result = healthHelper.initialize(); + if (result != RETURN_OK) { + return result; + } + + result = modeHelper.initialize(); + if (result != RETURN_OK) { + return result; + } + result = actionHelper.initialize(commandQueue); + if (result != RETURN_OK) { + return result; + } + result = fdirInstance->initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + result = parameterHelper.initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + result = hkSwitcher.initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + fillCommandAndReplyMap(); + + //Set temperature target state to NON_OP. + DataSet mySet; + PoolVariable thermalRequest(deviceThermalRequestPoolId, &mySet, + PoolVariableIF::VAR_WRITE); + mySet.read(); + thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; + mySet.commit(PoolVariableIF::VALID); + + return RETURN_OK; + +} + void DeviceHandlerBase::decrementDeviceReplyMap() { for (std::map::iterator iter = deviceReplyMap.begin(); iter != deviceReplyMap.end(); iter++) { @@ -455,7 +533,8 @@ 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 @@ -470,7 +549,6 @@ void DeviceHandlerBase::doGetWrite() { void DeviceHandlerBase::doSendRead() { ReturnValue_t result; - result = communicationInterface->requestReceiveMessage(cookie); if (result == RETURN_OK) { cookieInfo.state = COOKIE_READ_SENT; @@ -539,6 +617,8 @@ void DeviceHandlerBase::doGetRead() { break; case IGNORE_REPLY_DATA: break; + case IGNORE_FULL_PACKET: + return; default: //We need to wait for timeout.. don't know what command failed and who sent it. replyRawReplyIfnotWiretapped(receivedData, foundLen); @@ -579,84 +659,6 @@ ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, } -ReturnValue_t DeviceHandlerBase::initialize() { - ReturnValue_t result = SystemObject::initialize(); - if (result != RETURN_OK) { - return result; - } - - communicationInterface = objectManager->get( - deviceCommunicationId); - if (communicationInterface == NULL) { - return RETURN_FAILED; - } - - result = communicationInterface->open(&cookie, ioBoardAddress, - maxDeviceReplyLen); - if (result != RETURN_OK) { - return result; - } - - IPCStore = objectManager->get(objects::IPC_STORE); - if (IPCStore == NULL) { - return RETURN_FAILED; - } - - AcceptsDeviceResponsesIF *rawReceiver = objectManager->get< - AcceptsDeviceResponsesIF>(rawDataReceiverId); - - if (rawReceiver == NULL) { - return RETURN_FAILED; - } - - defaultRawReceiver = rawReceiver->getDeviceQueue(); - - powerSwitcher = objectManager->get(powerSwitcherId); - if (powerSwitcher == NULL) { - return RETURN_FAILED; - } - - result = healthHelper.initialize(); - if (result != RETURN_OK) { - return result; - } - - result = modeHelper.initialize(); - if (result != RETURN_OK) { - return result; - } - result = actionHelper.initialize(commandQueue); - if (result != RETURN_OK) { - return result; - } - result = fdirInstance->initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - - result = parameterHelper.initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - - result = hkSwitcher.initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - - fillCommandAndReplyMap(); - - //Set temperature target state to NON_OP. - DataSet mySet; - PoolVariable thermalRequest(deviceThermalRequestPoolId, &mySet, - PoolVariableIF::VAR_WRITE); - mySet.read(); - thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; - mySet.commit(PoolVariableIF::VALID); - - return RETURN_OK; - -} void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len, MessageQueueId_t sendTo, bool isCommand) { @@ -672,7 +674,6 @@ void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len, } CommandMessage message; - DeviceHandlerMessage::setDeviceHandlerRawReplyMessage(&message, getObjectId(), address, isCommand); @@ -753,7 +754,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 +838,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--; @@ -1112,8 +1114,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 +1271,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, object_id_t objectId, uint32_t parameter) { +} + +uint32_t DeviceHandlerBase::getLogicalAddress() { + return logicalAddress; +} diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 756ad530..f16a4ff9 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -34,24 +34,40 @@ class StorageManagerIF; */ /** - * \brief This is the abstract base class for device handlers. - * + * @brief This is the abstract base class for device handlers. + * @details * 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 @endlink, and communication with commanding objects. * 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. + * NOTE: RMAP is a 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. * * 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). + * The following abstract methods must be implemented by a device handler: + * 1. doStartUp() + * 2. doShutDown() + * 3. buildTransitionDeviceCommand() + * 4. buildNormalDeviceCommand() + * 5. buildCommandFromCommand() + * 6. fillCommandAndReplyMap() + * 7. scanForReply() + * 8. interpretDeviceReply() * - * \ingroup devices + * Other important virtual methods with a default implementation + * are the getTransitionDelayMs() function and the getSwitches() function. + * + * @ingroup devices */ class DeviceHandlerBase: public DeviceHandlerIF, public HasReturnvaluesIF, @@ -69,55 +85,270 @@ public: * @param setObjectId the ObjectId to pass to the SystemObject() Constructor * @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() + * @param deviceCommuncation Communcation Interface object which is used to implement communication functions + * @param thermalStatePoolId + * @param thermalRequestPoolId + * @param fdirInstance + * @param cmdQueueSize */ - 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, + object_id_t deviceCommunication, + uint32_t thermalStatePoolId = PoolVariableIF::NO_PARAMETER, uint32_t thermalRequestPoolId = PoolVariableIF::NO_PARAMETER, FailureIsolationBase* fdirInstance = NULL, uint32_t cmdQueueSize = 20); - virtual MessageQueueId_t getCommandQueue(void) const; - - /** - * This function is a 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 - * 2. Handles Device State Modes by calling doStateMachine(). - * This function calls callChildStatemachine() which calls the abstract functions - * doStartUp() and doShutDown() - * 3. Check switch states by calling checkSwitchStates() - * 4. Decrements counter for timeout of replies by calling decrementDeviceReplyMap() - * 5. Performs FDIR check for failures - * 6. Calls hkSwitcher.performOperation() - * 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(). - * 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() - * @param counter Specifies which Action to perform - * @return RETURN_OK for successful execution - */ + * @brief This function is the device handler base core component and is called periodically. + * @details + * General sequence, showing where abstract virtual functions are called: + * If the State is SEND_WRITE: + * 1. Set the cookie state to COOKIE_UNUSED and read the command queue + * 2. Handles Device State Modes by calling doStateMachine(). + * This function calls callChildStatemachine() which calls the abstract functions + * doStartUp() and doShutDown() + * 3. Check switch states by calling checkSwitchStates() + * 4. Decrements counter for timeout of replies by calling decrementDeviceReplyMap() + * 5. Performs FDIR check for failures + * 6. Calls hkSwitcher.performOperation() + * 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() 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() 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 + */ virtual ReturnValue_t performOperation(uint8_t counter); + /** + * @brief Initializes the device handler + * @details + * Initialize Device Handler as system object and + * initializes all important helper classes. + * Calls fillCommandAndReplyMap(). + * @return + */ virtual ReturnValue_t initialize(); - /** - * - * @param parentQueueId - */ - virtual void setParentQueue(MessageQueueId_t parentQueueId); /** * Destructor. */ virtual ~DeviceHandlerBase(); +protected: + /** + * This is used to let the child class handle the transition from mode @c _MODE_START_UP to @c MODE_ON + * + * It is only called when the device handler is in mode @c _MODE_START_UP. That means, the device switch(es) are already set to on. + * Device handler commands are read and can be handled by the child class. If the child class handles a command, it should also send + * an reply accordingly. + * If an Command is not handled (ie #DeviceHandlerCommand is not @c CMD_NONE, the base class handles rejecting the command and sends a reply. + * The replies for mode transitions are handled by the base class. + * + * If the device is started and ready for operation, the mode should be set to MODE_ON. It is possible to set the mode to _MODE_TO_ON to + * use the to on transition if available. + * If the power-up fails, the mode should be set to _MODE_POWER_DOWN which will lead to the device being powered off. + * If the device does not change the mode, the mode will be changed to _MODE_POWER_DOWN, after the timeout (from getTransitionDelay()) has passed. + * + * #transitionFailure can be set to a failure code indicating the reason for a failed transition + */ + virtual void doStartUp() = 0; + + /** + * This is used to let the child class handle the transition from mode @c _MODE_SHUT_DOWN to @c _MODE_POWER_DOWN + * + * It is only called when the device handler is in mode @c _MODE_SHUT_DOWN. + * Device handler commands are read and can be handled by the child class. If the child class handles a command, it should also send + * an reply accordingly. + * If an Command is not handled (ie #DeviceHandlerCommand is not @c CMD_NONE, the base class handles rejecting the command and sends a reply. + * The replies for mode transitions are handled by the base class. + * + * If the device ready to be switched off, the mode should be set to _MODE_POWER_DOWN. + * If the device should not be switched off, the mode can be changed to _MODE_TO_ON (or MODE_ON if no transition is needed). + * If the device does not change the mode, the mode will be changed to _MODE_POWER_DOWN, when the timeout (from getTransitionDelay()) has passed. + * + * #transitionFailure can be set to a failure code indicating the reason for a failed transition + */ + virtual void doShutDown() = 0; + + /** + * Build the device command to send for normal mode. + * + * This is only called in @c MODE_NORMAL. If multiple submodes for @c MODE_NORMAL are supported, + * different commands can built returned depending on the submode. + * + * #rawPacket and #rawPacketLen must be set by this method to the packet to be sent. + * + * @param[out] id the device command id that has been built + * @return + * - @c RETURN_OK when a command is to be sent + * - not @c RETURN_OK when no command is to be sent + */ + virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) = 0; + + /** + * Build the device command to send for a transitional mode. + * + * This is only called in @c _MODE_TO_NORMAL, @c _MODE_TO_ON, @c _MODE_TO_RAW, + * @c _MODE_START_UP and @c _MODE_TO_POWER_DOWN. So it is used by doStartUp() and doShutDown() as well as doTransition() + * + * A good idea is to implement a flag indicating a command has to be built and a variable containing the command number to be built + * and filling them in doStartUp(), doShutDown() and doTransition() so no modes have to be checked here. + * + * #rawPacket and #rawPacketLen must be set by this method to the packet to be sent. + * + * @param[out] id the device command id built + * @return + * - @c RETURN_OK when a command is to be sent + * - not @c RETURN_OK when no command is to be sent + */ + virtual ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) = 0; + + /** + * Build a device command packet from data supplied by a direct command. + * + * #rawPacket and #rawPacketLen should be set by this method to the packet to be sent. + * + * @param deviceCommand the command to build, already checked against deviceCommandMap + * @param commandData pointer to the data from the direct command + * @param commandDataLen length of commandData + * @return + * - @c RETURN_OK when #rawPacket is valid + * - @c RETURN_FAILED when #rawPacket is invalid and no data should be sent + */ + virtual ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, + const uint8_t * commandData, size_t commandDataLen) = 0; + + /** + * @brief fill the #deviceCommandMap + * called by the initialize() of the base class + * @details + * This is used to let the base class know which replies are expected. + * There are different scenarios regarding this: + * - "Normal" commands. These are commands, that trigger a direct reply from the device. + * In this case, the id of the command should be added to the command map + * with a commandData_t where maxDelayCycles is set to the maximum expected + * number of PST cycles the reply will take. Then, scanForReply returns + * the id of the command and the base class can handle time-out and missing replies. + * - Periodic, unrequested replies. These are replies that, once enabled, are sent by the device + * on its own in a defined interval. In this case, the id of the reply + * or a placeholder id should be added to the deviceCommandMap with a commandData_t + * where maxDelayCycles is set to the maximum expected number of PST cycles between + * two replies (also a tolerance should be added, as an FDIR message will be generated if it is missed). + * As soon as the replies are enabled, DeviceCommandInfo.periodic must be set to 1, + * DeviceCommandInfo.delayCycles to DeviceCommandInfo.MaxDelayCycles. + * From then on, the base class handles the reception. + * Then, scanForReply returns the id of the reply or the placeholder id and the base class will + * take care of checking that all replies are received and the interval is correct. + * When the replies are disabled, DeviceCommandInfo.periodic must be set to 0, + * DeviceCommandInfo.delayCycles to 0; + * - Aperiodic, unrequested replies. These are replies that are sent + * by the device without any preceding command and not in a defined interval. + * These are not entered in the deviceCommandMap but handled by returning @c APERIODIC_REPLY in scanForReply(). + * + */ + virtual void fillCommandAndReplyMap() = 0; + + /** + * @brief Scans a buffer for a valid reply. + * @details + * This is used by the base class to check the data received for valid packets. + * It only checks if a valid packet starts at @c start. + * It also only checks the structural validy of the packet, eg checksums lengths and protocol data. + * No information check is done, e.g. range checks etc. + * + * Errors should be reported directly, the base class does NOT report any errors based on the return + * value of this function. + * + * @param start start of remaining buffer to be scanned + * @param len length of remaining buffer to be scanned + * @param[out] foundId the id of the data found in the buffer. + * @param[out] foundLen length of the data found. Is to be set in function, buffer is scanned at previous position + foundLen. + * @return + * - @c RETURN_OK a valid packet was found at @c start, @c foundLen is valid + * - @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 DeviceHandlerIF::IGNORE_REPLY_DATA Ignore this specific part of the packet + * - @c DeviceHandlerIF::IGNORE_FULL_PACKET Ignore the packet + * - @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, + DeviceCommandId_t *foundId, uint32_t *foundLen) = 0; + + /** + * @brief Interpret a reply from the device. + * @details + * This is called after scanForReply() found a valid packet, it can be assumed that the length and structure is valid. + * This routine extracts the data from the packet into a DataSet and then calls handleDeviceTM(), which either sends + * a TM packet or stores the data in the DataPool depending on whether the it was an external command. + * No packet length is given, as it should be defined implicitly by the id. + * + * @param id the id found by scanForReply() + * @param packet + * @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 + */ + virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, + const uint8_t *packet) = 0; + + /** + * @brief Can be implemented by child handler to + * perform debugging + * @details Example: Calling this in performOperation + * to track values like mode. + * @param positionTracker Provide the child handler a way to know where the debugInterface was called + * @param objectId Provide the child handler object Id to specify actions for spefic devices + * @param parameter Supply a parameter of interest + * Please delete all debugInterface calls in DHB after debugging is finished ! + */ + virtual void debugInterface(uint8_t positionTracker = 0, object_id_t objectId = 0, uint32_t parameter = 0); + + /** + * Get the time needed to transit from modeFrom to modeTo. + * + * Used for the following transitions: + * modeFrom -> modeTo: + * - MODE_ON -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] + * - MODE_NORMAL -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] + * - MODE_RAW -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] + * - _MODE_START_UP -> MODE_ON (do not include time to set the switches, the base class got you covered) + * + * The default implementation returns 0 ! + * @param modeFrom + * @param modeTo + * @return time in ms + */ + virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo); + + /** + * Return the switches connected to the device. + * + * The default implementation returns one switch set in the ctor. + * + * @param[out] switches pointer to an array of switches + * @param[out] numberOfSwitches length of returned array + * @return + * - @c RETURN_OK if the parameters were set + * - @c RETURN_FAILED if no switches exist + */ + virtual ReturnValue_t getSwitches(const uint8_t **switches, + uint8_t *numberOfSwitches); + +public: + /** + * @param parentQueueId + */ + virtual void setParentQueue(MessageQueueId_t parentQueueId); ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size); @@ -136,6 +367,8 @@ public: * @param task_ Pointer to the taskIF of this task */ virtual void setTaskIF(PeriodicTaskIF* task_); + virtual MessageQueueId_t getCommandQueue(void) const; + protected: /** * The Returnvalues id of this class, required by HasReturnvaluesIF @@ -143,8 +376,9 @@ 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 IGNORE_REPLY_DATA = MAKE_RETURN_CODE(6); + 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); //!< Ignore parts of the received packet + static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE(7); //!< Ignore full received packet // static const ReturnValue_t ONE_SWITCH = MAKE_RETURN_CODE(8); // static const ReturnValue_t TWO_SWITCHES = MAKE_RETURN_CODE(9); static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(10); @@ -318,9 +552,10 @@ protected: uint32_t parameter = 0); /** - * - - * @param parameter2 additional parameter + * Send reply to a command, differentiate between raw command + * and normal command. + * @param status + * @param parameter */ void replyToCommand(ReturnValue_t status, uint32_t parameter = 0); @@ -345,41 +580,6 @@ protected: */ void setMode(Mode_t newMode, Submode_t submode); - /** - * This is used to let the child class handle the transition from mode @c _MODE_START_UP to @c MODE_ON - * - * It is only called when the device handler is in mode @c _MODE_START_UP. That means, the device switch(es) are already set to on. - * Device handler commands are read and can be handled by the child class. If the child class handles a command, it should also send - * an reply accordingly. - * If an Command is not handled (ie #DeviceHandlerCommand is not @c CMD_NONE, the base class handles rejecting the command and sends a reply. - * The replies for mode transitions are handled by the base class. - * - * If the device is started and ready for operation, the mode should be set to MODE_ON. It is possible to set the mode to _MODE_TO_ON to - * use the to on transition if available. - * If the power-up fails, the mode should be set to _MODE_POWER_DOWN which will lead to the device being powered off. - * If the device does not change the mode, the mode will be changed to _MODE_POWER_DOWN, after the timeout (from getTransitionDelay()) has passed. - * - * #transitionFailure can be set to a failure code indicating the reason for a failed transition - */ - virtual void doStartUp() = 0; - - /** - * This is used to let the child class handle the transition from mode @c _MODE_SHUT_DOWN to @c _MODE_POWER_DOWN - * - * It is only called when the device handler is in mode @c _MODE_SHUT_DOWN. - * Device handler commands are read and can be handled by the child class. If the child class handles a command, it should also send - * an reply accordingly. - * If an Command is not handled (ie #DeviceHandlerCommand is not @c CMD_NONE, the base class handles rejecting the command and sends a reply. - * The replies for mode transitions are handled by the base class. - * - * If the device ready to be switched off, the mode should be set to _MODE_POWER_DOWN. - * If the device should not be switched off, the mode can be changed to _MODE_TO_ON (or MODE_ON if no transition is needed). - * If the device does not change the mode, the mode will be changed to _MODE_POWER_DOWN, when the timeout (from getTransitionDelay()) has passed. - * - * #transitionFailure can be set to a failure code indicating the reason for a failed transition - */ - virtual void doShutDown() = 0; - /** * Do the transition to the main modes (MODE_ON, MODE_NORMAL and MODE_RAW). * @@ -409,24 +609,6 @@ protected: */ virtual void doTransition(Mode_t modeFrom, Submode_t subModeFrom); - /** - * Get the time needed to transit from modeFrom to modeTo. - * - * Used for the following transitions: - * modeFrom -> modeTo: - * MODE_ON -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] - * MODE_NORMAL -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] - * MODE_RAW -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] - * _MODE_START_UP -> MODE_ON (do not include time to set the switches, the base class got you covered) - * - * The default implementation returns 0; - * - * @param modeFrom - * @param modeTo - * @return time in ms - */ - virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo); - /** * Is the combination of mode and submode valid? * @@ -448,40 +630,6 @@ protected: */ virtual RmapAction_t getRmapAction(); - /** - * Build the device command to send for normal mode. - * - * This is only called in @c MODE_NORMAL. If multiple submodes for @c MODE_NORMAL are supported, - * different commands can built returned depending on the submode. - * - * #rawPacket and #rawPacketLen must be set by this method to the packet to be sent. - * - * @param[out] id the device command id that has been built - * @return - * - @c RETURN_OK when a command is to be sent - * - not @c RETURN_OK when no command is to be sent - */ - virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) = 0; - - /** - * Build the device command to send for a transitional mode. - * - * This is only called in @c _MODE_TO_NORMAL, @c _MODE_TO_ON, @c _MODE_TO_RAW, - * @c _MODE_START_UP and @c _MODE_TO_POWER_DOWN. So it is used by doStartUp() and doShutDown() as well as doTransition() - * - * A good idea is to implement a flag indicating a command has to be built and a variable containing the command number to be built - * and filling them in doStartUp(), doShutDown() and doTransition() so no modes have to be checked here. - * - * #rawPacket and #rawPacketLen must be set by this method to the packet to be sent. - * - * @param[out] id the device command id built - * @return - * - @c RETURN_OK when a command is to be sent - * - not @c RETURN_OK when no command is to be sent - */ - virtual ReturnValue_t buildTransitionDeviceCommand( - DeviceCommandId_t * id) = 0; - /** * Build the device command to send for raw mode. * @@ -502,40 +650,6 @@ protected: */ virtual ReturnValue_t buildChildRawCommand(); - /** - * Build a device command packet from data supplied by a direct command. - * - * #rawPacket and #rawPacketLen should be set by this method to the packet to be sent. - * - * @param deviceCommand the command to build, already checked against deviceCommandMap - * @param commandData pointer to the data from the direct command - * @param commandDataLen length of commandData - * @return - * - @c RETURN_OK when #rawPacket is valid - * - @c RETURN_FAILED when #rawPacket is invalid and no data should be sent - */ - virtual ReturnValue_t buildCommandFromCommand( - DeviceCommandId_t deviceCommand, const uint8_t * commandData, - size_t commandDataLen) = 0; - - /** - * fill the #deviceCommandMap - * - * called by the initialize() of the base class - * - * This is used to let the base class know which replies are expected. - * There are different scenarios regarding this: - * - "Normal" commands. These are commands, that trigger a direct reply from the device. In this case, the id of the command should be added to the command map - * with a commandData_t where maxDelayCycles is set to the maximum expected number of PST cycles the reply will take. Then, scanForReply returns the id of the command and the base class can handle time-out and missing replies. - * - Periodic, unrequested replies. These are replies that, once enabled, are sent by the device on its own in a defined interval. In this case, the id of the reply or a placeholder id should be added to the deviceCommandMap - * with a commandData_t where maxDelayCycles is set to the maximum expected number of PST cycles between two replies (also a tolerance should be added, as an FDIR message will be generated if it is missed). - * As soon as the replies are enabled, DeviceCommandInfo.periodic must be set to 1, DeviceCommandInfo.delayCycles to DeviceCommandInfo.MaxDelayCycles. From then on, the base class handles the reception. - * Then, scanForReply returns the id of the reply or the placeholder id and the base class will take care of checking that all replies are received and the interval is correct. - * When the replies are disabled, DeviceCommandInfo.periodic must be set to 0, DeviceCommandInfo.delayCycles to 0; - * - Aperiodic, unrequested replies. These are replies that are sent by the device without any preceding command and not in a defined interval. These are not entered in the deviceCommandMap but handled by returning @c APERIODIC_REPLY in scanForReply(). - * - */ - virtual void fillCommandAndReplyMap() = 0; /** * This is a helper method to facilitate inserting entries in the command map. @@ -583,48 +697,6 @@ protected: * @return The current delay count. If the command does not exist (should never happen) it returns 0. */ uint8_t getReplyDelayCycles(DeviceCommandId_t deviceCommand); - /** - * Scans a buffer for a valid reply. - * - * This is used by the base class to check the data received from the RMAP stack for valid packets. - * It only checks if a valid packet starts at @c start. - * It also only checks the structural validy of the packet, eg checksums lengths and protocol data. No - * information check is done, eg range checks etc. - * - * Errors should be reported directly, the base class does NOT report any errors based on the return - * value of this function. - * - * @param start start of data - * @param len length of data - * @param[out] foundId the id of the packet starting at @c start - * @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 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, - DeviceCommandId_t *foundId, uint32_t *foundLen) = 0; - - /** - * Interpret a reply from the device. - * - * This is called after scanForReply() found a valid packet, it can be assumed that the length and structure is valid. - * This routine extracts the data from the packet into a DataSet and then calls handleDeviceTM(), which either sends - * a TM packet or stores the data in the DataPool depending on whether the it was an external command. - * No packet length is given, as it should be defined implicitly by the id. - * - * @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 - */ - virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, - const uint8_t *packet) = 0; /** * Construct a command reply containing a raw reply. @@ -649,21 +721,6 @@ protected: */ void replyRawReplyIfnotWiretapped(const uint8_t *data, size_t len); - /** - * Return the switches connected to the device. - * - * The default implementation returns one switch set in the ctor. - * - * - * @param[out] switches pointer to an array of switches - * @param[out] numberOfSwitches length of returned array - * @return - * - @c RETURN_OK if the parameters were set - * - @c RETURN_FAILED if no switches exist - */ - virtual ReturnValue_t getSwitches(const uint8_t **switches, - uint8_t *numberOfSwitches); - /** * notify child about mode change */ @@ -671,7 +728,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 +793,11 @@ protected: */ virtual bool dontCheckQueue(); + /** + * Used to retrieve logical address + * @return logicalAddress + */ + virtual uint32_t getLogicalAddress(); Mode_t getBaseMode(Mode_t transitionMode); bool isAwaitingReply(); @@ -747,7 +810,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,6 +891,7 @@ protected: DeviceCommandMap deviceCommandMap; ActionHelper actionHelper; + private: /** @@ -862,9 +925,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. @@ -919,16 +982,12 @@ private: void buildRawDeviceCommand(CommandMessage* message); void buildInternalCommand(void); -// /** -// * Send a reply with the current mode and submode. -// */ -// void announceMode(void); - /** * Decrement the counter for the timout of replies. * * 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); @@ -1027,7 +1086,14 @@ private: */ ReturnValue_t switchCookieChannel(object_id_t newChannelId); + /** + * Handle device handler messages (e.g. commands sent by PUS Service 2) + * @param message + * @return + */ ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message); + + }; #endif /* DEVICEHANDLERBASE_H_ */ From 029b2133e6df5ecee9341226706ad6f8bcdf6b8b Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 23 Mar 2020 18:03:00 +0100 Subject: [PATCH 003/653] new adaptions for cookie + comIF changes hook for performOp() added --- devicehandlers/DeviceHandlerBase.cpp | 101 +++++++++-------- devicehandlers/DeviceHandlerBase.h | 164 ++++++++++++++++----------- 2 files changed, 151 insertions(+), 114 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index c4f7465d..5834db2f 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -16,37 +16,34 @@ object_id_t DeviceHandlerBase::powerSwitcherId = 0; object_id_t DeviceHandlerBase::rawDataReceiverId = 0; object_id_t DeviceHandlerBase::defaultFDIRParentId = 0; -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(), logicalAddress(logicalAddress_), - timeoutStart(0), childTransitionDelay(5000), transitionSourceMode(_MODE_POWER_DOWN), - transitionSourceSubMode(SUBMODE_NONE), deviceSwitch(setDeviceSwitch) +DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, address_t logicalAddress_, + object_id_t deviceCommunication, Cookie * cookie_, size_t maxReplyLen, + uint8_t setDeviceSwitch, uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, + FailureIsolationBase* fdirInstance, size_t cmdQueueSize) : + SystemObject(setObjectId), mode(MODE_OFF), submode(SUBMODE_NONE), + wiretappingMode(OFF), storedRawData(StorageManagerIF::INVALID_ADDRESS), + deviceCommunicationId(deviceCommunication), cookie(cookie_), + deviceThermalStatePoolId(thermalStatePoolId), deviceThermalRequestPoolId(thermalRequestPoolId), + healthHelper(this, setObjectId), modeHelper(this), parameterHelper(this), + fdirInstance(fdirInstance), hkSwitcher(this), + defaultFDIRUsed(fdirInstance == nullptr), switchOffWasReported(false), + executingTask(nullptr), actionHelper(this, nullptr), cookieInfo(), + logicalAddress(logicalAddress_), childTransitionDelay(5000), + transitionSourceMode(_MODE_POWER_DOWN), transitionSourceSubMode(SUBMODE_NONE), + deviceSwitch(setDeviceSwitch) { + this->cookie->setMaxReplyLen(maxReplyLen); commandQueue = QueueFactory::instance()-> createMessageQueue(cmdQueueSize, CommandMessage::MAX_MESSAGE_SIZE); cookieInfo.state = COOKIE_UNUSED; insertInCommandMap(RAW_COMMAND_ID); - if (this->fdirInstance == NULL) { + if (this->fdirInstance == nullptr) { this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, defaultFDIRParentId); } } DeviceHandlerBase::~DeviceHandlerBase() { - communicationInterface->close(cookie); if (defaultFDIRUsed) { delete fdirInstance; } @@ -63,10 +60,12 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { decrementDeviceReplyMap(); fdirInstance->checkForFailures(); hkSwitcher.performOperation(); + performOperationHook(); } if (mode == MODE_OFF) { return RETURN_OK; } + switch (getRmapAction()) { case SEND_WRITE: if ((cookieInfo.state == COOKIE_UNUSED)) { @@ -87,6 +86,7 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { default: break; } + return RETURN_OK; } @@ -102,11 +102,11 @@ ReturnValue_t DeviceHandlerBase::initialize() { return RETURN_FAILED; } - result = communicationInterface->open(&cookie, logicalAddress, - maxDeviceReplyLen); - if (result != RETURN_OK) { - return result; - } +// result = communicationInterface->open(&cookie, logicalAddress, +// maxDeviceReplyLen, comParameter1, comParameter2); +// if (result != RETURN_OK) { +// return result; +// } IPCStore = objectManager->get(objects::IPC_STORE); if (IPCStore == NULL) { @@ -166,7 +166,6 @@ ReturnValue_t DeviceHandlerBase::initialize() { mySet.commit(PoolVariableIF::VALID); return RETURN_OK; - } void DeviceHandlerBase::decrementDeviceReplyMap() { @@ -549,7 +548,7 @@ void DeviceHandlerBase::doGetWrite() { void DeviceHandlerBase::doSendRead() { ReturnValue_t result; - result = communicationInterface->requestReceiveMessage(cookie); + result = communicationInterface->requestReceiveMessage(cookie, requestLen); if (result == RETURN_OK) { cookieInfo.state = COOKIE_READ_SENT; } else { @@ -563,10 +562,10 @@ void DeviceHandlerBase::doSendRead() { } void DeviceHandlerBase::doGetRead() { - uint32_t receivedDataLen; + size_t receivedDataLen; uint8_t *receivedData; DeviceCommandId_t foundId = 0xFFFFFFFF; - uint32_t foundLen = 0; + size_t foundLen = 0; ReturnValue_t result; if (cookieInfo.state != COOKIE_READ_SENT) { @@ -637,8 +636,8 @@ void DeviceHandlerBase::doGetRead() { } ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, - uint8_t * *data, uint32_t * len) { - uint32_t lenTmp; + uint8_t ** data, size_t * len) { + size_t lenTmp; if (IPCStore == NULL) { *data = NULL; @@ -689,7 +688,7 @@ void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len, //Default child implementations -DeviceHandlerBase::RmapAction_t DeviceHandlerBase::getRmapAction() { +DeviceHandlerBase::CommunicationAction_t DeviceHandlerBase::getRmapAction() { switch (pstStep) { case 0: return SEND_WRITE; @@ -749,20 +748,20 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, } } -ReturnValue_t DeviceHandlerBase::switchCookieChannel(object_id_t newChannelId) { - DeviceCommunicationIF *newCommunication = objectManager->get< - DeviceCommunicationIF>(newChannelId); - - if (newCommunication != NULL) { - ReturnValue_t result = newCommunication->reOpen(cookie, logicalAddress, - maxDeviceReplyLen); - if (result != RETURN_OK) { - return result; - } - return RETURN_OK; - } - return RETURN_FAILED; -} +//ReturnValue_t DeviceHandlerBase::switchCookieChannel(object_id_t newChannelId) { +// DeviceCommunicationIF *newCommunication = objectManager->get< +// DeviceCommunicationIF>(newChannelId); +// +// if (newCommunication != NULL) { +// ReturnValue_t result = newCommunication->reOpen(cookie, logicalAddress, +// maxDeviceReplyLen, comParameter1, comParameter2); +// if (result != RETURN_OK) { +// return result; +// } +// return RETURN_OK; +// } +// return RETURN_FAILED; +//} void DeviceHandlerBase::buildRawDeviceCommand(CommandMessage* commandMessage) { storedRawData = DeviceHandlerMessage::getStoreAddress(commandMessage); @@ -1046,12 +1045,13 @@ ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage( } replyReturnvalueToCommand(RETURN_OK); return RETURN_OK; - case DeviceHandlerMessage::CMD_SWITCH_IOBOARD: + case DeviceHandlerMessage::CMD_SWITCH_ADDRESS: if (mode != MODE_OFF) { replyReturnvalueToCommand(WRONG_MODE_FOR_COMMAND); } else { - result = switchCookieChannel( - DeviceHandlerMessage::getIoBoardObjectId(message)); + // rework in progress + //result = switchCookieChannel( + // DeviceHandlerMessage::getIoBoardObjectId(message)); if (result == RETURN_OK) { replyReturnvalueToCommand(RETURN_OK); } else { @@ -1278,3 +1278,6 @@ void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t obje uint32_t DeviceHandlerBase::getLogicalAddress() { return logicalAddress; } + +void DeviceHandlerBase::performOperationHook() { +} diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index f16a4ff9..e9288921 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -18,9 +18,9 @@ #include #include #include -#include #include #include +#include namespace Factory{ void setStaticFrameworkObjectIds(); @@ -29,7 +29,7 @@ void setStaticFrameworkObjectIds(); class StorageManagerIF; /** - * \defgroup devices Devices + * @defgroup devices Devices * Contains all devices and the DeviceHandlerBase class. */ @@ -38,18 +38,20 @@ class StorageManagerIF; * @details * Documentation: Dissertation Baetz p.138,139, p.141-149 * - * It features handling of @link DeviceHandlerIF::Mode_t Modes @endlink, communication with - * physical devices, using the @link DeviceCommunicationIF @endlink, and communication with commanding objects. + * It features handling of @link DeviceHandlerIF::Mode_t Modes @endlink, + * communication with physical devices, using the @link DeviceCommunicationIF @endlink, + * and communication with commanding objects. * 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 (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. - * NOTE: RMAP is a standard which is used for FLP. + * 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. NOTE: RMAP is a 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. + * However, the communication principles are similar to RMAP as there are + * two write and two send calls involved. * * 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 @@ -83,7 +85,7 @@ public: * The constructor passes the objectId to the SystemObject(). * * @param setObjectId the ObjectId to pass to the SystemObject() Constructor - * @param maxDeviceReplyLen the length the RMAP getRead call will be sent with + * @param maxDeviceReplyLen the largest allowed reply size * @param setDeviceSwitch the switch the device is connected to, for devices using two switches, overwrite getSwitches() * @param deviceCommuncation Communcation Interface object which is used to implement communication functions * @param thermalStatePoolId @@ -91,12 +93,11 @@ public: * @param fdirInstance * @param cmdQueueSize */ - DeviceHandlerBase(uint32_t logicalAddress, object_id_t setObjectId, - uint32_t maxDeviceReplyLen, uint8_t setDeviceSwitch, - object_id_t deviceCommunication, - uint32_t thermalStatePoolId = PoolVariableIF::NO_PARAMETER, + DeviceHandlerBase(object_id_t setObjectId, address_t logicalAddress_, + object_id_t deviceCommunication, Cookie* cookie_, size_t maxReplyLen, + uint8_t setDeviceSwitch, uint32_t thermalStatePoolId = PoolVariableIF::NO_PARAMETER, uint32_t thermalRequestPoolId = PoolVariableIF::NO_PARAMETER, - FailureIsolationBase* fdirInstance = NULL, uint32_t cmdQueueSize = 20); + FailureIsolationBase* fdirInstance = nullptr, size_t cmdQueueSize = 20); /** * @brief This function is the device handler base core component and is called periodically. @@ -281,8 +282,8 @@ protected: * - @c DeviceHandlerIF::IGNORE_FULL_PACKET Ignore the packet * - @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, - DeviceCommandId_t *foundId, uint32_t *foundLen) = 0; + virtual ReturnValue_t scanForReply(const uint8_t *start, size_t len, + DeviceCommandId_t *foundId, size_t *foundLen) = 0; /** * @brief Interpret a reply from the device. @@ -301,6 +302,14 @@ protected: virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) = 0; + /** + * set all datapool variables that are update periodically in normal mode invalid + * + * Child classes should provide an implementation which sets all those variables invalid + * which are set periodically during any normal mode. + */ + virtual void setNormalDatapoolEntriesInvalid() = 0; + /** * @brief Can be implemented by child handler to * perform debugging @@ -344,6 +353,12 @@ protected: virtual ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches); + /** + * Can be used to perform device specific periodic operations. + * This is called on the SEND_READ step of the performOperation() call + */ + virtual void performOperationHook(); + public: /** * @param parentQueueId @@ -396,11 +411,32 @@ protected: /** * Pointer to the raw packet that will be sent. */ - uint8_t *rawPacket; + uint8_t *rawPacket = nullptr; /** * Size of the #rawPacket. */ - uint32_t rawPacketLen; + size_t rawPacketLen = 0; + + /** + * Size of data to request. + */ + size_t requestLen = 0; + +// /** +// * This union (or std::variant) type can be used to set comParameters which +// * are passed in the open() and reOpen() calls to the communication +// * interface +// * TODO: I don't know if we should use C++17 features but if we do we propably +// * should also write a function to get either a storeId handle +// * or an array handle so these values can be set conveniently. +// * The good think is that if there are many parameters, they can +// * be stored in the IPC pool. But maybe two uint32_t parameters are enough. +// * Simple = Good. It is downwards compatible and one can still store +// * 4 bytes of parameters AND a store ID. +// */ +// comParameters_t comParameters; + // uint32_t comParameter1 = 0; + // uint32_t comParameter2 = 0; /** * The mode the device handler is currently in. @@ -419,12 +455,12 @@ protected: /** * This is the counter value from performOperation(). */ - uint8_t pstStep; + uint8_t pstStep = 0; /** * This will be used in the RMAP getRead command as expected length, is set by the constructor, can be modiefied at will. */ - const uint32_t maxDeviceReplyLen; + const uint32_t maxDeviceReplyLen = 0; /** * wiretapping flag: @@ -442,7 +478,7 @@ protected: * 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 defaultRawReceiver; + MessageQueueId_t defaultRawReceiver = 0; store_address_t storedRawData; @@ -451,19 +487,19 @@ protected: * * if #isWiretappingActive all raw communication from and to the device will be sent to this queue */ - MessageQueueId_t requestedRawTraffic; + MessageQueueId_t requestedRawTraffic = 0; /** * the object used to set power switches */ - PowerSwitchIF *powerSwitcher; + PowerSwitchIF *powerSwitcher = nullptr; /** * Pointer to the IPCStore. * * This caches the pointer received from the objectManager in the constructor. */ - StorageManagerIF *IPCStore; + StorageManagerIF *IPCStore = nullptr; /** * cached for init @@ -473,17 +509,18 @@ protected: /** * Communication object used for device communication */ - DeviceCommunicationIF *communicationInterface; + DeviceCommunicationIF *communicationInterface = nullptr; /** - * Cookie used for communication + * Cookie used for communication. This is passed to the communication + * interface. */ Cookie *cookie; /** * The MessageQueue used to receive device handler commands and to send replies. */ - MessageQueueIF* commandQueue; + MessageQueueIF* commandQueue = nullptr; /** * this is the datapool variable with the thermal state of the device @@ -512,9 +549,9 @@ protected: * Optional Error code * Can be set in doStartUp(), doShutDown() and doTransition() to signal cause for Transition failure. */ - ReturnValue_t childTransitionFailure; + ReturnValue_t childTransitionFailure = RETURN_OK; - uint32_t ignoreMissedRepliesCount; //!< Counts if communication channel lost a reply, so some missed replys can be ignored. + uint32_t ignoreMissedRepliesCount = 0; //!< Counts if communication channel lost a reply, so some missed replys can be ignored. FailureIsolationBase* fdirInstance; //!< Pointer to the used FDIR instance. If not provided by child, default class is instantiated. @@ -531,6 +568,28 @@ protected: 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. + + /** + * Set the device handler mode + * + * Sets #timeoutStart with every call. + * + * Sets #transitionTargetMode if necessary so transitional states can be entered from everywhere without breaking the state machine + * (which relies on a correct #transitionTargetMode). + * + * The submode is left unchanged. + * + * + * @param newMode + */ + void setMode(Mode_t newMode); + + /** + * @overload + * @param submode + */ + void setMode(Mode_t newMode, Submode_t submode); + /** * Helper function to report a missed reply * @@ -559,27 +618,6 @@ protected: */ void replyToCommand(ReturnValue_t status, uint32_t parameter = 0); - /** - * Set the device handler mode - * - * Sets #timeoutStart with every call. - * - * Sets #transitionTargetMode if necessary so transitional states can be entered from everywhere without breaking the state machine - * (which relies on a correct #transitionTargetMode). - * - * The submode is left unchanged. - * - * - * @param newMode - */ - void setMode(Mode_t newMode); - - /** - * @overload - * @param submode - */ - void setMode(Mode_t newMode, Submode_t submode); - /** * Do the transition to the main modes (MODE_ON, MODE_NORMAL and MODE_RAW). * @@ -628,7 +666,7 @@ protected: * * @return The Rmap action to execute in this step */ - virtual RmapAction_t getRmapAction(); + virtual CommunicationAction_t getRmapAction(); /** * Build the device command to send for raw mode. @@ -655,8 +693,10 @@ protected: * This is a helper method to facilitate inserting entries in the command map. * @param deviceCommand Identifier of the command to add. * @param maxDelayCycles The maximum number of delay cycles the command waits until it times out. - * @param periodic Indicates if the command is periodic (i.e. it is sent by the device repeatedly without request) or not. + * @param periodic Indicates if the reply is periodic (i.e. it is sent by the device repeatedly without request) or not. * Default is aperiodic (0) + * @param hasDifferentReplyId + * @param replyId * @return RETURN_OK when the command was successfully inserted, COMMAND_MAP_ERROR else. */ ReturnValue_t insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, @@ -769,14 +809,6 @@ protected: */ ReturnValue_t getStateOfSwitches(void); - /** - * set all datapool variables that are update periodically in normal mode invalid - * - * Child classes should provide an implementation which sets all those variables invalid - * which are set periodically during any normal mode. - */ - virtual void setNormalDatapoolEntriesInvalid() = 0; - /** * build a list of sids and pass it to the #hkSwitcher */ @@ -897,7 +929,7 @@ private: /** * State a cookie is in. * - * Used to keep track of the state of the RMAP communication. + * Used to keep track of the state of the communication. */ enum CookieState_t { COOKIE_UNUSED, //!< The Cookie is unused @@ -934,7 +966,7 @@ private: * * Set when setMode() is called. */ - uint32_t timeoutStart; + uint32_t timeoutStart = 0; /** * Delay for the current mode transition, used for time out @@ -976,6 +1008,8 @@ private: * - checks whether commanded mode transitions are required and calls handleCommandedModeTransition() * - does the necessary action for the current mode or calls doChildStateMachine in modes @c MODE_TO_ON and @c MODE_TO_OFF * - actions that happen in transitions (eg setting a timeout) are handled in setMode() + * - Maybe export this into own class to increase modularity of software + * and reduce the massive class size ? */ void doStateMachine(void); @@ -1054,8 +1088,8 @@ private: * - @c RETURN_FAILED IPCStore is NULL * - the return value from the IPCStore if it was not @c RETURN_OK */ - ReturnValue_t getStorageData(store_address_t storageAddress, uint8_t **data, - uint32_t *len); + ReturnValue_t getStorageData(store_address_t storageAddress, + uint8_t ** data, size_t * len); /** * set all switches returned by getSwitches() @@ -1084,7 +1118,7 @@ private: * - @c RETURN_FAILED when cookies could not be changed, eg because the newChannel is not enabled * - @c returnvalues of RMAPChannelIF::isActive() */ - ReturnValue_t switchCookieChannel(object_id_t newChannelId); + //ReturnValue_t switchCookieChannel(object_id_t newChannelId); /** * Handle device handler messages (e.g. commands sent by PUS Service 2) From 59812199fdfe32ee3817a3a61de4834e1a4d4906 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 23 Mar 2020 19:16:01 +0100 Subject: [PATCH 004/653] new cookieIF --- devicehandlers/DeviceHandlerBase.cpp | 31 ++++++++++++++-------------- devicehandlers/DeviceHandlerBase.h | 29 +++++++------------------- 2 files changed, 23 insertions(+), 37 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 5834db2f..33e44146 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -16,23 +16,22 @@ object_id_t DeviceHandlerBase::powerSwitcherId = 0; object_id_t DeviceHandlerBase::rawDataReceiverId = 0; object_id_t DeviceHandlerBase::defaultFDIRParentId = 0; -DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, address_t logicalAddress_, - object_id_t deviceCommunication, Cookie * cookie_, size_t maxReplyLen, - uint8_t setDeviceSwitch, uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, +DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, + CookieIF * comCookie_, size_t maxReplyLen, uint8_t setDeviceSwitch, + uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, FailureIsolationBase* fdirInstance, size_t cmdQueueSize) : SystemObject(setObjectId), mode(MODE_OFF), submode(SUBMODE_NONE), wiretappingMode(OFF), storedRawData(StorageManagerIF::INVALID_ADDRESS), - deviceCommunicationId(deviceCommunication), cookie(cookie_), + deviceCommunicationId(deviceCommunication), comCookie(comCookie_), deviceThermalStatePoolId(thermalStatePoolId), deviceThermalRequestPoolId(thermalRequestPoolId), healthHelper(this, setObjectId), modeHelper(this), parameterHelper(this), fdirInstance(fdirInstance), hkSwitcher(this), defaultFDIRUsed(fdirInstance == nullptr), switchOffWasReported(false), executingTask(nullptr), actionHelper(this, nullptr), cookieInfo(), - logicalAddress(logicalAddress_), childTransitionDelay(5000), - transitionSourceMode(_MODE_POWER_DOWN), transitionSourceSubMode(SUBMODE_NONE), - deviceSwitch(setDeviceSwitch) + childTransitionDelay(5000), transitionSourceMode(_MODE_POWER_DOWN), + transitionSourceSubMode(SUBMODE_NONE), deviceSwitch(setDeviceSwitch) { - this->cookie->setMaxReplyLen(maxReplyLen); + this->comCookie->setMaxReplyLen(maxReplyLen); commandQueue = QueueFactory::instance()-> createMessageQueue(cmdQueueSize, CommandMessage::MAX_MESSAGE_SIZE); cookieInfo.state = COOKIE_UNUSED; @@ -44,6 +43,7 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, address_t logicalA } DeviceHandlerBase::~DeviceHandlerBase() { + delete comCookie; if (defaultFDIRUsed) { delete fdirInstance; } @@ -66,7 +66,7 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { return RETURN_OK; } - switch (getRmapAction()) { + switch (getComAction()) { case SEND_WRITE: if ((cookieInfo.state == COOKIE_UNUSED)) { buildInternalCommand(); @@ -506,7 +506,7 @@ void DeviceHandlerBase::replyToReply(DeviceReplyMap::iterator iter, void DeviceHandlerBase::doSendWrite() { if (cookieInfo.state == COOKIE_WRITE_READY) { - ReturnValue_t result = communicationInterface->sendMessage(cookie, + ReturnValue_t result = communicationInterface->sendMessage(comCookie, rawPacket, rawPacketLen); if (result == RETURN_OK) { @@ -527,7 +527,7 @@ void DeviceHandlerBase::doGetWrite() { return; } cookieInfo.state = COOKIE_UNUSED; - ReturnValue_t result = communicationInterface->getSendSuccess(cookie); + ReturnValue_t result = communicationInterface->getSendSuccess(comCookie); if (result == RETURN_OK) { if (wiretappingMode == RAW) { replyRawData(rawPacket, rawPacketLen, requestedRawTraffic, true); @@ -548,7 +548,7 @@ void DeviceHandlerBase::doGetWrite() { void DeviceHandlerBase::doSendRead() { ReturnValue_t result; - result = communicationInterface->requestReceiveMessage(cookie, requestLen); + result = communicationInterface->requestReceiveMessage(comCookie, requestLen); if (result == RETURN_OK) { cookieInfo.state = COOKIE_READ_SENT; } else { @@ -575,7 +575,7 @@ void DeviceHandlerBase::doGetRead() { cookieInfo.state = COOKIE_UNUSED; - result = communicationInterface->readReceivedMessage(cookie, &receivedData, + result = communicationInterface->readReceivedMessage(comCookie, &receivedData, &receivedDataLen); if (result != RETURN_OK) { @@ -688,7 +688,7 @@ void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len, //Default child implementations -DeviceHandlerBase::CommunicationAction_t DeviceHandlerBase::getRmapAction() { +DeviceHandlerBase::CommunicationAction_t DeviceHandlerBase::getComAction() { switch (pstStep) { case 0: return SEND_WRITE; @@ -1050,6 +1050,7 @@ ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage( replyReturnvalueToCommand(WRONG_MODE_FOR_COMMAND); } else { // rework in progress + result = RETURN_OK; //result = switchCookieChannel( // DeviceHandlerMessage::getIoBoardObjectId(message)); if (result == RETURN_OK) { @@ -1276,7 +1277,7 @@ void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t obje } uint32_t DeviceHandlerBase::getLogicalAddress() { - return logicalAddress; + return this->comCookie->getAddress(); } void DeviceHandlerBase::performOperationHook() { diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index e9288921..05be2d45 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -93,9 +94,9 @@ public: * @param fdirInstance * @param cmdQueueSize */ - DeviceHandlerBase(object_id_t setObjectId, address_t logicalAddress_, - object_id_t deviceCommunication, Cookie* cookie_, size_t maxReplyLen, - uint8_t setDeviceSwitch, uint32_t thermalStatePoolId = PoolVariableIF::NO_PARAMETER, + DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, + CookieIF * comCookie_, size_t maxReplyLen, uint8_t setDeviceSwitch, + uint32_t thermalStatePoolId = PoolVariableIF::NO_PARAMETER, uint32_t thermalRequestPoolId = PoolVariableIF::NO_PARAMETER, FailureIsolationBase* fdirInstance = nullptr, size_t cmdQueueSize = 20); @@ -422,22 +423,6 @@ protected: */ size_t requestLen = 0; -// /** -// * This union (or std::variant) type can be used to set comParameters which -// * are passed in the open() and reOpen() calls to the communication -// * interface -// * TODO: I don't know if we should use C++17 features but if we do we propably -// * should also write a function to get either a storeId handle -// * or an array handle so these values can be set conveniently. -// * The good think is that if there are many parameters, they can -// * be stored in the IPC pool. But maybe two uint32_t parameters are enough. -// * Simple = Good. It is downwards compatible and one can still store -// * 4 bytes of parameters AND a store ID. -// */ -// comParameters_t comParameters; - // uint32_t comParameter1 = 0; - // uint32_t comParameter2 = 0; - /** * The mode the device handler is currently in. * @@ -515,7 +500,7 @@ protected: * Cookie used for communication. This is passed to the communication * interface. */ - Cookie *cookie; + CookieIF *comCookie; /** * The MessageQueue used to receive device handler commands and to send replies. @@ -666,7 +651,7 @@ protected: * * @return The Rmap action to execute in this step */ - virtual CommunicationAction_t getRmapAction(); + virtual CommunicationAction_t getComAction(); /** * Build the device command to send for raw mode. @@ -959,7 +944,7 @@ private: /** * cached from ctor for initialize() */ - const uint32_t logicalAddress; + //const uint32_t logicalAddress = 0; /** * Used for timing out mode transitions. From ea4151455364c18ed1e791cee6ae001824aa74d5 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 23 Mar 2020 19:17:53 +0100 Subject: [PATCH 005/653] new cookie.cpp + cookieIF.h --- devicehandlers/Cookie.cpp | 26 ++++++++++++++++++++++++++ devicehandlers/CookieIF.h | 25 +++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 devicehandlers/Cookie.cpp create mode 100644 devicehandlers/CookieIF.h diff --git a/devicehandlers/Cookie.cpp b/devicehandlers/Cookie.cpp new file mode 100644 index 00000000..05b9425c --- /dev/null +++ b/devicehandlers/Cookie.cpp @@ -0,0 +1,26 @@ +/** + * @file Cookie.cpp + * + * @date 23.03.2020 + */ +#include + +Cookie::Cookie(address_t logicalAddress_): logicalAddress(logicalAddress_) { +} + +void Cookie::setAddress(address_t logicalAddress_) { + logicalAddress = logicalAddress_; +} +void Cookie::setMaxReplyLen(size_t maxReplyLen_) { + maxReplyLen = maxReplyLen_; +} + +address_t Cookie::getAddress() const { + return logicalAddress; +} + +size_t Cookie::getMaxReplyLen() const { + return maxReplyLen; +} + + diff --git a/devicehandlers/CookieIF.h b/devicehandlers/CookieIF.h new file mode 100644 index 00000000..d8781cd7 --- /dev/null +++ b/devicehandlers/CookieIF.h @@ -0,0 +1,25 @@ +/** + * @file CookieIF.h + * + * @date 23.03.2020 + */ + +#ifndef FRAMEWORK_DEVICEHANDLERS_COOKIEIF_H_ +#define FRAMEWORK_DEVICEHANDLERS_COOKIEIF_H_ +#include + +class CookieIF { +public: + /** + * Default empty virtual destructor. + */ + virtual ~CookieIF() {}; + + virtual void setAddress(address_t logicalAddress_) = 0; + virtual address_t getAddress() const = 0; + + virtual void setMaxReplyLen(size_t maxReplyLen_) = 0; + virtual size_t getMaxReplyLen() const = 0; +}; + +#endif /* FRAMEWORK_DEVICEHANDLERS_COOKIEIF_H_ */ From bfb0234d4134097db7e4db9e251d21989b894b32 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 24 Mar 2020 15:59:08 +0100 Subject: [PATCH 006/653] more refactoring --- devicehandlers/DeviceCommunicationIF.h | 121 +++++++++++++------ devicehandlers/DeviceHandlerBase.cpp | 31 +++-- devicehandlers/DeviceHandlerBase.h | 59 ++++++---- devicehandlers/DeviceHandlerIF.h | 157 ++++++++++++++----------- 4 files changed, 225 insertions(+), 143 deletions(-) diff --git a/devicehandlers/DeviceCommunicationIF.h b/devicehandlers/DeviceCommunicationIF.h index e0aca573..931fc8b5 100644 --- a/devicehandlers/DeviceCommunicationIF.h +++ b/devicehandlers/DeviceCommunicationIF.h @@ -2,62 +2,107 @@ #define DEVICECOMMUNICATIONIF_H_ #include +#include #include +/** + * @defgroup interfaces Interfaces + * @brief Interfaces for flight software objects + */ +/** + * @defgroup communication comm + * @brief Communication software components. + */ + +/** + * @brief This is an interface to decouple device communication from + * the device handler to allow reuse of these components. + * @details + * Documentation: Dissertation Baetz p.138 + * 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. + * The CommunicationMessage message type can be used to extend the functionality of the + * ComIF if a separate polling task is required. + * @ingroup interfaces + * @ingroup comm + */ class DeviceCommunicationIF: public HasReturnvaluesIF { public: 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); - static const ReturnValue_t INVALID_ADDRESS = MAKE_RETURN_CODE(0x03); - static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x04); - static const ReturnValue_t NULLPOINTER = MAKE_RETURN_CODE(0x05); - static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0x06); - static const ReturnValue_t CANT_CHANGE_REPLY_LEN = MAKE_RETURN_CODE(0x07); + static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x03); + static const ReturnValue_t NULLPOINTER = MAKE_RETURN_CODE(0x04); + static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0x05); - virtual ~DeviceCommunicationIF() { - - } - - virtual ReturnValue_t open(Cookie **cookie, uint32_t address, - uint32_t maxReplyLen) = 0; + virtual ~DeviceCommunicationIF() {} /** - * Use an existing cookie to open a connection to a new DeviceCommunication. - * The previous connection must not be closed. - * If the returnvalue is not RETURN_OK, the cookie is unchanged and - * can be used with the previous connection. - * + * @brief Device specific initialization, using the cookie. + * @details + * The cookie is already prepared in the factory. If the communication + * interface needs to be set up in some way and requires cookie information, + * this can be performed in this function, which is called on device handler + * initialization. * @param cookie - * @param address - * @param maxReplyLen * @return */ - virtual ReturnValue_t reOpen(Cookie *cookie, uint32_t address, - uint32_t maxReplyLen) = 0; + virtual ReturnValue_t initializeInterface(CookieIF * cookie) = 0; - virtual void close(Cookie *cookie) = 0; + /** + * 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 -@c RETURN_OK for successfull send + * - Everything else triggers sending failed event with + * returnvalue as parameter 1 + */ + virtual ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t * sendData, + size_t sendLen) = 0; - //SHOULDDO can data be const? - virtual ReturnValue_t sendMessage(Cookie *cookie, uint8_t *data, - uint32_t len) = 0; + /** + * Called by DHB in the GET_WRITE doGetWrite(). + * Get send confirmation that the data in sendMessage() was sent successfully. + * @param cookie + * @return -@c RETURN_OK if data was sent successfull + * - Everything else triggers sending failed event with + * returnvalue as parameter 1 + */ + virtual ReturnValue_t getSendSuccess(CookieIF *cookie) = 0; - virtual ReturnValue_t getSendSuccess(Cookie *cookie) = 0; - - virtual ReturnValue_t requestReceiveMessage(Cookie *cookie) = 0; - - virtual ReturnValue_t readReceivedMessage(Cookie *cookie, uint8_t **buffer, - uint32_t *size) = 0; - - virtual ReturnValue_t setAddress(Cookie *cookie, uint32_t address) = 0; - - virtual uint32_t getAddress(Cookie *cookie) = 0; - - virtual ReturnValue_t setParameter(Cookie *cookie, uint32_t parameter) = 0; - - virtual uint32_t getParameter(Cookie *cookie) = 0; + /** + * Called by DHB in the SEND_WRITE doSendRead(). + * Request a reply. + * @param cookie + * @return + */ + virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie, size_t requestLen) = 0; + /** + * Called by DHB in the GET_WRITE 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 @c RETURN_OK for successfull receive + * - Everything else triggers receiving failed with + * returnvalue as parameter 1 + */ + virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, + size_t *size) = 0; }; #endif /* DEVICECOMMUNICATIONIF_H_ */ diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 33e44146..ad699508 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -102,11 +102,10 @@ ReturnValue_t DeviceHandlerBase::initialize() { return RETURN_FAILED; } -// result = communicationInterface->open(&cookie, logicalAddress, -// maxDeviceReplyLen, comParameter1, comParameter2); -// if (result != RETURN_OK) { -// return result; -// } + result = communicationInterface->initializeInterface(comCookie); + if (result != RETURN_OK) { + return result; + } IPCStore = objectManager->get(objects::IPC_STORE); if (IPCStore == NULL) { @@ -811,9 +810,9 @@ ReturnValue_t DeviceHandlerBase::enableReplyInReplyMap( iter = deviceReplyMap.find(command->first); } if (iter != deviceReplyMap.end()) { - DeviceReplyInfo *info = &(iter->second); - info->delayCycles = info->maxDelayCycles; - info->command = command; + DeviceReplyInfo & info = iter->second; + info.delayCycles = info.maxDelayCycles; + info.command = command; command->second.expectedReplies = expectedReplies; return RETURN_OK; } else { @@ -1056,7 +1055,7 @@ ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage( if (result == RETURN_OK) { replyReturnvalueToCommand(RETURN_OK); } else { - replyReturnvalueToCommand(CANT_SWITCH_IOBOARD); + replyReturnvalueToCommand(CANT_SWITCH_ADDRESS); } } return RETURN_OK; @@ -1138,11 +1137,15 @@ void DeviceHandlerBase::handleDeviceTM(SerializeIF* data, } ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId, - MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size) { + MessageQueueId_t commandedBy, const uint8_t* data, size_t size) { ReturnValue_t result = acceptExternalDeviceCommands(); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } + if(size == 0) { + return NO_COMMAND_DATA; + } + DeviceCommandMap::iterator iter = deviceCommandMap.find(actionId); if (iter == deviceCommandMap.end()) { result = COMMAND_NOT_SUPPORTED; @@ -1161,7 +1164,7 @@ ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId, } void DeviceHandlerBase::buildInternalCommand(void) { -//Neither Raw nor Direct could build a command + // Neither Raw nor Direct could build a command ReturnValue_t result = NOTHING_TO_SEND; DeviceCommandId_t deviceCommandId = NO_COMMAND_ID; if (mode == MODE_NORMAL) { @@ -1179,12 +1182,13 @@ void DeviceHandlerBase::buildInternalCommand(void) { } else { return; } + if (result == NOTHING_TO_SEND) { return; } if (result == RETURN_OK) { - DeviceCommandMap::iterator iter = deviceCommandMap.find( - deviceCommandId); + DeviceCommandMap::iterator iter = + deviceCommandMap.find(deviceCommandId); if (iter == deviceCommandMap.end()) { result = COMMAND_NOT_SUPPORTED; } else if (iter->second.isExecuting) { @@ -1199,6 +1203,7 @@ void DeviceHandlerBase::buildInternalCommand(void) { cookieInfo.state = COOKIE_WRITE_READY; } } + if (result != RETURN_OK) { triggerEvent(DEVICE_BUILDING_COMMAND_FAILED, result, deviceCommandId); } diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 05be2d45..dcca2cc4 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -69,6 +69,12 @@ class StorageManagerIF; * * Other important virtual methods with a default implementation * are the getTransitionDelayMs() function and the getSwitches() function. + * Please ensure that getSwitches() returns DeviceHandlerIF::NO_SWITCHES if + * power switches are not implemented yet. Otherwise, the device handler will + * not transition to MODE_ON, even if setMode(MODE_ON) is called. + * If a transition to MODE_ON is desired without commanding, override the + * intialize() function and call setMode(_MODE_START_UP) before calling + * DeviceHandlerBase::initialize(). * * @ingroup devices */ @@ -191,8 +197,9 @@ protected: * * @param[out] id the device command id that has been built * @return - * - @c RETURN_OK when a command is to be sent - * - not @c RETURN_OK when no command is to be sent + * - @c RETURN_OK to send command after setting #rawPacket and #rawPacketLen. + * - @c NOTHING_TO_SEND when no command is to be sent. + * - Anything else triggers an even with the returnvalue as a parameter. */ virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) = 0; @@ -210,21 +217,25 @@ protected: * @param[out] id the device command id built * @return * - @c RETURN_OK when a command is to be sent - * - not @c RETURN_OK when no command is to be sent + * - @c NOTHING_TO_SEND when no command is to be sent + * - Anything else triggers an even with the returnvalue as a parameter */ virtual ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) = 0; /** - * Build a device command packet from data supplied by a direct command. + * @brief Build a device command packet from data supplied by a direct command. * + * @details * #rawPacket and #rawPacketLen should be set by this method to the packet to be sent. + * The existence of the command in the command map and the command size check + * against 0 are done by the base class. * * @param deviceCommand the command to build, already checked against deviceCommandMap * @param commandData pointer to the data from the direct command * @param commandDataLen length of commandData * @return - * - @c RETURN_OK when #rawPacket is valid - * - @c RETURN_FAILED when #rawPacket is invalid and no data should be sent + * - @c RETURN_OK to send command after #rawPacket and #rawPacketLen have been set. + * - Anything else triggers an event with the returnvalue as a parameter */ virtual ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t * commandData, size_t commandDataLen) = 0; @@ -349,7 +360,7 @@ protected: * @param[out] numberOfSwitches length of returned array * @return * - @c RETURN_OK if the parameters were set - * - @c RETURN_FAILED if no switches exist + * - @c NO_SWITCH or any other returnvalue if no switches exist */ virtual ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches); @@ -360,14 +371,29 @@ protected: */ virtual void performOperationHook(); + /** + * The Returnvalues id of this class, required by HasReturnvaluesIF + */ + static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE; + public: /** * @param parentQueueId */ virtual void setParentQueue(MessageQueueId_t parentQueueId); + /** + * This function call handles the execution of external commands as required + * by the HasActionIF. + * @param actionId + * @param commandedBy + * @param data + * @param size + * @return + */ ReturnValue_t executeAction(ActionId_t actionId, - MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size); + MessageQueueId_t commandedBy, const uint8_t* data, size_t size); + Mode_t getTransitionSourceMode() const; Submode_t getTransitionSourceSubMode() const; virtual void getMode(Mode_t *mode, Submode_t *submode); @@ -386,21 +412,6 @@ public: virtual MessageQueueId_t getCommandQueue(void) const; protected: - /** - * The Returnvalues id of this class, required by HasReturnvaluesIF - */ - 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); //!< 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); //!< Ignore parts of the received packet - static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE(7); //!< Ignore full received packet -// static const ReturnValue_t ONE_SWITCH = MAKE_RETURN_CODE(8); -// static const ReturnValue_t TWO_SWITCHES = MAKE_RETURN_CODE(9); - static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(10); - static const ReturnValue_t COMMAND_MAP_ERROR = MAKE_RETURN_CODE(11); - static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(12); - //Mode handling error Codes static const ReturnValue_t CHILD_TIMEOUT = MAKE_RETURN_CODE(0xE1); static const ReturnValue_t SWITCH_FAILED = MAKE_RETURN_CODE(0xE2); @@ -453,7 +464,7 @@ protected: * indicates either that all raw messages to and from the device should be sent to #theOneWhoWantsToReadRawTraffic * or that all device TM should be downlinked to #theOneWhoWantsToReadRawTraffic */ - enum WiretappingMode { + enum WiretappingMode: uint8_t { OFF = 0, RAW = 1, TM = 2 } wiretappingMode; diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index fe0ee8e8..5ea527e9 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -8,7 +8,13 @@ #include /** - * This is the Interface used to communicate with a device handler. + * @brief Physical address type + */ +typedef uint32_t address_t; + +/** + * @brief This is the Interface used to communicate with a device handler. + * @details Includes all expected return values, events and modes. * */ class DeviceHandlerIF { @@ -22,80 +28,95 @@ 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. - static const Mode_t MODE_RAW = 3; //!< The device is powered on and ready to perform operations. In this mode, raw commands can be sent. The device handler will send all replies received from the command back to the commanding object. - 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_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 - static const Mode_t _MODE_POWER_ON = TRANSITION_MODE_BASE_ACTION_MASK | 2; //!< This is a transitional state which can not be commanded. The device will be switched on in this state. After the command to set the switch on has been sent, the mode changes to @c MODE_WAIT_ON - static const Mode_t _MODE_WAIT_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 3; //!< This is a transitional state which can not be commanded. The switch has been commanded off and the handler waits for it to be off. When the switch is off, the mode changes to @c MODE_OFF. - static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4; //!< This is a transitional state which can not be commanded. The switch has been commanded on and the handler waits for it to be on. When the switch is on, the mode changes to @c MODE_TO_ON. - static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5; //!< This is a transitional state which can not be commanded. The switch has been commanded off and is off now. This state is only to do an RMAP cycle once more where the doSendRead() function will set the mode to MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board - static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CDH; - static const Event DEVICE_BUILDING_COMMAND_FAILED = MAKE_EVENT(0, SEVERITY::LOW); - static const Event DEVICE_SENDING_COMMAND_FAILED = MAKE_EVENT(1, SEVERITY::LOW); - static const Event DEVICE_REQUESTING_REPLY_FAILED = MAKE_EVENT(2, SEVERITY::LOW); - static const Event DEVICE_READING_REPLY_FAILED = MAKE_EVENT(3, SEVERITY::LOW); - static const Event DEVICE_INTERPRETING_REPLY_FAILED = MAKE_EVENT(4, SEVERITY::LOW); - static const Event DEVICE_MISSED_REPLY = MAKE_EVENT(5, SEVERITY::LOW); - static const Event DEVICE_UNKNOWN_REPLY = MAKE_EVENT(6, SEVERITY::LOW); - static const Event DEVICE_UNREQUESTED_REPLY = MAKE_EVENT(7, SEVERITY::LOW); - static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, SEVERITY::LOW); //!< Indicates a SW bug in child class. - static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, SEVERITY::LOW); - static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, SEVERITY::HIGH); + // 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. + static const Mode_t MODE_RAW = 3; //!< The device is powered on and ready to perform operations. In this mode, raw commands can be sent. The device handler will send all replies received from the command back to the commanding object. + 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; //!< 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 + static const Mode_t _MODE_POWER_ON = TRANSITION_MODE_BASE_ACTION_MASK | 2; //!< This is a transitional state which can not be commanded. The device will be switched on in this state. After the command to set the switch on has been sent, the mode changes to @c MODE_WAIT_ON + static const Mode_t _MODE_WAIT_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 3; //!< This is a transitional state which can not be commanded. The switch has been commanded off and the handler waits for it to be off. When the switch is off, the mode changes to @c MODE_OFF. + static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4; //!< This is a transitional state which can not be commanded. The switch has been commanded on and the handler waits for it to be on. When the switch is on, the mode changes to @c MODE_TO_ON. + static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5; //!< This is a transitional state which can not be commanded. The switch has been commanded off and is off now. This state is only to do an RMAP cycle once more where the doSendRead() function will set the mode to MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board - 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); - static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3); - static const ReturnValue_t CANT_SWITCH_IOBOARD = MAKE_RETURN_CODE(0xA4); - static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA5); - static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA6); - 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); + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CDH; + static const Event DEVICE_BUILDING_COMMAND_FAILED = MAKE_EVENT(0, SEVERITY::LOW); + static const Event DEVICE_SENDING_COMMAND_FAILED = MAKE_EVENT(1, SEVERITY::LOW); + static const Event DEVICE_REQUESTING_REPLY_FAILED = MAKE_EVENT(2, SEVERITY::LOW); + static const Event DEVICE_READING_REPLY_FAILED = MAKE_EVENT(3, SEVERITY::LOW); + static const Event DEVICE_INTERPRETING_REPLY_FAILED = MAKE_EVENT(4, SEVERITY::LOW); + static const Event DEVICE_MISSED_REPLY = MAKE_EVENT(5, SEVERITY::LOW); + static const Event DEVICE_UNKNOWN_REPLY = MAKE_EVENT(6, SEVERITY::LOW); + static const Event DEVICE_UNREQUESTED_REPLY = MAKE_EVENT(7, SEVERITY::LOW); + static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, SEVERITY::LOW); //!< Indicates a SW bug in child class. + static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, SEVERITY::LOW); + static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, SEVERITY::HIGH); - //standard codes used in scan for reply - // static const ReturnValue_t TOO_SHORT = MAKE_RETURN_CODE(0xB1); - static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB2); - static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB3); - static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB4); - static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB5); + static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF; - //standard codes used in interpret device reply - static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC1); //the device reported, that it did not execute the command - static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC2); - static const ReturnValue_t UNKNOW_DEVICE_REPLY = MAKE_RETURN_CODE(0xC3); //the deviceCommandId reported by scanforReply is unknown - static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC4); //syntax etc is correct but still not ok, eg parameters where none are expected + // Standard codes used when building commands. + static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(0xA0); //!< Return this if no command sending in required + // Mostly used for internal handling. + static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA2); //!< If the command size is 0. Checked in DHB + static const ReturnValue_t NO_REPLY_EXPECTED = MAKE_RETURN_CODE(0xA3); //!< Used to indicate that this is a command-only command. + static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA4); //!< Command ID not in commandMap. Checked in DHB + static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA5); //!< Command was already executed. Checked in DHB + static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA6); + static const ReturnValue_t CANT_SWITCH_ADDRESS = MAKE_RETURN_CODE(0xA7); + static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA8); + static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA9); + static const ReturnValue_t BUSY = MAKE_RETURN_CODE(0xAA); + static const ReturnValue_t NON_OP_TEMPERATURE = MAKE_RETURN_CODE(0xAB); + static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xAC); - //Standard codes used in buildCommandFromCommand - static const ReturnValue_t INVALID_COMMAND_PARAMETER = MAKE_RETURN_CODE( - 0xD0); - static const ReturnValue_t INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS = - MAKE_RETURN_CODE(0xD1); + // Standard codes used in scanForReply + static const ReturnValue_t APERIODIC_REPLY = MAKE_RETURN_CODE(0xB1); //!< This is used to specify for replies from a device which are not replies to requests + static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB2); + static const ReturnValue_t IGNORE_REPLY_DATA = MAKE_RETURN_CODE(0xB3); //!< Ignore parts of the received packet + static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE(0xB4); //!< Ignore full received packet + static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB5); + static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB6); + static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB7); + + // Standard codes used in interpretDeviceReply + static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC1); //the device reported, that it did not execute the command + static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC2); + static const ReturnValue_t UNKNOW_DEVICE_REPLY = MAKE_RETURN_CODE(0xC3); //the deviceCommandId reported by scanforReply is unknown + static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC4); //syntax etc is correct but still not ok, eg parameters where none are expected + + // Standard codes used in buildCommandFromCommand + static const ReturnValue_t INVALID_COMMAND_PARAMETER = MAKE_RETURN_CODE(0xD0); + static const ReturnValue_t INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS = MAKE_RETURN_CODE(0xD1); + + // Standard codes used in getSwitches + static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(0xE1); //!< Return in getSwitches() to specify there are no switches + + // static const ReturnValue_t ONE_SWITCH = MAKE_RETURN_CODE(8); + // static const ReturnValue_t TWO_SWITCHES = MAKE_RETURN_CODE(9); + // where is this used? + // static const ReturnValue_t COMMAND_MAP_ERROR = MAKE_RETURN_CODE(11); + + /** + * Communication action that will be executed. + * + * This is used by the child class to tell the base class what to do. + */ + enum CommunicationAction_t: uint8_t { + SEND_WRITE,//!< Send write + GET_WRITE, //!< Get write + SEND_READ, //!< Send read + GET_READ, //!< Get read + NOTHING //!< Do nothing. + }; - /** - * 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 */ From ac4275ef05628a02185906811bec00297198982e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 27 Mar 2020 14:44:54 +0100 Subject: [PATCH 007/653] some minor changes --- devicehandlers/DeviceHandlerBase.cpp | 63 +++++----- devicehandlers/DeviceHandlerBase.h | 182 ++++++++++++++------------- devicehandlers/DeviceHandlerIF.h | 5 - 3 files changed, 131 insertions(+), 119 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index ad699508..8187ffde 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -332,55 +332,49 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode, } } -ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap( - DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, - uint8_t periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) { -//No need to check, as we may try to insert multiple times. +ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, + uint16_t maxDelayCycles, size_t replyLen, uint8_t periodic, + bool hasDifferentReplyId, DeviceCommandId_t replyId) { + //No need to check, as we may try to insert multiple times. insertInCommandMap(deviceCommand); if (hasDifferentReplyId) { - return insertInReplyMap(replyId, maxDelayCycles, periodic); + return insertInReplyMap(replyId, maxDelayCycles, replyLen, periodic); } else { - return insertInReplyMap(deviceCommand, maxDelayCycles, periodic); + return insertInReplyMap(deviceCommand, maxDelayCycles, replyLen, periodic); } } ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId, - uint16_t maxDelayCycles, uint8_t periodic) { + uint16_t maxDelayCycles, size_t replyLen, uint8_t periodic) { DeviceReplyInfo info; info.maxDelayCycles = maxDelayCycles; info.periodic = periodic; info.delayCycles = 0; + info.replyLen = replyLen; info.command = deviceCommandMap.end(); - std::pair::iterator, bool> returnValue; - returnValue = deviceReplyMap.insert( - std::pair(replyId, info)); - if (returnValue.second) { + std::pair result = deviceReplyMap.emplace(replyId, info); + if (result.second) { return RETURN_OK; } else { return RETURN_FAILED; } } -ReturnValue_t DeviceHandlerBase::insertInCommandMap( - DeviceCommandId_t deviceCommand) { +ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceCommand) { DeviceCommandInfo info; info.expectedReplies = 0; info.isExecuting = false; info.sendReplyTo = NO_COMMANDER; - std::pair::iterator, bool> returnValue; - returnValue = deviceCommandMap.insert( - std::pair(deviceCommand, - info)); - if (returnValue.second) { + std::pair result = deviceCommandMap.emplace(deviceCommand,info); + if (result.second) { return RETURN_OK; } else { return RETURN_FAILED; } } -ReturnValue_t DeviceHandlerBase::updateReplyMapEntry( - DeviceCommandId_t deviceReply, uint16_t delayCycles, - uint16_t maxDelayCycles, uint8_t periodic) { +ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply, + uint16_t delayCycles, uint16_t maxDelayCycles, uint8_t periodic) { std::map::iterator iter = deviceReplyMap.find(deviceReply); if (iter == deviceReplyMap.end()) { @@ -492,7 +486,7 @@ void DeviceHandlerBase::replyToReply(DeviceReplyMap::iterator iter, return; } //Check if more replies are expected. If so, do nothing. - DeviceCommandInfo* info = &(iter->second.command->second); + DeviceCommandInfo * info = &(iter->second.command->second); if (--info->expectedReplies == 0) { //Check if it was transition or internal command. Don't send any replies in that case. if (info->sendReplyTo != NO_COMMANDER) { @@ -547,10 +541,23 @@ void DeviceHandlerBase::doGetWrite() { void DeviceHandlerBase::doSendRead() { ReturnValue_t result; + + DeviceReplyIter iter = deviceReplyMap.find(cookieInfo.pendingCommand->first); + if(iter != deviceReplyMap.end()) { + requestLen = iter->second.replyLen; + } + else { + requestLen = comCookie->getMaxReplyLen(); + } + result = communicationInterface->requestReceiveMessage(comCookie, requestLen); if (result == RETURN_OK) { cookieInfo.state = COOKIE_READ_SENT; - } else { + } + else if(result == DeviceCommunicationIF::NO_READ_REQUEST) { + return; + } + 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. @@ -770,8 +777,8 @@ void DeviceHandlerBase::buildRawDeviceCommand(CommandMessage* commandMessage) { replyReturnvalueToCommand(result, RAW_COMMAND_ID); storedRawData.raw = StorageManagerIF::INVALID_ADDRESS; } else { - cookieInfo.pendingCommand = deviceCommandMap.find( - (DeviceCommandId_t) RAW_COMMAND_ID); + cookieInfo.pendingCommand = deviceCommandMap. + find((DeviceCommandId_t) RAW_COMMAND_ID); cookieInfo.pendingCommand->second.isExecuting = true; cookieInfo.state = COOKIE_WRITE_READY; } @@ -810,9 +817,9 @@ ReturnValue_t DeviceHandlerBase::enableReplyInReplyMap( iter = deviceReplyMap.find(command->first); } if (iter != deviceReplyMap.end()) { - DeviceReplyInfo & info = iter->second; - info.delayCycles = info.maxDelayCycles; - info.command = command; + DeviceReplyInfo * info = &(iter->second); + info->delayCycles = info->maxDelayCycles; + info->command = command; command->second.expectedReplies = expectedReplies; return RETURN_OK; } else { diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index dcca2cc4..129fb288 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -194,6 +194,9 @@ protected: * different commands can built returned depending on the submode. * * #rawPacket and #rawPacketLen must be set by this method to the packet to be sent. + * If variable command frequence is required, a counter can be used and + * the frequency in the reply map has to be set manually + * by calling updateReplyMap(). * * @param[out] id the device command id that has been built * @return @@ -275,26 +278,33 @@ protected: * @details * This is used by the base class to check the data received for valid packets. * It only checks if a valid packet starts at @c start. - * It also only checks the structural validy of the packet, eg checksums lengths and protocol data. + * It also only checks the structural validy of the packet, + * e.g. checksums lengths and protocol data. * No information check is done, e.g. range checks etc. * - * Errors should be reported directly, the base class does NOT report any errors based on the return - * value of this function. + * Errors should be reported directly, the base class does NOT report + * any errors based on the returnvalue of this function. * * @param start start of remaining buffer to be scanned * @param len length of remaining buffer to be scanned * @param[out] foundId the id of the data found in the buffer. - * @param[out] foundLen length of the data found. Is to be set in function, buffer is scanned at previous position + foundLen. + * @param[out] foundLen length of the data found. Is to be set in function, + * buffer is scanned at previous position + foundLen. * @return * - @c RETURN_OK a valid packet was found at @c start, @c foundLen is valid - * - @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 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, + * e.g. checksum error, implies @c foundLen is valid, can be used to skip some bytes * - @c DeviceHandlerIF::LENGTH_MISSMATCH @c len is invalid * - @c DeviceHandlerIF::IGNORE_REPLY_DATA Ignore this specific part of the packet * - @c DeviceHandlerIF::IGNORE_FULL_PACKET Ignore the packet - * - @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() ) + * - @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, size_t len, + virtual ReturnValue_t scanForReply(const uint8_t *start, size_t remainingSize, DeviceCommandId_t *foundId, size_t *foundLen) = 0; /** @@ -513,6 +523,31 @@ protected: */ CookieIF *comCookie; + struct DeviceCommandInfo { + bool isExecuting; //!< Indicates if the command is already executing. + 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. + }; + typedef std::map DeviceCommandMap; + typedef DeviceCommandMap::iterator DeviceCommandIter; + + /** + * @brief Information about expected replies + * + * This is used to keep track of pending replies + */ + struct DeviceReplyInfo { + uint16_t maxDelayCycles; //!< The maximum number of cycles the handler should wait for a reply to this command. + uint16_t delayCycles; //!< The currently remaining cycles the handler should wait for a reply, 0 means there is no reply expected + size_t replyLen = 0; //!< Expected size of the reply. + 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. + }; + + typedef std::map DeviceReplyMap; + typedef DeviceReplyMap::iterator DeviceReplyIter; + /** * The MessageQueue used to receive device handler commands and to send replies. */ @@ -643,6 +678,55 @@ protected: */ virtual void doTransition(Mode_t modeFrom, Submode_t subModeFrom); + /** + * This is a helper method to facilitate inserting entries in the command map. + * @param deviceCommand Identifier of the command to add. + * @param maxDelayCycles The maximum number of delay cycles the command waits until it times out. + * @param periodic Indicates if the reply is periodic (i.e. it is sent by the device repeatedly without request) or not. + * Default is aperiodic (0) + * @param hasDifferentReplyId + * @param replyId + * @return RETURN_OK when the command was successfully inserted, COMMAND_MAP_ERROR else. + */ + ReturnValue_t insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, + uint16_t maxDelayCycles, size_t replyLen = 0, uint8_t periodic = 0, + bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0); + /** + * This is a helper method to insert replies in the reply map. + * @param deviceCommand Identifier of the reply to add. + * @param maxDelayCycles The maximum number of delay cycles the reply waits until it times out. + * @param periodic Indicates if the command is periodic (i.e. it is sent by the device repeatedly without request) or not. + * Default is aperiodic (0) + * @return RETURN_OK when the command was successfully inserted, COMMAND_MAP_ERROR else. + */ + ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, + uint16_t maxDelayCycles, size_t replyLen = 0, uint8_t periodic = 0); + /** + * A simple command to add a command to the commandList. + * @param deviceCommand The command to add + * @return RETURN_OK if the command was successfully inserted, RETURN_FAILED else. + */ + ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand); + /** + * This is a helper method to facilitate updating entries in the reply map. + * @param deviceCommand Identifier of the reply to update. + * @param delayCycles The current number of delay cycles to wait. As stated in #fillCommandAndCookieMap, to disable periodic commands, this is set to zero. + * @param maxDelayCycles The maximum number of delay cycles the reply waits until it times out. By passing 0 the entry remains untouched. + * @param periodic Indicates if the command is periodic (i.e. it is sent by the device repeatedly without request) or not. + * Default is aperiodic (0). Warning: The setting always overrides the value that was entered in the map. + * @return RETURN_OK when the reply was successfully updated, COMMAND_MAP_ERROR else. + */ + ReturnValue_t updateReplyMapEntry(DeviceCommandId_t deviceReply, + uint16_t delayCycles, uint16_t maxDelayCycles, + uint8_t periodic = 0); + /** + * Returns the delay cycle count of a reply. + * A count != 0 indicates that the command is already executed. + * @param deviceCommand The command to look for + * @return The current delay count. If the command does not exist (should never happen) it returns 0. + */ + uint8_t getReplyDelayCycles(DeviceCommandId_t deviceCommand); + /** * Is the combination of mode and submode valid? * @@ -684,56 +768,6 @@ protected: */ virtual ReturnValue_t buildChildRawCommand(); - - /** - * This is a helper method to facilitate inserting entries in the command map. - * @param deviceCommand Identifier of the command to add. - * @param maxDelayCycles The maximum number of delay cycles the command waits until it times out. - * @param periodic Indicates if the reply is periodic (i.e. it is sent by the device repeatedly without request) or not. - * Default is aperiodic (0) - * @param hasDifferentReplyId - * @param replyId - * @return RETURN_OK when the command was successfully inserted, COMMAND_MAP_ERROR else. - */ - ReturnValue_t insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, - uint16_t maxDelayCycles, uint8_t periodic = 0, - bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0); - /** - * This is a helper method to insert replies in the reply map. - * @param deviceCommand Identifier of the reply to add. - * @param maxDelayCycles The maximum number of delay cycles the reply waits until it times out. - * @param periodic Indicates if the command is periodic (i.e. it is sent by the device repeatedly without request) or not. - * Default is aperiodic (0) - * @return RETURN_OK when the command was successfully inserted, COMMAND_MAP_ERROR else. - */ - ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, - uint16_t maxDelayCycles, uint8_t periodic = 0); - /** - * A simple command to add a command to the commandList. - * @param deviceCommand The command to add - * @return RETURN_OK if the command was successfully inserted, RETURN_FAILED else. - */ - ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand); - /** - * This is a helper method to facilitate updating entries in the reply map. - * @param deviceCommand Identifier of the reply to update. - * @param delayCycles The current number of delay cycles to wait. As stated in #fillCommandAndCookieMap, to disable periodic commands, this is set to zero. - * @param maxDelayCycles The maximum number of delay cycles the reply waits until it times out. By passing 0 the entry remains untouched. - * @param periodic Indicates if the command is periodic (i.e. it is sent by the device repeatedly without request) or not. - * Default is aperiodic (0). Warning: The setting always overrides the value that was entered in the map. - * @return RETURN_OK when the reply was successfully updated, COMMAND_MAP_ERROR else. - */ - ReturnValue_t updateReplyMapEntry(DeviceCommandId_t deviceReply, - uint16_t delayCycles, uint16_t maxDelayCycles, - uint8_t periodic = 0); - /** - * Returns the delay cycle count of a reply. - * A count != 0 indicates that the command is already executed. - * @param deviceCommand The command to look for - * @return The current delay count. If the command does not exist (should never happen) it returns 0. - */ - uint8_t getReplyDelayCycles(DeviceCommandId_t deviceCommand); - /** * Construct a command reply containing a raw reply. * @@ -762,14 +796,6 @@ protected: */ virtual void modeChanged(void); - struct DeviceCommandInfo { - bool isExecuting; //!< Indicates if the command is already executing. - 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. - }; - - typedef std::map DeviceCommandMap; /** * Enable the reply checking for a command * @@ -780,16 +806,16 @@ protected: * When found, copies maxDelayCycles to delayCycles in the reply information and sets the command to * expect one reply. * - * Can be overwritten by the child, if a command activates multiple replies or replyId differs from - * commandId. + * Can be overwritten by the child, if a command activates multiple replies + * or replyId differs from commandId. * Notes for child implementations: * - If the command was not found in the reply map, NO_REPLY_EXPECTED MUST be returned. * - A failure code may be returned if something went fundamentally wrong. * * @param deviceCommand * @return - RETURN_OK if a reply was activated. - * - NO_REPLY_EXPECTED if there was no reply found. This is not an error case as many commands - * do not expect a reply. + * - NO_REPLY_EXPECTED if there was no reply found. This is not an + * error case as many commands do not expect a reply. */ virtual ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator cmd, uint8_t expectedReplies = 1, bool useAlternateId = false, @@ -884,22 +910,6 @@ protected: bool commandIsExecuting(DeviceCommandId_t commandId); - /** - * Information about expected replies - * - * This is used to keep track of pending replies - */ - struct DeviceReplyInfo { - uint16_t maxDelayCycles; //!< The maximum number of cycles the handler should wait for a reply to this command. - uint16_t delayCycles; //!< The currently remaining cycles the handler should wait for a reply, 0 means there is no reply expected - 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. - */ - typedef std::map DeviceReplyMap; /** * This map is used to check and track correct reception of all replies. * diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index 5ea527e9..34aa4114 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -7,11 +7,6 @@ #include #include -/** - * @brief Physical address type - */ -typedef uint32_t address_t; - /** * @brief This is the Interface used to communicate with a device handler. * @details Includes all expected return values, events and modes. From 511c0db8c70e490b1a41800552e539add5147288 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 1 Apr 2020 12:43:53 +0200 Subject: [PATCH 008/653] Cookie -> CookieIF, DHB changes According to changes agreed on 01.04.2020, slight refactoring of DHB: requestLen is set to 0 if no respective reply is enabled --- devicehandlers/Cookie.cpp | 26 ------------ devicehandlers/Cookie.h | 10 ----- devicehandlers/CookieIF.h | 58 +++++++++++++++----------- devicehandlers/DeviceCommunicationIF.h | 43 +++++++++++-------- devicehandlers/DeviceHandlerBase.cpp | 31 +++++++------- devicehandlers/DeviceHandlerBase.h | 23 +--------- 6 files changed, 75 insertions(+), 116 deletions(-) delete mode 100644 devicehandlers/Cookie.cpp delete mode 100644 devicehandlers/Cookie.h diff --git a/devicehandlers/Cookie.cpp b/devicehandlers/Cookie.cpp deleted file mode 100644 index 05b9425c..00000000 --- a/devicehandlers/Cookie.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @file Cookie.cpp - * - * @date 23.03.2020 - */ -#include - -Cookie::Cookie(address_t logicalAddress_): logicalAddress(logicalAddress_) { -} - -void Cookie::setAddress(address_t logicalAddress_) { - logicalAddress = logicalAddress_; -} -void Cookie::setMaxReplyLen(size_t maxReplyLen_) { - maxReplyLen = maxReplyLen_; -} - -address_t Cookie::getAddress() const { - return logicalAddress; -} - -size_t Cookie::getMaxReplyLen() const { - return maxReplyLen; -} - - diff --git a/devicehandlers/Cookie.h b/devicehandlers/Cookie.h deleted file mode 100644 index 495c8c40..00000000 --- a/devicehandlers/Cookie.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef COOKIE_H_ -#define COOKIE_H_ - -class Cookie{ -public: - virtual ~Cookie(){} -}; - - -#endif /* COOKIE_H_ */ diff --git a/devicehandlers/CookieIF.h b/devicehandlers/CookieIF.h index d8781cd7..55fdb44b 100644 --- a/devicehandlers/CookieIF.h +++ b/devicehandlers/CookieIF.h @@ -1,25 +1,33 @@ -/** - * @file CookieIF.h - * - * @date 23.03.2020 - */ - -#ifndef FRAMEWORK_DEVICEHANDLERS_COOKIEIF_H_ -#define FRAMEWORK_DEVICEHANDLERS_COOKIEIF_H_ -#include - -class CookieIF { -public: - /** - * Default empty virtual destructor. - */ - virtual ~CookieIF() {}; - - virtual void setAddress(address_t logicalAddress_) = 0; - virtual address_t getAddress() const = 0; - - virtual void setMaxReplyLen(size_t maxReplyLen_) = 0; - virtual size_t getMaxReplyLen() const = 0; -}; - -#endif /* FRAMEWORK_DEVICEHANDLERS_COOKIEIF_H_ */ +#ifndef COOKIE_H_ +#define COOKIE_H_ +#include +#include + +/** + * @brief Physical address type + */ +typedef uint32_t address_t; + +/** + * @brief This datatype is used to identify different connection over a single interface + * (like RMAP or I2C) + * @details + * To use this class, implement a communication specific child cookie which + * inherits Cookie. Cookie instances are created in config/ Factory.cpp by calling + * CookieIF* childCookie = new ChildCookie(...). + * + * This cookie is then passed to the child device handlers, which stores the + * pointer and passes it to the communication interface functions. + * + * The cookie can be used to store all kinds of information + * about the communication, like slave addresses, communication status, + * communication parameters etc. + * + * @ingroup comm + */ +class CookieIF { +public: + virtual ~CookieIF() {}; +}; + +#endif /* COOKIE_H_ */ diff --git a/devicehandlers/DeviceCommunicationIF.h b/devicehandlers/DeviceCommunicationIF.h index 931fc8b5..657f7232 100644 --- a/devicehandlers/DeviceCommunicationIF.h +++ b/devicehandlers/DeviceCommunicationIF.h @@ -1,7 +1,7 @@ #ifndef DEVICECOMMUNICATIONIF_H_ #define DEVICECOMMUNICATIONIF_H_ -#include +#include #include #include /** @@ -10,7 +10,7 @@ */ /** - * @defgroup communication comm + * @defgroup comm Communication * @brief Communication software components. */ @@ -18,7 +18,7 @@ * @brief This is an interface to decouple device communication from * the device handler to allow reuse of these components. * @details - * Documentation: Dissertation Baetz p.138 + * Documentation: Dissertation Baetz p.138. * It works with the assumption that received data * is polled by a component. There are four generic steps of device communication: * @@ -38,11 +38,16 @@ class DeviceCommunicationIF: public HasReturnvaluesIF { public: 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); - static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x03); - static const ReturnValue_t NULLPOINTER = MAKE_RETURN_CODE(0x04); - static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0x05); + //!< This is used if no read request is to be made by the device handler. + static const ReturnValue_t NO_READ_REQUEST = MAKE_RETURN_CODE(0x01); + //! General protocol error. Define more concrete errors in child handler + static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0x02); + //! If cookie is a null pointer + static const ReturnValue_t NULLPOINTER = MAKE_RETURN_CODE(0x03); + static const ReturnValue_t INVALID_COOKIE_TYPE = MAKE_RETURN_CODE(0x04); + // is this needed if there is no open/close call? + static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x05); + static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x06); virtual ~DeviceCommunicationIF() {} @@ -54,7 +59,8 @@ public: * this can be performed in this function, which is called on device handler * initialization. * @param cookie - * @return + * @return -@c RETURN_OK if initialization was successfull + * - Everything else triggers failure event with returnvalue as parameter 1 */ virtual ReturnValue_t initializeInterface(CookieIF * cookie) = 0; @@ -66,8 +72,7 @@ public: * @param data * @param len * @return -@c RETURN_OK for successfull send - * - Everything else triggers sending failed event with - * returnvalue as parameter 1 + * - Everything else triggers failure event with returnvalue as parameter 1 */ virtual ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t * sendData, size_t sendLen) = 0; @@ -77,16 +82,21 @@ public: * Get send confirmation that the data in sendMessage() was sent successfully. * @param cookie * @return -@c RETURN_OK if data was sent successfull - * - Everything else triggers sending failed event with - * returnvalue as parameter 1 + * - Everything else triggers falure event with returnvalue as parameter 1 */ virtual ReturnValue_t getSendSuccess(CookieIF *cookie) = 0; /** * Called by DHB in the SEND_WRITE doSendRead(). - * Request a reply. + * It is assumed that it is always possible to request a reply + * from a device. If a requestLen of 0 is supplied, no reply was enabled + * and communication specific action should be taken (e.g. read nothing + * or read everything). + * * @param cookie - * @return + * @param requestLen Size of data to read + * @return -@c RETURN_OK to confirm the request for data has been sent. + * - Everything else triggers failure event with returnvalue as parameter 1 */ virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie, size_t requestLen) = 0; @@ -98,8 +108,7 @@ public: * @param data * @param len * @return @c RETURN_OK for successfull receive - * - Everything else triggers receiving failed with - * returnvalue as parameter 1 + * - Everything else triggers failure event with returnvalue as parameter 1 */ virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) = 0; diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 8187ffde..9691ac2f 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -17,7 +17,7 @@ object_id_t DeviceHandlerBase::rawDataReceiverId = 0; object_id_t DeviceHandlerBase::defaultFDIRParentId = 0; DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, - CookieIF * comCookie_, size_t maxReplyLen, uint8_t setDeviceSwitch, + CookieIF * comCookie_, uint8_t setDeviceSwitch, uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, FailureIsolationBase* fdirInstance, size_t cmdQueueSize) : SystemObject(setObjectId), mode(MODE_OFF), submode(SUBMODE_NONE), @@ -31,7 +31,6 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device childTransitionDelay(5000), transitionSourceMode(_MODE_POWER_DOWN), transitionSourceSubMode(SUBMODE_NONE), deviceSwitch(setDeviceSwitch) { - this->comCookie->setMaxReplyLen(maxReplyLen); commandQueue = QueueFactory::instance()-> createMessageQueue(cmdQueueSize, CommandMessage::MAX_MESSAGE_SIZE); cookieInfo.state = COOKIE_UNUSED; @@ -540,23 +539,27 @@ void DeviceHandlerBase::doGetWrite() { } void DeviceHandlerBase::doSendRead() { - ReturnValue_t result; - - DeviceReplyIter iter = deviceReplyMap.find(cookieInfo.pendingCommand->first); - if(iter != deviceReplyMap.end()) { - requestLen = iter->second.replyLen; - } - else { - requestLen = comCookie->getMaxReplyLen(); + ReturnValue_t result = RETURN_FAILED; + size_t requestLen = 0; + // If the device handler can only request replies after a command + // has been sent, there should be only one reply enabled and the + // correct reply length will be mapped. + for(DeviceReplyIter iter = deviceReplyMap.begin(); + iter != deviceReplyMap.end();iter++) + { + if(iter->second.delayCycles != 0) { + requestLen = iter->second.replyLen; + break; + } } result = communicationInterface->requestReceiveMessage(comCookie, requestLen); if (result == RETURN_OK) { cookieInfo.state = COOKIE_READ_SENT; } - else if(result == DeviceCommunicationIF::NO_READ_REQUEST) { +/* else if(result == DeviceCommunicationIF::NO_READ_REQUEST) { return; - } + }*/ else { triggerEvent(DEVICE_REQUESTING_REPLY_FAILED, result); //We can't inform anyone, because we don't know which command was sent last. @@ -1288,9 +1291,5 @@ void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_){ void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t objectId, uint32_t parameter) { } -uint32_t DeviceHandlerBase::getLogicalAddress() { - return this->comCookie->getAddress(); -} - void DeviceHandlerBase::performOperationHook() { } diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 129fb288..c162210c 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -101,7 +101,7 @@ public: * @param cmdQueueSize */ DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, - CookieIF * comCookie_, size_t maxReplyLen, uint8_t setDeviceSwitch, + CookieIF * comCookie_, uint8_t setDeviceSwitch, uint32_t thermalStatePoolId = PoolVariableIF::NO_PARAMETER, uint32_t thermalRequestPoolId = PoolVariableIF::NO_PARAMETER, FailureIsolationBase* fdirInstance = nullptr, size_t cmdQueueSize = 20); @@ -439,11 +439,6 @@ protected: */ size_t rawPacketLen = 0; - /** - * Size of data to request. - */ - size_t requestLen = 0; - /** * The mode the device handler is currently in. * @@ -463,11 +458,6 @@ protected: */ uint8_t pstStep = 0; - /** - * This will be used in the RMAP getRead command as expected length, is set by the constructor, can be modiefied at will. - */ - const uint32_t maxDeviceReplyLen = 0; - /** * wiretapping flag: * @@ -526,7 +516,6 @@ protected: struct DeviceCommandInfo { bool isExecuting; //!< Indicates if the command is already executing. 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. }; typedef std::map DeviceCommandMap; @@ -847,11 +836,6 @@ protected: */ virtual bool dontCheckQueue(); - /** - * Used to retrieve logical address - * @return logicalAddress - */ - virtual uint32_t getLogicalAddress(); Mode_t getBaseMode(Mode_t transitionMode); bool isAwaitingReply(); @@ -962,11 +946,6 @@ private: */ CookieInfo cookieInfo; - /** - * cached from ctor for initialize() - */ - //const uint32_t logicalAddress = 0; - /** * Used for timing out mode transitions. * From ee23a7c0b57f78256bc69cddf012db44b83f1d13 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 6 Apr 2020 14:02:33 +0200 Subject: [PATCH 009/653] fix --- devicehandlers/DeviceHandlerBase.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 9691ac2f..5fb5a9e5 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -557,9 +557,6 @@ void DeviceHandlerBase::doSendRead() { if (result == RETURN_OK) { cookieInfo.state = COOKIE_READ_SENT; } -/* else if(result == DeviceCommunicationIF::NO_READ_REQUEST) { - return; - }*/ else { triggerEvent(DEVICE_REQUESTING_REPLY_FAILED, result); //We can't inform anyone, because we don't know which command was sent last. @@ -594,7 +591,7 @@ void DeviceHandlerBase::doGetRead() { return; } - if (receivedDataLen == 0) + if (receivedDataLen == 0 or result == DeviceCommunicationIF::NO_REPLY_RECEIVED) return; if (wiretappingMode == RAW) { @@ -1152,9 +1149,6 @@ ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId, if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - if(size == 0) { - return NO_COMMAND_DATA; - } DeviceCommandMap::iterator iter = deviceCommandMap.find(actionId); if (iter == deviceCommandMap.end()) { From 2b740a3c0f9f2b28173afb1b3eb1e4efa161551f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 9 Apr 2020 18:02:42 +0200 Subject: [PATCH 010/653] bugfix --- timemanager/Stopwatch.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/timemanager/Stopwatch.cpp b/timemanager/Stopwatch.cpp index 6c50f0de..3f0755fd 100644 --- a/timemanager/Stopwatch.cpp +++ b/timemanager/Stopwatch.cpp @@ -12,7 +12,7 @@ Stopwatch::Stopwatch(bool displayOnDestruction, StopwatchDisplayMode displayMode): displayMode(displayMode), displayOnDestruction(displayOnDestruction) { // Measures start time on initialization. - Clock::getUptime(&startTime); + startTime = Clock::getUptime(); } void Stopwatch::start() { @@ -31,8 +31,8 @@ seconds_t Stopwatch::stopSeconds() { void Stopwatch::display() { if(displayMode == StopwatchDisplayMode::MILLIS) { - info << "Stopwatch: Operation took " << elapsedTime.tv_sec * 1000 + - elapsedTime.tv_usec * 1000 << " milliseconds" << std::endl; + info << "Stopwatch: Operation took " << (elapsedTime.tv_sec * 1000 + + elapsedTime.tv_usec / 1000) << " milliseconds" << std::endl; } else if(displayMode == StopwatchDisplayMode::SECONDS) { info <<"Stopwatch: Operation took " << std::setprecision(3) From 81ab5a691480af2dc67d0cec5ba87157f30dfb01 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 18 Apr 2020 14:03:37 +0200 Subject: [PATCH 011/653] As discussed, renamed Cookie to CookieIF. Also added documentation on the purpose of this class --- devicehandlers/Cookie.h | 10 ---------- devicehandlers/CookieIF.h | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 10 deletions(-) delete mode 100644 devicehandlers/Cookie.h create mode 100644 devicehandlers/CookieIF.h diff --git a/devicehandlers/Cookie.h b/devicehandlers/Cookie.h deleted file mode 100644 index 495c8c40..00000000 --- a/devicehandlers/Cookie.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef COOKIE_H_ -#define COOKIE_H_ - -class Cookie{ -public: - virtual ~Cookie(){} -}; - - -#endif /* COOKIE_H_ */ diff --git a/devicehandlers/CookieIF.h b/devicehandlers/CookieIF.h new file mode 100644 index 00000000..6b2bb559 --- /dev/null +++ b/devicehandlers/CookieIF.h @@ -0,0 +1,34 @@ +#ifndef COOKIE_H_ +#define COOKIE_H_ +#include +#include + +/** + * @brief Physical address type + */ +typedef uint32_t address_t; + +/** + * @brief This datatype is used to identify different connection over a + * single interface (like RMAP or I2C) + * @details + * To use this class, implement a communication specific child cookie which + * inherits Cookie. Cookie instances are created in config/Factory.cpp by + * calling @code{.cpp} CookieIF* childCookie = new ChildCookie(...) + * @endcode . + * + * This cookie is then passed to the child device handlers, which stores the + * pointer and passes it to the communication interface functions. + * + * The cookie can be used to store all kinds of information + * about the communication, like slave addresses, communication status, + * communication parameters etc. + * + * @ingroup comm + */ +class CookieIF { +public: + virtual ~CookieIF() {}; +}; + +#endif /* COOKIE_H_ */ From 9c958c06fe9eda9cbb5cb5ec0e6d27d3db985197 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 18 Apr 2020 14:10:38 +0200 Subject: [PATCH 012/653] Changed Cookie to CookieIF --- devicehandlers/CookieIF.h | 1 + devicehandlers/DeviceCommunicationIF.h | 24 ++++++++++++------------ devicehandlers/DeviceHandlerBase.h | 2 +- rmap/RMAPCookie.h | 4 ++-- rmap/RmapDeviceCommunicationIF.cpp | 16 ++++++++-------- rmap/RmapDeviceCommunicationIF.h | 22 +++++++++++----------- 6 files changed, 35 insertions(+), 34 deletions(-) diff --git a/devicehandlers/CookieIF.h b/devicehandlers/CookieIF.h index 6b2bb559..e25ef258 100644 --- a/devicehandlers/CookieIF.h +++ b/devicehandlers/CookieIF.h @@ -17,6 +17,7 @@ typedef uint32_t address_t; * calling @code{.cpp} CookieIF* childCookie = new ChildCookie(...) * @endcode . * + * [not implemented yet] * This cookie is then passed to the child device handlers, which stores the * pointer and passes it to the communication interface functions. * diff --git a/devicehandlers/DeviceCommunicationIF.h b/devicehandlers/DeviceCommunicationIF.h index e0aca573..35a64cee 100644 --- a/devicehandlers/DeviceCommunicationIF.h +++ b/devicehandlers/DeviceCommunicationIF.h @@ -1,7 +1,7 @@ #ifndef DEVICECOMMUNICATIONIF_H_ #define DEVICECOMMUNICATIONIF_H_ -#include +#include #include class DeviceCommunicationIF: public HasReturnvaluesIF { @@ -20,7 +20,7 @@ public: } - virtual ReturnValue_t open(Cookie **cookie, uint32_t address, + virtual ReturnValue_t open(CookieIF **cookie, uint32_t address, uint32_t maxReplyLen) = 0; /** @@ -34,29 +34,29 @@ public: * @param maxReplyLen * @return */ - virtual ReturnValue_t reOpen(Cookie *cookie, uint32_t address, + virtual ReturnValue_t reOpen(CookieIF *cookie, uint32_t address, uint32_t maxReplyLen) = 0; - virtual void close(Cookie *cookie) = 0; + virtual void close(CookieIF *cookie) = 0; //SHOULDDO can data be const? - virtual ReturnValue_t sendMessage(Cookie *cookie, uint8_t *data, + virtual ReturnValue_t sendMessage(CookieIF *cookie, uint8_t *data, uint32_t len) = 0; - virtual ReturnValue_t getSendSuccess(Cookie *cookie) = 0; + virtual ReturnValue_t getSendSuccess(CookieIF *cookie) = 0; - virtual ReturnValue_t requestReceiveMessage(Cookie *cookie) = 0; + virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie) = 0; - virtual ReturnValue_t readReceivedMessage(Cookie *cookie, uint8_t **buffer, + virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, uint32_t *size) = 0; - virtual ReturnValue_t setAddress(Cookie *cookie, uint32_t address) = 0; + virtual ReturnValue_t setAddress(CookieIF *cookie, uint32_t address) = 0; - virtual uint32_t getAddress(Cookie *cookie) = 0; + virtual uint32_t getAddress(CookieIF *cookie) = 0; - virtual ReturnValue_t setParameter(Cookie *cookie, uint32_t parameter) = 0; + virtual ReturnValue_t setParameter(CookieIF *cookie, uint32_t parameter) = 0; - virtual uint32_t getParameter(Cookie *cookie) = 0; + virtual uint32_t getParameter(CookieIF *cookie) = 0; }; diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 756ad530..ec5e3cd8 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -244,7 +244,7 @@ protected: /** * Cookie used for communication */ - Cookie *cookie; + CookieIF *cookie; /** * The MessageQueue used to receive device handler commands and to send replies. diff --git a/rmap/RMAPCookie.h b/rmap/RMAPCookie.h index c091ba18..4890c516 100644 --- a/rmap/RMAPCookie.h +++ b/rmap/RMAPCookie.h @@ -1,12 +1,12 @@ #ifndef RMAPCOOKIE_H_ #define RMAPCOOKIE_H_ -#include +#include #include class RMAPChannelIF; -class RMAPCookie : public Cookie{ +class RMAPCookie : public CookieIF { public: //To Uli: Sorry, I need an empty ctor to initialize an array of cookies. RMAPCookie(); diff --git a/rmap/RmapDeviceCommunicationIF.cpp b/rmap/RmapDeviceCommunicationIF.cpp index 4958b3ed..674d050d 100644 --- a/rmap/RmapDeviceCommunicationIF.cpp +++ b/rmap/RmapDeviceCommunicationIF.cpp @@ -5,43 +5,43 @@ RmapDeviceCommunicationIF::~RmapDeviceCommunicationIF() { } -ReturnValue_t RmapDeviceCommunicationIF::sendMessage(Cookie* cookie, +ReturnValue_t RmapDeviceCommunicationIF::sendMessage(CookieIF* cookie, uint8_t* data, uint32_t len) { return RMAP::sendWriteCommand((RMAPCookie *) cookie, data, len); } -ReturnValue_t RmapDeviceCommunicationIF::getSendSuccess(Cookie* cookie) { +ReturnValue_t RmapDeviceCommunicationIF::getSendSuccess(CookieIF* cookie) { return RMAP::getWriteReply((RMAPCookie *) cookie); } ReturnValue_t RmapDeviceCommunicationIF::requestReceiveMessage( - Cookie* cookie) { + CookieIF* cookie) { return RMAP::sendReadCommand((RMAPCookie *) cookie, ((RMAPCookie *) cookie)->getMaxReplyLen()); } -ReturnValue_t RmapDeviceCommunicationIF::readReceivedMessage(Cookie* cookie, +ReturnValue_t RmapDeviceCommunicationIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, uint32_t* size) { return RMAP::getReadReply((RMAPCookie *) cookie, buffer, size); } -ReturnValue_t RmapDeviceCommunicationIF::setAddress(Cookie* cookie, +ReturnValue_t RmapDeviceCommunicationIF::setAddress(CookieIF* cookie, uint32_t address) { ((RMAPCookie *) cookie)->setAddress(address); return HasReturnvaluesIF::RETURN_OK; } -uint32_t RmapDeviceCommunicationIF::getAddress(Cookie* cookie) { +uint32_t RmapDeviceCommunicationIF::getAddress(CookieIF* cookie) { return ((RMAPCookie *) cookie)->getAddress(); } -ReturnValue_t RmapDeviceCommunicationIF::setParameter(Cookie* cookie, +ReturnValue_t RmapDeviceCommunicationIF::setParameter(CookieIF* cookie, uint32_t parameter) { //TODO Empty? return HasReturnvaluesIF::RETURN_FAILED; } -uint32_t RmapDeviceCommunicationIF::getParameter(Cookie* cookie) { +uint32_t RmapDeviceCommunicationIF::getParameter(CookieIF* cookie) { return 0; } diff --git a/rmap/RmapDeviceCommunicationIF.h b/rmap/RmapDeviceCommunicationIF.h index 12ae67e4..9d756ea2 100644 --- a/rmap/RmapDeviceCommunicationIF.h +++ b/rmap/RmapDeviceCommunicationIF.h @@ -25,7 +25,7 @@ public: * @param maxReplyLen Maximum length of expected reply * @return */ - virtual ReturnValue_t open(Cookie **cookie, uint32_t address, + virtual ReturnValue_t open(CookieIF **cookie, uint32_t address, uint32_t maxReplyLen) = 0; /** @@ -39,7 +39,7 @@ public: * @param maxReplyLen * @return */ - virtual ReturnValue_t reOpen(Cookie *cookie, uint32_t address, + virtual ReturnValue_t reOpen(CookieIF *cookie, uint32_t address, uint32_t maxReplyLen) = 0; @@ -47,7 +47,7 @@ public: * Closing call of connection and memory free of cookie. Mission dependent call * @param cookie */ - virtual void close(Cookie *cookie) = 0; + virtual void close(CookieIF *cookie) = 0; //SHOULDDO can data be const? /** @@ -58,23 +58,23 @@ public: * @param len Length of the data to be send * @return - Return codes of RMAP::sendWriteCommand() */ - virtual ReturnValue_t sendMessage(Cookie *cookie, uint8_t *data, + virtual ReturnValue_t sendMessage(CookieIF *cookie, uint8_t *data, uint32_t len); - virtual ReturnValue_t getSendSuccess(Cookie *cookie); + virtual ReturnValue_t getSendSuccess(CookieIF *cookie); - virtual ReturnValue_t requestReceiveMessage(Cookie *cookie); + virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie); - virtual ReturnValue_t readReceivedMessage(Cookie *cookie, uint8_t **buffer, + virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, uint32_t *size); - virtual ReturnValue_t setAddress(Cookie *cookie, uint32_t address); + virtual ReturnValue_t setAddress(CookieIF *cookie, uint32_t address); - virtual uint32_t getAddress(Cookie *cookie); + virtual uint32_t getAddress(CookieIF *cookie); - virtual ReturnValue_t setParameter(Cookie *cookie, uint32_t parameter); + virtual ReturnValue_t setParameter(CookieIF *cookie, uint32_t parameter); - virtual uint32_t getParameter(Cookie *cookie); + virtual uint32_t getParameter(CookieIF *cookie); }; #endif /* MISSION_RMAP_RMAPDEVICECOMMUNICATIONINTERFACE_H_ */ From db34c45b67dfa8621581617700dc9f8dc487026d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 18 Apr 2020 14:16:46 +0200 Subject: [PATCH 013/653] removed self-inclusion --- devicehandlers/CookieIF.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/devicehandlers/CookieIF.h b/devicehandlers/CookieIF.h index e25ef258..ae2c5173 100644 --- a/devicehandlers/CookieIF.h +++ b/devicehandlers/CookieIF.h @@ -1,7 +1,6 @@ #ifndef COOKIE_H_ #define COOKIE_H_ -#include -#include +#include /** * @brief Physical address type From a1f36e6ae5c36062ea31d42ae0fac37b31a3b04d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 18 Apr 2020 15:05:51 +0200 Subject: [PATCH 014/653] added std:: before uint32_t typedef --- devicehandlers/CookieIF.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devicehandlers/CookieIF.h b/devicehandlers/CookieIF.h index ae2c5173..496cf0d2 100644 --- a/devicehandlers/CookieIF.h +++ b/devicehandlers/CookieIF.h @@ -5,7 +5,7 @@ /** * @brief Physical address type */ -typedef uint32_t address_t; +typedef std::uint32_t address_t; /** * @brief This datatype is used to identify different connection over a From abe7239018908ac5c4912dcc62b840b882fd95f6 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 19 Apr 2020 13:24:10 +0200 Subject: [PATCH 015/653] reset, splitting up merge request --- devicehandlers/CookieIF.h | 33 - devicehandlers/DeviceCommunicationIF.h | 142 +-- devicehandlers/DeviceHandlerBase.cpp | 357 ++++---- devicehandlers/DeviceHandlerBase.h | 1095 +++++++++++------------- devicehandlers/DeviceHandlerIF.h | 152 ++-- 5 files changed, 787 insertions(+), 992 deletions(-) delete mode 100644 devicehandlers/CookieIF.h diff --git a/devicehandlers/CookieIF.h b/devicehandlers/CookieIF.h deleted file mode 100644 index 55fdb44b..00000000 --- a/devicehandlers/CookieIF.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef COOKIE_H_ -#define COOKIE_H_ -#include -#include - -/** - * @brief Physical address type - */ -typedef uint32_t address_t; - -/** - * @brief This datatype is used to identify different connection over a single interface - * (like RMAP or I2C) - * @details - * To use this class, implement a communication specific child cookie which - * inherits Cookie. Cookie instances are created in config/ Factory.cpp by calling - * CookieIF* childCookie = new ChildCookie(...). - * - * This cookie is then passed to the child device handlers, which stores the - * pointer and passes it to the communication interface functions. - * - * The cookie can be used to store all kinds of information - * about the communication, like slave addresses, communication status, - * communication parameters etc. - * - * @ingroup comm - */ -class CookieIF { -public: - virtual ~CookieIF() {}; -}; - -#endif /* COOKIE_H_ */ diff --git a/devicehandlers/DeviceCommunicationIF.h b/devicehandlers/DeviceCommunicationIF.h index 657f7232..e0aca573 100644 --- a/devicehandlers/DeviceCommunicationIF.h +++ b/devicehandlers/DeviceCommunicationIF.h @@ -1,117 +1,63 @@ #ifndef DEVICECOMMUNICATIONIF_H_ #define DEVICECOMMUNICATIONIF_H_ -#include -#include +#include #include -/** - * @defgroup interfaces Interfaces - * @brief Interfaces for flight software objects - */ -/** - * @defgroup comm Communication - * @brief Communication software components. - */ - -/** - * @brief This is an interface to decouple device communication from - * the device handler to allow reuse of these components. - * @details - * Documentation: Dissertation Baetz p.138. - * 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. - * The CommunicationMessage message type can be used to extend the functionality of the - * ComIF if a separate polling task is required. - * @ingroup interfaces - * @ingroup comm - */ class DeviceCommunicationIF: public HasReturnvaluesIF { public: static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_COMMUNICATION_IF; - //!< This is used if no read request is to be made by the device handler. - static const ReturnValue_t NO_READ_REQUEST = MAKE_RETURN_CODE(0x01); - //! General protocol error. Define more concrete errors in child handler - static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0x02); - //! If cookie is a null pointer - static const ReturnValue_t NULLPOINTER = MAKE_RETURN_CODE(0x03); - static const ReturnValue_t INVALID_COOKIE_TYPE = MAKE_RETURN_CODE(0x04); - // is this needed if there is no open/close call? - static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x05); - static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x06); + static const ReturnValue_t INVALID_COOKIE_TYPE = MAKE_RETURN_CODE(0x01); + static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x02); + static const ReturnValue_t INVALID_ADDRESS = MAKE_RETURN_CODE(0x03); + static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x04); + static const ReturnValue_t NULLPOINTER = MAKE_RETURN_CODE(0x05); + static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0x06); + static const ReturnValue_t CANT_CHANGE_REPLY_LEN = MAKE_RETURN_CODE(0x07); - virtual ~DeviceCommunicationIF() {} + virtual ~DeviceCommunicationIF() { + + } + + virtual ReturnValue_t open(Cookie **cookie, uint32_t address, + uint32_t maxReplyLen) = 0; /** - * @brief Device specific initialization, using the cookie. - * @details - * The cookie is already prepared in the factory. If the communication - * interface needs to be set up in some way and requires cookie information, - * this can be performed in this function, which is called on device handler - * initialization. - * @param cookie - * @return -@c RETURN_OK if initialization was successfull - * - Everything else triggers failure event with returnvalue as parameter 1 - */ - virtual ReturnValue_t initializeInterface(CookieIF * cookie) = 0; - - /** - * 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 -@c RETURN_OK for successfull send - * - Everything else triggers failure event with returnvalue as parameter 1 - */ - virtual ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t * sendData, - size_t sendLen) = 0; - - /** - * Called by DHB in the GET_WRITE doGetWrite(). - * Get send confirmation that the data in sendMessage() was sent successfully. - * @param cookie - * @return -@c RETURN_OK if data was sent successfull - * - Everything else triggers falure event with returnvalue as parameter 1 - */ - virtual ReturnValue_t getSendSuccess(CookieIF *cookie) = 0; - - /** - * Called by DHB in the SEND_WRITE doSendRead(). - * It is assumed that it is always possible to request a reply - * from a device. If a requestLen of 0 is supplied, no reply was enabled - * and communication specific action should be taken (e.g. read nothing - * or read everything). + * Use an existing cookie to open a connection to a new DeviceCommunication. + * The previous connection must not be closed. + * If the returnvalue is not RETURN_OK, the cookie is unchanged and + * can be used with the previous connection. * * @param cookie - * @param requestLen Size of data to read - * @return -@c RETURN_OK to confirm the request for data has been sent. - * - Everything else triggers failure event with returnvalue as parameter 1 + * @param address + * @param maxReplyLen + * @return */ - virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie, size_t requestLen) = 0; + virtual ReturnValue_t reOpen(Cookie *cookie, uint32_t address, + uint32_t maxReplyLen) = 0; + + virtual void close(Cookie *cookie) = 0; + + //SHOULDDO can data be const? + virtual ReturnValue_t sendMessage(Cookie *cookie, uint8_t *data, + uint32_t len) = 0; + + virtual ReturnValue_t getSendSuccess(Cookie *cookie) = 0; + + virtual ReturnValue_t requestReceiveMessage(Cookie *cookie) = 0; + + virtual ReturnValue_t readReceivedMessage(Cookie *cookie, uint8_t **buffer, + uint32_t *size) = 0; + + virtual ReturnValue_t setAddress(Cookie *cookie, uint32_t address) = 0; + + virtual uint32_t getAddress(Cookie *cookie) = 0; + + virtual ReturnValue_t setParameter(Cookie *cookie, uint32_t parameter) = 0; + + virtual uint32_t getParameter(Cookie *cookie) = 0; - /** - * Called by DHB in the GET_WRITE 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 @c RETURN_OK for successfull receive - * - Everything else triggers failure event with returnvalue as parameter 1 - */ - virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, - size_t *size) = 0; }; #endif /* DEVICECOMMUNICATIONIF_H_ */ diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 5fb5a9e5..22d49d37 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -16,33 +16,37 @@ object_id_t DeviceHandlerBase::powerSwitcherId = 0; object_id_t DeviceHandlerBase::rawDataReceiverId = 0; object_id_t DeviceHandlerBase::defaultFDIRParentId = 0; -DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, - CookieIF * comCookie_, uint8_t setDeviceSwitch, +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, - FailureIsolationBase* fdirInstance, size_t cmdQueueSize) : - SystemObject(setObjectId), mode(MODE_OFF), submode(SUBMODE_NONE), - wiretappingMode(OFF), storedRawData(StorageManagerIF::INVALID_ADDRESS), - deviceCommunicationId(deviceCommunication), comCookie(comCookie_), - deviceThermalStatePoolId(thermalStatePoolId), deviceThermalRequestPoolId(thermalRequestPoolId), - healthHelper(this, setObjectId), modeHelper(this), parameterHelper(this), - fdirInstance(fdirInstance), hkSwitcher(this), - defaultFDIRUsed(fdirInstance == nullptr), switchOffWasReported(false), - executingTask(nullptr), actionHelper(this, nullptr), cookieInfo(), - childTransitionDelay(5000), transitionSourceMode(_MODE_POWER_DOWN), - transitionSourceSubMode(SUBMODE_NONE), deviceSwitch(setDeviceSwitch) -{ - commandQueue = QueueFactory::instance()-> - createMessageQueue(cmdQueueSize, CommandMessage::MAX_MESSAGE_SIZE); + 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) { + commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize, + CommandMessage::MAX_MESSAGE_SIZE); cookieInfo.state = COOKIE_UNUSED; insertInCommandMap(RAW_COMMAND_ID); - if (this->fdirInstance == nullptr) { - this->fdirInstance = - new DeviceHandlerFailureIsolation(setObjectId, defaultFDIRParentId); + if (this->fdirInstance == NULL) { + this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, + defaultFDIRParentId); } } DeviceHandlerBase::~DeviceHandlerBase() { - delete comCookie; + communicationInterface->close(cookie); if (defaultFDIRUsed) { delete fdirInstance; } @@ -51,6 +55,7 @@ DeviceHandlerBase::~DeviceHandlerBase() { ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { this->pstStep = counter; + if (counter == 0) { cookieInfo.state = COOKIE_UNUSED; readCommandQueue(); @@ -59,13 +64,11 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { decrementDeviceReplyMap(); fdirInstance->checkForFailures(); hkSwitcher.performOperation(); - performOperationHook(); } if (mode == MODE_OFF) { return RETURN_OK; } - - switch (getComAction()) { + switch (getRmapAction()) { case SEND_WRITE: if ((cookieInfo.state == COOKIE_UNUSED)) { buildInternalCommand(); @@ -85,84 +88,6 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { default: break; } - - return RETURN_OK; -} - -ReturnValue_t DeviceHandlerBase::initialize() { - ReturnValue_t result = SystemObject::initialize(); - if (result != RETURN_OK) { - return result; - } - - communicationInterface = objectManager->get( - deviceCommunicationId); - if (communicationInterface == NULL) { - return RETURN_FAILED; - } - - result = communicationInterface->initializeInterface(comCookie); - if (result != RETURN_OK) { - return result; - } - - IPCStore = objectManager->get(objects::IPC_STORE); - if (IPCStore == NULL) { - return RETURN_FAILED; - } - - AcceptsDeviceResponsesIF *rawReceiver = objectManager->get< - AcceptsDeviceResponsesIF>(rawDataReceiverId); - - if (rawReceiver == NULL) { - return RETURN_FAILED; - } - - defaultRawReceiver = rawReceiver->getDeviceQueue(); - - powerSwitcher = objectManager->get(powerSwitcherId); - if (powerSwitcher == NULL) { - return RETURN_FAILED; - } - - result = healthHelper.initialize(); - if (result != RETURN_OK) { - return result; - } - - result = modeHelper.initialize(); - if (result != RETURN_OK) { - return result; - } - result = actionHelper.initialize(commandQueue); - if (result != RETURN_OK) { - return result; - } - result = fdirInstance->initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - - result = parameterHelper.initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - - result = hkSwitcher.initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - - fillCommandAndReplyMap(); - - //Set temperature target state to NON_OP. - DataSet mySet; - PoolVariable thermalRequest(deviceThermalRequestPoolId, &mySet, - PoolVariableIF::VAR_WRITE); - mySet.read(); - thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; - mySet.commit(PoolVariableIF::VALID); - return RETURN_OK; } @@ -331,49 +256,55 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode, } } -ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, - uint16_t maxDelayCycles, size_t replyLen, uint8_t periodic, - bool hasDifferentReplyId, DeviceCommandId_t replyId) { - //No need to check, as we may try to insert multiple times. +ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap( + DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, + uint8_t periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) { +//No need to check, as we may try to insert multiple times. insertInCommandMap(deviceCommand); if (hasDifferentReplyId) { - return insertInReplyMap(replyId, maxDelayCycles, replyLen, periodic); + return insertInReplyMap(replyId, maxDelayCycles, periodic); } else { - return insertInReplyMap(deviceCommand, maxDelayCycles, replyLen, periodic); + return insertInReplyMap(deviceCommand, maxDelayCycles, periodic); } } ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId, - uint16_t maxDelayCycles, size_t replyLen, uint8_t periodic) { + uint16_t maxDelayCycles, uint8_t periodic) { DeviceReplyInfo info; info.maxDelayCycles = maxDelayCycles; info.periodic = periodic; info.delayCycles = 0; - info.replyLen = replyLen; info.command = deviceCommandMap.end(); - std::pair result = deviceReplyMap.emplace(replyId, info); - if (result.second) { + std::pair::iterator, bool> returnValue; + returnValue = deviceReplyMap.insert( + std::pair(replyId, info)); + if (returnValue.second) { return RETURN_OK; } else { return RETURN_FAILED; } } -ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceCommand) { +ReturnValue_t DeviceHandlerBase::insertInCommandMap( + DeviceCommandId_t deviceCommand) { DeviceCommandInfo info; info.expectedReplies = 0; info.isExecuting = false; info.sendReplyTo = NO_COMMANDER; - std::pair result = deviceCommandMap.emplace(deviceCommand,info); - if (result.second) { + std::pair::iterator, bool> returnValue; + returnValue = deviceCommandMap.insert( + std::pair(deviceCommand, + info)); + if (returnValue.second) { return RETURN_OK; } else { return RETURN_FAILED; } } -ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply, - uint16_t delayCycles, uint16_t maxDelayCycles, uint8_t periodic) { +ReturnValue_t DeviceHandlerBase::updateReplyMapEntry( + DeviceCommandId_t deviceReply, uint16_t delayCycles, + uint16_t maxDelayCycles, uint8_t periodic) { std::map::iterator iter = deviceReplyMap.find(deviceReply); if (iter == deviceReplyMap.end()) { @@ -485,7 +416,7 @@ void DeviceHandlerBase::replyToReply(DeviceReplyMap::iterator iter, return; } //Check if more replies are expected. If so, do nothing. - DeviceCommandInfo * info = &(iter->second.command->second); + DeviceCommandInfo* info = &(iter->second.command->second); if (--info->expectedReplies == 0) { //Check if it was transition or internal command. Don't send any replies in that case. if (info->sendReplyTo != NO_COMMANDER) { @@ -498,7 +429,7 @@ void DeviceHandlerBase::replyToReply(DeviceReplyMap::iterator iter, void DeviceHandlerBase::doSendWrite() { if (cookieInfo.state == COOKIE_WRITE_READY) { - ReturnValue_t result = communicationInterface->sendMessage(comCookie, + ReturnValue_t result = communicationInterface->sendMessage(cookie, rawPacket, rawPacketLen); if (result == RETURN_OK) { @@ -519,13 +450,12 @@ void DeviceHandlerBase::doGetWrite() { return; } cookieInfo.state = COOKIE_UNUSED; - ReturnValue_t result = communicationInterface->getSendSuccess(comCookie); + ReturnValue_t result = communicationInterface->getSendSuccess(cookie); if (result == RETURN_OK) { 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 @@ -539,25 +469,12 @@ void DeviceHandlerBase::doGetWrite() { } void DeviceHandlerBase::doSendRead() { - ReturnValue_t result = RETURN_FAILED; - size_t requestLen = 0; - // If the device handler can only request replies after a command - // has been sent, there should be only one reply enabled and the - // correct reply length will be mapped. - for(DeviceReplyIter iter = deviceReplyMap.begin(); - iter != deviceReplyMap.end();iter++) - { - if(iter->second.delayCycles != 0) { - requestLen = iter->second.replyLen; - break; - } - } + ReturnValue_t result; - result = communicationInterface->requestReceiveMessage(comCookie, requestLen); + result = communicationInterface->requestReceiveMessage(cookie); if (result == RETURN_OK) { cookieInfo.state = COOKIE_READ_SENT; - } - else { + } 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. @@ -568,10 +485,10 @@ void DeviceHandlerBase::doSendRead() { } void DeviceHandlerBase::doGetRead() { - size_t receivedDataLen; + uint32_t receivedDataLen; uint8_t *receivedData; DeviceCommandId_t foundId = 0xFFFFFFFF; - size_t foundLen = 0; + uint32_t foundLen = 0; ReturnValue_t result; if (cookieInfo.state != COOKIE_READ_SENT) { @@ -581,7 +498,7 @@ void DeviceHandlerBase::doGetRead() { cookieInfo.state = COOKIE_UNUSED; - result = communicationInterface->readReceivedMessage(comCookie, &receivedData, + result = communicationInterface->readReceivedMessage(cookie, &receivedData, &receivedDataLen); if (result != RETURN_OK) { @@ -591,7 +508,7 @@ void DeviceHandlerBase::doGetRead() { return; } - if (receivedDataLen == 0 or result == DeviceCommunicationIF::NO_REPLY_RECEIVED) + if (receivedDataLen == 0) return; if (wiretappingMode == RAW) { @@ -622,8 +539,6 @@ void DeviceHandlerBase::doGetRead() { break; case IGNORE_REPLY_DATA: break; - case IGNORE_FULL_PACKET: - return; default: //We need to wait for timeout.. don't know what command failed and who sent it. replyRawReplyIfnotWiretapped(receivedData, foundLen); @@ -642,8 +557,8 @@ void DeviceHandlerBase::doGetRead() { } ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, - uint8_t ** data, size_t * len) { - size_t lenTmp; + uint8_t * *data, uint32_t * len) { + uint32_t lenTmp; if (IPCStore == NULL) { *data = NULL; @@ -664,6 +579,84 @@ ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, } +ReturnValue_t DeviceHandlerBase::initialize() { + ReturnValue_t result = SystemObject::initialize(); + if (result != RETURN_OK) { + return result; + } + + communicationInterface = objectManager->get( + deviceCommunicationId); + if (communicationInterface == NULL) { + return RETURN_FAILED; + } + + result = communicationInterface->open(&cookie, ioBoardAddress, + maxDeviceReplyLen); + if (result != RETURN_OK) { + return result; + } + + IPCStore = objectManager->get(objects::IPC_STORE); + if (IPCStore == NULL) { + return RETURN_FAILED; + } + + AcceptsDeviceResponsesIF *rawReceiver = objectManager->get< + AcceptsDeviceResponsesIF>(rawDataReceiverId); + + if (rawReceiver == NULL) { + return RETURN_FAILED; + } + + defaultRawReceiver = rawReceiver->getDeviceQueue(); + + powerSwitcher = objectManager->get(powerSwitcherId); + if (powerSwitcher == NULL) { + return RETURN_FAILED; + } + + result = healthHelper.initialize(); + if (result != RETURN_OK) { + return result; + } + + result = modeHelper.initialize(); + if (result != RETURN_OK) { + return result; + } + result = actionHelper.initialize(commandQueue); + if (result != RETURN_OK) { + return result; + } + result = fdirInstance->initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + result = parameterHelper.initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + result = hkSwitcher.initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + fillCommandAndReplyMap(); + + //Set temperature target state to NON_OP. + DataSet mySet; + PoolVariable thermalRequest(deviceThermalRequestPoolId, &mySet, + PoolVariableIF::VAR_WRITE); + mySet.read(); + thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; + mySet.commit(PoolVariableIF::VALID); + + return RETURN_OK; + +} void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len, MessageQueueId_t sendTo, bool isCommand) { @@ -679,6 +672,7 @@ void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len, } CommandMessage message; + DeviceHandlerMessage::setDeviceHandlerRawReplyMessage(&message, getObjectId(), address, isCommand); @@ -694,7 +688,7 @@ void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len, //Default child implementations -DeviceHandlerBase::CommunicationAction_t DeviceHandlerBase::getComAction() { +DeviceHandlerBase::RmapAction_t DeviceHandlerBase::getRmapAction() { switch (pstStep) { case 0: return SEND_WRITE; @@ -754,20 +748,20 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, } } -//ReturnValue_t DeviceHandlerBase::switchCookieChannel(object_id_t newChannelId) { -// DeviceCommunicationIF *newCommunication = objectManager->get< -// DeviceCommunicationIF>(newChannelId); -// -// if (newCommunication != NULL) { -// ReturnValue_t result = newCommunication->reOpen(cookie, logicalAddress, -// maxDeviceReplyLen, comParameter1, comParameter2); -// if (result != RETURN_OK) { -// return result; -// } -// return RETURN_OK; -// } -// return RETURN_FAILED; -//} +ReturnValue_t DeviceHandlerBase::switchCookieChannel(object_id_t newChannelId) { + DeviceCommunicationIF *newCommunication = objectManager->get< + DeviceCommunicationIF>(newChannelId); + + if (newCommunication != NULL) { + ReturnValue_t result = newCommunication->reOpen(cookie, ioBoardAddress, + maxDeviceReplyLen); + if (result != RETURN_OK) { + return result; + } + return RETURN_OK; + } + return RETURN_FAILED; +} void DeviceHandlerBase::buildRawDeviceCommand(CommandMessage* commandMessage) { storedRawData = DeviceHandlerMessage::getStoreAddress(commandMessage); @@ -777,8 +771,8 @@ void DeviceHandlerBase::buildRawDeviceCommand(CommandMessage* commandMessage) { replyReturnvalueToCommand(result, RAW_COMMAND_ID); storedRawData.raw = StorageManagerIF::INVALID_ADDRESS; } else { - cookieInfo.pendingCommand = deviceCommandMap. - find((DeviceCommandId_t) RAW_COMMAND_ID); + cookieInfo.pendingCommand = deviceCommandMap.find( + (DeviceCommandId_t) RAW_COMMAND_ID); cookieInfo.pendingCommand->second.isExecuting = true; cookieInfo.state = COOKIE_WRITE_READY; } @@ -817,7 +811,7 @@ ReturnValue_t DeviceHandlerBase::enableReplyInReplyMap( iter = deviceReplyMap.find(command->first); } if (iter != deviceReplyMap.end()) { - DeviceReplyInfo * info = &(iter->second); + DeviceReplyInfo *info = &(iter->second); info->delayCycles = info->maxDelayCycles; info->command = command; command->second.expectedReplies = expectedReplies; @@ -843,9 +837,8 @@ 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--; @@ -1051,18 +1044,16 @@ ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage( } replyReturnvalueToCommand(RETURN_OK); return RETURN_OK; - case DeviceHandlerMessage::CMD_SWITCH_ADDRESS: + case DeviceHandlerMessage::CMD_SWITCH_IOBOARD: if (mode != MODE_OFF) { replyReturnvalueToCommand(WRONG_MODE_FOR_COMMAND); } else { - // rework in progress - result = RETURN_OK; - //result = switchCookieChannel( - // DeviceHandlerMessage::getIoBoardObjectId(message)); + result = switchCookieChannel( + DeviceHandlerMessage::getIoBoardObjectId(message)); if (result == RETURN_OK) { replyReturnvalueToCommand(RETURN_OK); } else { - replyReturnvalueToCommand(CANT_SWITCH_ADDRESS); + replyReturnvalueToCommand(CANT_SWITCH_IOBOARD); } } return RETURN_OK; @@ -1121,7 +1112,8 @@ 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 @@ -1144,12 +1136,11 @@ void DeviceHandlerBase::handleDeviceTM(SerializeIF* data, } ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId, - MessageQueueId_t commandedBy, const uint8_t* data, size_t size) { + MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size) { ReturnValue_t result = acceptExternalDeviceCommands(); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - DeviceCommandMap::iterator iter = deviceCommandMap.find(actionId); if (iter == deviceCommandMap.end()) { result = COMMAND_NOT_SUPPORTED; @@ -1168,7 +1159,7 @@ ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId, } void DeviceHandlerBase::buildInternalCommand(void) { - // Neither Raw nor Direct could build a command +//Neither Raw nor Direct could build a command ReturnValue_t result = NOTHING_TO_SEND; DeviceCommandId_t deviceCommandId = NO_COMMAND_ID; if (mode == MODE_NORMAL) { @@ -1186,13 +1177,12 @@ void DeviceHandlerBase::buildInternalCommand(void) { } else { return; } - if (result == NOTHING_TO_SEND) { return; } if (result == RETURN_OK) { - DeviceCommandMap::iterator iter = - deviceCommandMap.find(deviceCommandId); + DeviceCommandMap::iterator iter = deviceCommandMap.find( + deviceCommandId); if (iter == deviceCommandMap.end()) { result = COMMAND_NOT_SUPPORTED; } else if (iter->second.isExecuting) { @@ -1207,7 +1197,6 @@ void DeviceHandlerBase::buildInternalCommand(void) { cookieInfo.state = COOKIE_WRITE_READY; } } - if (result != RETURN_OK) { triggerEvent(DEVICE_BUILDING_COMMAND_FAILED, result, deviceCommandId); } @@ -1281,9 +1270,3 @@ void DeviceHandlerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) { void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_){ executingTask = task_; } - -void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t objectId, uint32_t parameter) { -} - -void DeviceHandlerBase::performOperationHook() { -} diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index c162210c..756ad530 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -17,11 +17,10 @@ #include #include #include -#include #include +#include #include #include -#include namespace Factory{ void setStaticFrameworkObjectIds(); @@ -30,53 +29,29 @@ void setStaticFrameworkObjectIds(); class StorageManagerIF; /** - * @defgroup devices Devices + * \defgroup devices Devices * Contains all devices and the DeviceHandlerBase class. */ /** - * @brief This is the abstract base class for device handlers. - * @details - * Documentation: Dissertation Baetz p.138,139, p.141-149 + * \brief This is the abstract base class for device handlers. * - * It features handling of @link DeviceHandlerIF::Mode_t Modes @endlink, - * communication with physical devices, using the @link DeviceCommunicationIF @endlink, - * and communication with commanding objects. + * 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 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 (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. NOTE: RMAP is a 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. + * 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. * * 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). - * The following abstract methods must be implemented by a device handler: - * 1. doStartUp() - * 2. doShutDown() - * 3. buildTransitionDeviceCommand() - * 4. buildNormalDeviceCommand() - * 5. buildCommandFromCommand() - * 6. fillCommandAndReplyMap() - * 7. scanForReply() - * 8. interpretDeviceReply() * - * Other important virtual methods with a default implementation - * are the getTransitionDelayMs() function and the getSwitches() function. - * Please ensure that getSwitches() returns DeviceHandlerIF::NO_SWITCHES if - * power switches are not implemented yet. Otherwise, the device handler will - * not transition to MODE_ON, even if setMode(MODE_ON) is called. - * If a transition to MODE_ON is desired without commanding, override the - * intialize() function and call setMode(_MODE_START_UP) before calling - * DeviceHandlerBase::initialize(). - * - * @ingroup devices + * \ingroup devices */ class DeviceHandlerBase: public DeviceHandlerIF, public HasReturnvaluesIF, @@ -92,66 +67,284 @@ public: * The constructor passes the objectId to the SystemObject(). * * @param setObjectId the ObjectId to pass to the SystemObject() Constructor - * @param maxDeviceReplyLen the largest allowed reply size + * @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() - * @param deviceCommuncation Communcation Interface object which is used to implement communication functions - * @param thermalStatePoolId - * @param thermalRequestPoolId - * @param fdirInstance - * @param cmdQueueSize */ - DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, - CookieIF * comCookie_, uint8_t setDeviceSwitch, - uint32_t thermalStatePoolId = PoolVariableIF::NO_PARAMETER, + DeviceHandlerBase(uint32_t ioBoardAddress, object_id_t setObjectId, + uint32_t maxDeviceReplyLen, uint8_t setDeviceSwitch, + object_id_t deviceCommunication, uint32_t thermalStatePoolId = + PoolVariableIF::NO_PARAMETER, uint32_t thermalRequestPoolId = PoolVariableIF::NO_PARAMETER, - FailureIsolationBase* fdirInstance = nullptr, size_t cmdQueueSize = 20); + FailureIsolationBase* fdirInstance = NULL, uint32_t cmdQueueSize = 20); + + virtual MessageQueueId_t getCommandQueue(void) const; + /** - * @brief This function is the device handler base core component and is called periodically. - * @details - * General sequence, showing where abstract virtual functions are called: - * If the State is SEND_WRITE: - * 1. Set the cookie state to COOKIE_UNUSED and read the command queue - * 2. Handles Device State Modes by calling doStateMachine(). - * This function calls callChildStatemachine() which calls the abstract functions - * doStartUp() and doShutDown() - * 3. Check switch states by calling checkSwitchStates() - * 4. Decrements counter for timeout of replies by calling decrementDeviceReplyMap() - * 5. Performs FDIR check for failures - * 6. Calls hkSwitcher.performOperation() - * 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() 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() 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 - */ + * This function is a 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 + * 2. Handles Device State Modes by calling doStateMachine(). + * This function calls callChildStatemachine() which calls the abstract functions + * doStartUp() and doShutDown() + * 3. Check switch states by calling checkSwitchStates() + * 4. Decrements counter for timeout of replies by calling decrementDeviceReplyMap() + * 5. Performs FDIR check for failures + * 6. Calls hkSwitcher.performOperation() + * 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(). + * 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() + * @param counter Specifies which Action to perform + * @return RETURN_OK for successful execution + */ virtual ReturnValue_t performOperation(uint8_t counter); - /** - * @brief Initializes the device handler - * @details - * Initialize Device Handler as system object and - * initializes all important helper classes. - * Calls fillCommandAndReplyMap(). - * @return - */ virtual ReturnValue_t initialize(); + /** + * + * @param parentQueueId + */ + virtual void setParentQueue(MessageQueueId_t parentQueueId); /** * Destructor. */ virtual ~DeviceHandlerBase(); + + ReturnValue_t executeAction(ActionId_t actionId, + MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size); + Mode_t getTransitionSourceMode() const; + Submode_t getTransitionSourceSubMode() const; + virtual void getMode(Mode_t *mode, Submode_t *submode); + HealthState getHealth(); + ReturnValue_t setHealth(HealthState health); + virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, + ParameterWrapper *parameterWrapper, + const ParameterWrapper *newValues, uint16_t startAtIndex); + /** + * Implementation of ExecutableObjectIF function + * + * Used to setup the reference of the task, that executes this component + * @param task_ Pointer to the taskIF of this task + */ + virtual void setTaskIF(PeriodicTaskIF* task_); protected: + /** + * The Returnvalues id of this class, required by HasReturnvaluesIF + */ + 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 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); + static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(10); + static const ReturnValue_t COMMAND_MAP_ERROR = MAKE_RETURN_CODE(11); + static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(12); + + //Mode handling error Codes + static const ReturnValue_t CHILD_TIMEOUT = MAKE_RETURN_CODE(0xE1); + static const ReturnValue_t SWITCH_FAILED = MAKE_RETURN_CODE(0xE2); + + static const DeviceCommandId_t RAW_COMMAND_ID = -1; + static const DeviceCommandId_t NO_COMMAND_ID = -2; + static const MessageQueueId_t NO_COMMANDER = 0; + + /** + * Pointer to the raw packet that will be sent. + */ + uint8_t *rawPacket; + /** + * Size of the #rawPacket. + */ + uint32_t rawPacketLen; + + /** + * The mode the device handler is currently in. + * + * This should never be changed directly but only with setMode() + */ + Mode_t mode; + + /** + * The submode the device handler is currently in. + * + * This should never be changed directly but only with setMode() + */ + Submode_t submode; + + /** + * This is the counter value from performOperation(). + */ + uint8_t pstStep; + + /** + * This will be used in the RMAP getRead command as expected length, is set by the constructor, can be modiefied at will. + */ + const uint32_t maxDeviceReplyLen; + + /** + * wiretapping flag: + * + * indicates either that all raw messages to and from the device should be sent to #theOneWhoWantsToReadRawTraffic + * or that all device TM should be downlinked to #theOneWhoWantsToReadRawTraffic + */ + enum WiretappingMode { + OFF = 0, RAW = 1, TM = 2 + } wiretappingMode; + + /** + * A message queue that accepts 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 defaultRawReceiver; + + store_address_t storedRawData; + + /** + * the message queue which wants to read all raw traffic + * + * if #isWiretappingActive all raw communication from and to the device will be sent to this queue + */ + MessageQueueId_t requestedRawTraffic; + + /** + * the object used to set power switches + */ + PowerSwitchIF *powerSwitcher; + + /** + * Pointer to the IPCStore. + * + * This caches the pointer received from the objectManager in the constructor. + */ + StorageManagerIF *IPCStore; + + /** + * cached for init + */ + object_id_t deviceCommunicationId; + + /** + * Communication object used for device communication + */ + DeviceCommunicationIF *communicationInterface; + + /** + * Cookie used for communication + */ + Cookie *cookie; + + /** + * The MessageQueue used to receive device handler commands and to send replies. + */ + MessageQueueIF* commandQueue; + + /** + * this is the datapool variable with the thermal state of the device + * + * can be set to PoolVariableIF::NO_PARAMETER to deactivate thermal checking + */ + uint32_t deviceThermalStatePoolId; + + /** + * this is the datapool variable with the thermal request of the device + * + * can be set to PoolVariableIF::NO_PARAMETER to deactivate thermal checking + */ + uint32_t deviceThermalRequestPoolId; + + /** + * Taking care of the health + */ + HealthHelper healthHelper; + + ModeHelper modeHelper; + + ParameterHelper parameterHelper; + + /** + * Optional Error code + * Can be set in doStartUp(), doShutDown() and doTransition() to signal cause for Transition failure. + */ + ReturnValue_t childTransitionFailure; + + uint32_t ignoreMissedRepliesCount; //!< Counts if communication channel lost a reply, so some missed replys can be ignored. + + 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. + + PeriodicTaskIF* executingTask;//!< Pointer to the task which executes this component, is invalid before setTaskIF was called. + + 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. + /** + * Helper function to report a missed reply + * + * Can be overwritten by children to act on missed replies or to fake reporting Id. + * + * @param id of the missed reply + */ + virtual void missedReply(DeviceCommandId_t id); + + /** + * Send a reply to a received device handler command. + * + * This also resets #DeviceHandlerCommand to 0. + * + * @param reply the reply type + * @param parameter parameter for the reply + */ + void replyReturnvalueToCommand(ReturnValue_t status, + uint32_t parameter = 0); + + /** + * + + * @param parameter2 additional parameter + */ + void replyToCommand(ReturnValue_t status, uint32_t parameter = 0); + + /** + * Set the device handler mode + * + * Sets #timeoutStart with every call. + * + * Sets #transitionTargetMode if necessary so transitional states can be entered from everywhere without breaking the state machine + * (which relies on a correct #transitionTargetMode). + * + * The submode is left unchanged. + * + * + * @param newMode + */ + void setMode(Mode_t newMode); + + /** + * @overload + * @param submode + */ + void setMode(Mode_t newMode, Submode_t submode); + /** * This is used to let the child class handle the transition from mode @c _MODE_START_UP to @c MODE_ON * @@ -187,457 +380,6 @@ protected: */ virtual void doShutDown() = 0; - /** - * Build the device command to send for normal mode. - * - * This is only called in @c MODE_NORMAL. If multiple submodes for @c MODE_NORMAL are supported, - * different commands can built returned depending on the submode. - * - * #rawPacket and #rawPacketLen must be set by this method to the packet to be sent. - * If variable command frequence is required, a counter can be used and - * the frequency in the reply map has to be set manually - * by calling updateReplyMap(). - * - * @param[out] id the device command id that has been built - * @return - * - @c RETURN_OK to send command after setting #rawPacket and #rawPacketLen. - * - @c NOTHING_TO_SEND when no command is to be sent. - * - Anything else triggers an even with the returnvalue as a parameter. - */ - virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) = 0; - - /** - * Build the device command to send for a transitional mode. - * - * This is only called in @c _MODE_TO_NORMAL, @c _MODE_TO_ON, @c _MODE_TO_RAW, - * @c _MODE_START_UP and @c _MODE_TO_POWER_DOWN. So it is used by doStartUp() and doShutDown() as well as doTransition() - * - * A good idea is to implement a flag indicating a command has to be built and a variable containing the command number to be built - * and filling them in doStartUp(), doShutDown() and doTransition() so no modes have to be checked here. - * - * #rawPacket and #rawPacketLen must be set by this method to the packet to be sent. - * - * @param[out] id the device command id built - * @return - * - @c RETURN_OK when a command is to be sent - * - @c NOTHING_TO_SEND when no command is to be sent - * - Anything else triggers an even with the returnvalue as a parameter - */ - virtual ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) = 0; - - /** - * @brief Build a device command packet from data supplied by a direct command. - * - * @details - * #rawPacket and #rawPacketLen should be set by this method to the packet to be sent. - * The existence of the command in the command map and the command size check - * against 0 are done by the base class. - * - * @param deviceCommand the command to build, already checked against deviceCommandMap - * @param commandData pointer to the data from the direct command - * @param commandDataLen length of commandData - * @return - * - @c RETURN_OK to send command after #rawPacket and #rawPacketLen have been set. - * - Anything else triggers an event with the returnvalue as a parameter - */ - virtual ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, - const uint8_t * commandData, size_t commandDataLen) = 0; - - /** - * @brief fill the #deviceCommandMap - * called by the initialize() of the base class - * @details - * This is used to let the base class know which replies are expected. - * There are different scenarios regarding this: - * - "Normal" commands. These are commands, that trigger a direct reply from the device. - * In this case, the id of the command should be added to the command map - * with a commandData_t where maxDelayCycles is set to the maximum expected - * number of PST cycles the reply will take. Then, scanForReply returns - * the id of the command and the base class can handle time-out and missing replies. - * - Periodic, unrequested replies. These are replies that, once enabled, are sent by the device - * on its own in a defined interval. In this case, the id of the reply - * or a placeholder id should be added to the deviceCommandMap with a commandData_t - * where maxDelayCycles is set to the maximum expected number of PST cycles between - * two replies (also a tolerance should be added, as an FDIR message will be generated if it is missed). - * As soon as the replies are enabled, DeviceCommandInfo.periodic must be set to 1, - * DeviceCommandInfo.delayCycles to DeviceCommandInfo.MaxDelayCycles. - * From then on, the base class handles the reception. - * Then, scanForReply returns the id of the reply or the placeholder id and the base class will - * take care of checking that all replies are received and the interval is correct. - * When the replies are disabled, DeviceCommandInfo.periodic must be set to 0, - * DeviceCommandInfo.delayCycles to 0; - * - Aperiodic, unrequested replies. These are replies that are sent - * by the device without any preceding command and not in a defined interval. - * These are not entered in the deviceCommandMap but handled by returning @c APERIODIC_REPLY in scanForReply(). - * - */ - virtual void fillCommandAndReplyMap() = 0; - - /** - * @brief Scans a buffer for a valid reply. - * @details - * This is used by the base class to check the data received for valid packets. - * It only checks if a valid packet starts at @c start. - * It also only checks the structural validy of the packet, - * e.g. checksums lengths and protocol data. - * No information check is done, e.g. range checks etc. - * - * Errors should be reported directly, the base class does NOT report - * any errors based on the returnvalue of this function. - * - * @param start start of remaining buffer to be scanned - * @param len length of remaining buffer to be scanned - * @param[out] foundId the id of the data found in the buffer. - * @param[out] foundLen length of the data found. Is to be set in function, - * buffer is scanned at previous position + foundLen. - * @return - * - @c RETURN_OK a valid packet was found at @c start, @c foundLen is valid - * - @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, - * e.g. checksum error, implies @c foundLen is valid, can be used to skip some bytes - * - @c DeviceHandlerIF::LENGTH_MISSMATCH @c len is invalid - * - @c DeviceHandlerIF::IGNORE_REPLY_DATA Ignore this specific part of the packet - * - @c DeviceHandlerIF::IGNORE_FULL_PACKET Ignore the packet - * - @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, size_t remainingSize, - DeviceCommandId_t *foundId, size_t *foundLen) = 0; - - /** - * @brief Interpret a reply from the device. - * @details - * This is called after scanForReply() found a valid packet, it can be assumed that the length and structure is valid. - * This routine extracts the data from the packet into a DataSet and then calls handleDeviceTM(), which either sends - * a TM packet or stores the data in the DataPool depending on whether the it was an external command. - * No packet length is given, as it should be defined implicitly by the id. - * - * @param id the id found by scanForReply() - * @param packet - * @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 - */ - virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, - const uint8_t *packet) = 0; - - /** - * set all datapool variables that are update periodically in normal mode invalid - * - * Child classes should provide an implementation which sets all those variables invalid - * which are set periodically during any normal mode. - */ - virtual void setNormalDatapoolEntriesInvalid() = 0; - - /** - * @brief Can be implemented by child handler to - * perform debugging - * @details Example: Calling this in performOperation - * to track values like mode. - * @param positionTracker Provide the child handler a way to know where the debugInterface was called - * @param objectId Provide the child handler object Id to specify actions for spefic devices - * @param parameter Supply a parameter of interest - * Please delete all debugInterface calls in DHB after debugging is finished ! - */ - virtual void debugInterface(uint8_t positionTracker = 0, object_id_t objectId = 0, uint32_t parameter = 0); - - /** - * Get the time needed to transit from modeFrom to modeTo. - * - * Used for the following transitions: - * modeFrom -> modeTo: - * - MODE_ON -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] - * - MODE_NORMAL -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] - * - MODE_RAW -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] - * - _MODE_START_UP -> MODE_ON (do not include time to set the switches, the base class got you covered) - * - * The default implementation returns 0 ! - * @param modeFrom - * @param modeTo - * @return time in ms - */ - virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo); - - /** - * Return the switches connected to the device. - * - * The default implementation returns one switch set in the ctor. - * - * @param[out] switches pointer to an array of switches - * @param[out] numberOfSwitches length of returned array - * @return - * - @c RETURN_OK if the parameters were set - * - @c NO_SWITCH or any other returnvalue if no switches exist - */ - virtual ReturnValue_t getSwitches(const uint8_t **switches, - uint8_t *numberOfSwitches); - - /** - * Can be used to perform device specific periodic operations. - * This is called on the SEND_READ step of the performOperation() call - */ - virtual void performOperationHook(); - - /** - * The Returnvalues id of this class, required by HasReturnvaluesIF - */ - static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE; - -public: - /** - * @param parentQueueId - */ - virtual void setParentQueue(MessageQueueId_t parentQueueId); - - /** - * This function call handles the execution of external commands as required - * by the HasActionIF. - * @param actionId - * @param commandedBy - * @param data - * @param size - * @return - */ - ReturnValue_t executeAction(ActionId_t actionId, - MessageQueueId_t commandedBy, const uint8_t* data, size_t size); - - Mode_t getTransitionSourceMode() const; - Submode_t getTransitionSourceSubMode() const; - virtual void getMode(Mode_t *mode, Submode_t *submode); - HealthState getHealth(); - ReturnValue_t setHealth(HealthState health); - virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, - ParameterWrapper *parameterWrapper, - const ParameterWrapper *newValues, uint16_t startAtIndex); - /** - * Implementation of ExecutableObjectIF function - * - * Used to setup the reference of the task, that executes this component - * @param task_ Pointer to the taskIF of this task - */ - virtual void setTaskIF(PeriodicTaskIF* task_); - virtual MessageQueueId_t getCommandQueue(void) const; - -protected: - //Mode handling error Codes - static const ReturnValue_t CHILD_TIMEOUT = MAKE_RETURN_CODE(0xE1); - static const ReturnValue_t SWITCH_FAILED = MAKE_RETURN_CODE(0xE2); - - static const DeviceCommandId_t RAW_COMMAND_ID = -1; - static const DeviceCommandId_t NO_COMMAND_ID = -2; - static const MessageQueueId_t NO_COMMANDER = 0; - - /** - * Pointer to the raw packet that will be sent. - */ - uint8_t *rawPacket = nullptr; - /** - * Size of the #rawPacket. - */ - size_t rawPacketLen = 0; - - /** - * The mode the device handler is currently in. - * - * This should never be changed directly but only with setMode() - */ - Mode_t mode; - - /** - * The submode the device handler is currently in. - * - * This should never be changed directly but only with setMode() - */ - Submode_t submode; - - /** - * This is the counter value from performOperation(). - */ - uint8_t pstStep = 0; - - /** - * wiretapping flag: - * - * indicates either that all raw messages to and from the device should be sent to #theOneWhoWantsToReadRawTraffic - * or that all device TM should be downlinked to #theOneWhoWantsToReadRawTraffic - */ - enum WiretappingMode: uint8_t { - OFF = 0, RAW = 1, TM = 2 - } wiretappingMode; - - /** - * A message queue that accepts 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 defaultRawReceiver = 0; - - store_address_t storedRawData; - - /** - * the message queue which wants to read all raw traffic - * - * if #isWiretappingActive all raw communication from and to the device will be sent to this queue - */ - MessageQueueId_t requestedRawTraffic = 0; - - /** - * the object used to set power switches - */ - PowerSwitchIF *powerSwitcher = nullptr; - - /** - * Pointer to the IPCStore. - * - * This caches the pointer received from the objectManager in the constructor. - */ - StorageManagerIF *IPCStore = nullptr; - - /** - * cached for init - */ - object_id_t deviceCommunicationId; - - /** - * Communication object used for device communication - */ - DeviceCommunicationIF *communicationInterface = nullptr; - - /** - * Cookie used for communication. This is passed to the communication - * interface. - */ - CookieIF *comCookie; - - struct DeviceCommandInfo { - bool isExecuting; //!< Indicates if the command is already executing. - uint8_t expectedReplies; //!< Dynamic value to indicate how many replies are expected. Inititated with 0. - MessageQueueId_t sendReplyTo; //!< if this is != NO_COMMANDER, DHB was commanded externally and shall report everything to commander. - }; - typedef std::map DeviceCommandMap; - typedef DeviceCommandMap::iterator DeviceCommandIter; - - /** - * @brief Information about expected replies - * - * This is used to keep track of pending replies - */ - struct DeviceReplyInfo { - uint16_t maxDelayCycles; //!< The maximum number of cycles the handler should wait for a reply to this command. - uint16_t delayCycles; //!< The currently remaining cycles the handler should wait for a reply, 0 means there is no reply expected - size_t replyLen = 0; //!< Expected size of the reply. - 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. - }; - - typedef std::map DeviceReplyMap; - typedef DeviceReplyMap::iterator DeviceReplyIter; - - /** - * The MessageQueue used to receive device handler commands and to send replies. - */ - MessageQueueIF* commandQueue = nullptr; - - /** - * this is the datapool variable with the thermal state of the device - * - * can be set to PoolVariableIF::NO_PARAMETER to deactivate thermal checking - */ - uint32_t deviceThermalStatePoolId; - - /** - * this is the datapool variable with the thermal request of the device - * - * can be set to PoolVariableIF::NO_PARAMETER to deactivate thermal checking - */ - uint32_t deviceThermalRequestPoolId; - - /** - * Taking care of the health - */ - HealthHelper healthHelper; - - ModeHelper modeHelper; - - ParameterHelper parameterHelper; - - /** - * Optional Error code - * Can be set in doStartUp(), doShutDown() and doTransition() to signal cause for Transition failure. - */ - ReturnValue_t childTransitionFailure = RETURN_OK; - - uint32_t ignoreMissedRepliesCount = 0; //!< Counts if communication channel lost a reply, so some missed replys can be ignored. - - 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. - - PeriodicTaskIF* executingTask;//!< Pointer to the task which executes this component, is invalid before setTaskIF was called. - - 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. - - /** - * Set the device handler mode - * - * Sets #timeoutStart with every call. - * - * Sets #transitionTargetMode if necessary so transitional states can be entered from everywhere without breaking the state machine - * (which relies on a correct #transitionTargetMode). - * - * The submode is left unchanged. - * - * - * @param newMode - */ - void setMode(Mode_t newMode); - - /** - * @overload - * @param submode - */ - void setMode(Mode_t newMode, Submode_t submode); - - /** - * Helper function to report a missed reply - * - * Can be overwritten by children to act on missed replies or to fake reporting Id. - * - * @param id of the missed reply - */ - virtual void missedReply(DeviceCommandId_t id); - - /** - * Send a reply to a received device handler command. - * - * This also resets #DeviceHandlerCommand to 0. - * - * @param reply the reply type - * @param parameter parameter for the reply - */ - void replyReturnvalueToCommand(ReturnValue_t status, - uint32_t parameter = 0); - - /** - * Send reply to a command, differentiate between raw command - * and normal command. - * @param status - * @param parameter - */ - void replyToCommand(ReturnValue_t status, uint32_t parameter = 0); - /** * Do the transition to the main modes (MODE_ON, MODE_NORMAL and MODE_RAW). * @@ -667,18 +409,144 @@ protected: */ virtual void doTransition(Mode_t modeFrom, Submode_t subModeFrom); + /** + * Get the time needed to transit from modeFrom to modeTo. + * + * Used for the following transitions: + * modeFrom -> modeTo: + * MODE_ON -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] + * MODE_NORMAL -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] + * MODE_RAW -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] + * _MODE_START_UP -> MODE_ON (do not include time to set the switches, the base class got you covered) + * + * The default implementation returns 0; + * + * @param modeFrom + * @param modeTo + * @return time in ms + */ + virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo); + + /** + * Is the combination of mode and submode valid? + * + * @param mode + * @param submode + * @return + * - @c RETURN_OK if valid + * - @c RETURN_FAILED if invalid + */ + virtual ReturnValue_t isModeCombinationValid(Mode_t mode, + Submode_t submode); + + /** + * Get the Rmap action for the current step. + * + * The step number can be read from #pstStep. + * + * @return The Rmap action to execute in this step + */ + virtual RmapAction_t getRmapAction(); + + /** + * Build the device command to send for normal mode. + * + * This is only called in @c MODE_NORMAL. If multiple submodes for @c MODE_NORMAL are supported, + * different commands can built returned depending on the submode. + * + * #rawPacket and #rawPacketLen must be set by this method to the packet to be sent. + * + * @param[out] id the device command id that has been built + * @return + * - @c RETURN_OK when a command is to be sent + * - not @c RETURN_OK when no command is to be sent + */ + virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) = 0; + + /** + * Build the device command to send for a transitional mode. + * + * This is only called in @c _MODE_TO_NORMAL, @c _MODE_TO_ON, @c _MODE_TO_RAW, + * @c _MODE_START_UP and @c _MODE_TO_POWER_DOWN. So it is used by doStartUp() and doShutDown() as well as doTransition() + * + * A good idea is to implement a flag indicating a command has to be built and a variable containing the command number to be built + * and filling them in doStartUp(), doShutDown() and doTransition() so no modes have to be checked here. + * + * #rawPacket and #rawPacketLen must be set by this method to the packet to be sent. + * + * @param[out] id the device command id built + * @return + * - @c RETURN_OK when a command is to be sent + * - not @c RETURN_OK when no command is to be sent + */ + virtual ReturnValue_t buildTransitionDeviceCommand( + DeviceCommandId_t * id) = 0; + + /** + * Build the device command to send for raw mode. + * + * This is only called in @c MODE_RAW. It is for the rare case that in raw mode packets + * are to be sent by the handler itself. It is NOT needed for the raw commanding service. + * Its only current use is in the STR handler which gets its raw packets from a different + * source. + * Also it can be used for transitional commands, to get the device ready for @c MODE_RAW + * + * As it is almost never used, there is a default implementation returning @c NOTHING_TO_SEND. + * + * #rawPacket and #rawPacketLen must be set by this method to the packet to be sent. + * + * @param[out] id the device command id built + * @return + * - @c RETURN_OK when a command is to be sent + * - not @c NOTHING_TO_SEND when no command is to be sent + */ + virtual ReturnValue_t buildChildRawCommand(); + + /** + * Build a device command packet from data supplied by a direct command. + * + * #rawPacket and #rawPacketLen should be set by this method to the packet to be sent. + * + * @param deviceCommand the command to build, already checked against deviceCommandMap + * @param commandData pointer to the data from the direct command + * @param commandDataLen length of commandData + * @return + * - @c RETURN_OK when #rawPacket is valid + * - @c RETURN_FAILED when #rawPacket is invalid and no data should be sent + */ + virtual ReturnValue_t buildCommandFromCommand( + DeviceCommandId_t deviceCommand, const uint8_t * commandData, + size_t commandDataLen) = 0; + + /** + * fill the #deviceCommandMap + * + * called by the initialize() of the base class + * + * This is used to let the base class know which replies are expected. + * There are different scenarios regarding this: + * - "Normal" commands. These are commands, that trigger a direct reply from the device. In this case, the id of the command should be added to the command map + * with a commandData_t where maxDelayCycles is set to the maximum expected number of PST cycles the reply will take. Then, scanForReply returns the id of the command and the base class can handle time-out and missing replies. + * - Periodic, unrequested replies. These are replies that, once enabled, are sent by the device on its own in a defined interval. In this case, the id of the reply or a placeholder id should be added to the deviceCommandMap + * with a commandData_t where maxDelayCycles is set to the maximum expected number of PST cycles between two replies (also a tolerance should be added, as an FDIR message will be generated if it is missed). + * As soon as the replies are enabled, DeviceCommandInfo.periodic must be set to 1, DeviceCommandInfo.delayCycles to DeviceCommandInfo.MaxDelayCycles. From then on, the base class handles the reception. + * Then, scanForReply returns the id of the reply or the placeholder id and the base class will take care of checking that all replies are received and the interval is correct. + * When the replies are disabled, DeviceCommandInfo.periodic must be set to 0, DeviceCommandInfo.delayCycles to 0; + * - Aperiodic, unrequested replies. These are replies that are sent by the device without any preceding command and not in a defined interval. These are not entered in the deviceCommandMap but handled by returning @c APERIODIC_REPLY in scanForReply(). + * + */ + virtual void fillCommandAndReplyMap() = 0; + /** * This is a helper method to facilitate inserting entries in the command map. * @param deviceCommand Identifier of the command to add. * @param maxDelayCycles The maximum number of delay cycles the command waits until it times out. - * @param periodic Indicates if the reply is periodic (i.e. it is sent by the device repeatedly without request) or not. + * @param periodic Indicates if the command is periodic (i.e. it is sent by the device repeatedly without request) or not. * Default is aperiodic (0) - * @param hasDifferentReplyId - * @param replyId * @return RETURN_OK when the command was successfully inserted, COMMAND_MAP_ERROR else. */ ReturnValue_t insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, - uint16_t maxDelayCycles, size_t replyLen = 0, uint8_t periodic = 0, + uint16_t maxDelayCycles, uint8_t periodic = 0, bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0); /** * This is a helper method to insert replies in the reply map. @@ -689,7 +557,7 @@ protected: * @return RETURN_OK when the command was successfully inserted, COMMAND_MAP_ERROR else. */ ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, - uint16_t maxDelayCycles, size_t replyLen = 0, uint8_t periodic = 0); + uint16_t maxDelayCycles, uint8_t periodic = 0); /** * A simple command to add a command to the commandList. * @param deviceCommand The command to add @@ -715,47 +583,48 @@ protected: * @return The current delay count. If the command does not exist (should never happen) it returns 0. */ uint8_t getReplyDelayCycles(DeviceCommandId_t deviceCommand); - /** - * Is the combination of mode and submode valid? + * Scans a buffer for a valid reply. * - * @param mode - * @param submode + * This is used by the base class to check the data received from the RMAP stack for valid packets. + * It only checks if a valid packet starts at @c start. + * It also only checks the structural validy of the packet, eg checksums lengths and protocol data. No + * information check is done, eg range checks etc. + * + * Errors should be reported directly, the base class does NOT report any errors based on the return + * value of this function. + * + * @param start start of data + * @param len length of data + * @param[out] foundId the id of the packet starting at @c start + * @param[out] foundLen length of the packet found * @return - * - @c RETURN_OK if valid - * - @c RETURN_FAILED if invalid + * - @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 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 isModeCombinationValid(Mode_t mode, - Submode_t submode); + virtual ReturnValue_t scanForReply(const uint8_t *start, uint32_t len, + DeviceCommandId_t *foundId, uint32_t *foundLen) = 0; /** - * Get the Rmap action for the current step. + * Interpret a reply from the device. * - * The step number can be read from #pstStep. + * This is called after scanForReply() found a valid packet, it can be assumed that the length and structure is valid. + * This routine extracts the data from the packet into a DataSet and then calls handleDeviceTM(), which either sends + * a TM packet or stores the data in the DataPool depending on whether the it was an external command. + * No packet length is given, as it should be defined implicitly by the id. * - * @return The Rmap action to execute in this step - */ - virtual CommunicationAction_t getComAction(); - - /** - * Build the device command to send for raw mode. - * - * This is only called in @c MODE_RAW. It is for the rare case that in raw mode packets - * are to be sent by the handler itself. It is NOT needed for the raw commanding service. - * Its only current use is in the STR handler which gets its raw packets from a different - * source. - * Also it can be used for transitional commands, to get the device ready for @c MODE_RAW - * - * As it is almost never used, there is a default implementation returning @c NOTHING_TO_SEND. - * - * #rawPacket and #rawPacketLen must be set by this method to the packet to be sent. - * - * @param[out] id the device command id built + * @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 a command is to be sent - * - not @c NOTHING_TO_SEND when no command is to be sent + * - @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 */ - virtual ReturnValue_t buildChildRawCommand(); + virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, + const uint8_t *packet) = 0; /** * Construct a command reply containing a raw reply. @@ -780,11 +649,33 @@ protected: */ void replyRawReplyIfnotWiretapped(const uint8_t *data, size_t len); + /** + * Return the switches connected to the device. + * + * The default implementation returns one switch set in the ctor. + * + * + * @param[out] switches pointer to an array of switches + * @param[out] numberOfSwitches length of returned array + * @return + * - @c RETURN_OK if the parameters were set + * - @c RETURN_FAILED if no switches exist + */ + virtual ReturnValue_t getSwitches(const uint8_t **switches, + uint8_t *numberOfSwitches); + /** * notify child about mode change */ virtual void modeChanged(void); + struct DeviceCommandInfo { + bool isExecuting; //!< Indicates if the command is already executing. + uint8_t expectedReplies; //!< Dynamic value to indicate how many replies are expected. + MessageQueueId_t sendReplyTo; //!< if this is != NO_COMMANDER, DHB was commanded externally and shall report everything to commander. + }; + + typedef std::map DeviceCommandMap; /** * Enable the reply checking for a command * @@ -795,16 +686,16 @@ protected: * When found, copies maxDelayCycles to delayCycles in the reply information and sets the command to * expect one reply. * - * Can be overwritten by the child, if a command activates multiple replies - * or replyId differs from commandId. + * Can be overwritten by the child, if a command activates multiple replies or replyId differs from + * commandId. * Notes for child implementations: * - If the command was not found in the reply map, NO_REPLY_EXPECTED MUST be returned. * - A failure code may be returned if something went fundamentally wrong. * * @param deviceCommand * @return - RETURN_OK if a reply was activated. - * - NO_REPLY_EXPECTED if there was no reply found. This is not an - * error case as many commands do not expect a reply. + * - NO_REPLY_EXPECTED if there was no reply found. This is not an error case as many commands + * do not expect a reply. */ virtual ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator cmd, uint8_t expectedReplies = 1, bool useAlternateId = false, @@ -820,6 +711,14 @@ protected: */ ReturnValue_t getStateOfSwitches(void); + /** + * set all datapool variables that are update periodically in normal mode invalid + * + * Child classes should provide an implementation which sets all those variables invalid + * which are set periodically during any normal mode. + */ + virtual void setNormalDatapoolEntriesInvalid() = 0; + /** * build a list of sids and pass it to the #hkSwitcher */ @@ -848,6 +747,7 @@ protected: virtual void startTransition(Mode_t mode, Submode_t submode); virtual void setToExternalControl(); virtual void announceMode(bool recursive); + virtual ReturnValue_t letChildHandleMessage(CommandMessage *message); /** @@ -894,6 +794,22 @@ protected: bool commandIsExecuting(DeviceCommandId_t commandId); + /** + * Information about expected replies + * + * This is used to keep track of pending replies + */ + struct DeviceReplyInfo { + uint16_t maxDelayCycles; //!< The maximum number of cycles the handler should wait for a reply to this command. + uint16_t delayCycles; //!< The currently remaining cycles the handler should wait for a reply, 0 means there is no reply expected + 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. + */ + typedef std::map DeviceReplyMap; /** * This map is used to check and track correct reception of all replies. * @@ -913,13 +829,12 @@ protected: DeviceCommandMap deviceCommandMap; ActionHelper actionHelper; - private: /** * State a cookie is in. * - * Used to keep track of the state of the communication. + * Used to keep track of the state of the RMAP communication. */ enum CookieState_t { COOKIE_UNUSED, //!< The Cookie is unused @@ -946,12 +861,17 @@ private: */ CookieInfo cookieInfo; + /** + * cached from ctor for initialize() + */ + const uint32_t ioBoardAddress; + /** * Used for timing out mode transitions. * * Set when setMode() is called. */ - uint32_t timeoutStart = 0; + uint32_t timeoutStart; /** * Delay for the current mode transition, used for time out @@ -993,20 +913,22 @@ private: * - checks whether commanded mode transitions are required and calls handleCommandedModeTransition() * - does the necessary action for the current mode or calls doChildStateMachine in modes @c MODE_TO_ON and @c MODE_TO_OFF * - actions that happen in transitions (eg setting a timeout) are handled in setMode() - * - Maybe export this into own class to increase modularity of software - * and reduce the massive class size ? */ void doStateMachine(void); void buildRawDeviceCommand(CommandMessage* message); void buildInternalCommand(void); +// /** +// * Send a reply with the current mode and submode. +// */ +// void announceMode(void); + /** * Decrement the counter for the timout of replies. * * 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); @@ -1073,8 +995,8 @@ private: * - @c RETURN_FAILED IPCStore is NULL * - the return value from the IPCStore if it was not @c RETURN_OK */ - ReturnValue_t getStorageData(store_address_t storageAddress, - uint8_t ** data, size_t * len); + ReturnValue_t getStorageData(store_address_t storageAddress, uint8_t **data, + uint32_t *len); /** * set all switches returned by getSwitches() @@ -1103,16 +1025,9 @@ private: * - @c RETURN_FAILED when cookies could not be changed, eg because the newChannel is not enabled * - @c returnvalues of RMAPChannelIF::isActive() */ - //ReturnValue_t switchCookieChannel(object_id_t newChannelId); + ReturnValue_t switchCookieChannel(object_id_t newChannelId); - /** - * Handle device handler messages (e.g. commands sent by PUS Service 2) - * @param message - * @return - */ ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message); - - }; #endif /* DEVICEHANDLERBASE_H_ */ diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index 34aa4114..fe0ee8e8 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -8,8 +8,7 @@ #include /** - * @brief This is the Interface used to communicate with a device handler. - * @details Includes all expected return values, events and modes. + * This is the Interface used to communicate with a device handler. * */ class DeviceHandlerIF { @@ -23,95 +22,80 @@ 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. + static const Mode_t MODE_RAW = 3; //!< The device is powered on and ready to perform operations. In this mode, raw commands can be sent. The device handler will send all replies received from the command back to the commanding object. + 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_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 + static const Mode_t _MODE_POWER_ON = TRANSITION_MODE_BASE_ACTION_MASK | 2; //!< This is a transitional state which can not be commanded. The device will be switched on in this state. After the command to set the switch on has been sent, the mode changes to @c MODE_WAIT_ON + static const Mode_t _MODE_WAIT_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 3; //!< This is a transitional state which can not be commanded. The switch has been commanded off and the handler waits for it to be off. When the switch is off, the mode changes to @c MODE_OFF. + static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4; //!< This is a transitional state which can not be commanded. The switch has been commanded on and the handler waits for it to be on. When the switch is on, the mode changes to @c MODE_TO_ON. + static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5; //!< This is a transitional state which can not be commanded. The switch has been commanded off and is off now. This state is only to do an RMAP cycle once more where the doSendRead() function will set the mode to MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board - // 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. - static const Mode_t MODE_RAW = 3; //!< The device is powered on and ready to perform operations. In this mode, raw commands can be sent. The device handler will send all replies received from the command back to the commanding object. - 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; //!< 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 - static const Mode_t _MODE_POWER_ON = TRANSITION_MODE_BASE_ACTION_MASK | 2; //!< This is a transitional state which can not be commanded. The device will be switched on in this state. After the command to set the switch on has been sent, the mode changes to @c MODE_WAIT_ON - static const Mode_t _MODE_WAIT_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 3; //!< This is a transitional state which can not be commanded. The switch has been commanded off and the handler waits for it to be off. When the switch is off, the mode changes to @c MODE_OFF. - static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4; //!< This is a transitional state which can not be commanded. The switch has been commanded on and the handler waits for it to be on. When the switch is on, the mode changes to @c MODE_TO_ON. - static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5; //!< This is a transitional state which can not be commanded. The switch has been commanded off and is off now. This state is only to do an RMAP cycle once more where the doSendRead() function will set the mode to MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CDH; + static const Event DEVICE_BUILDING_COMMAND_FAILED = MAKE_EVENT(0, SEVERITY::LOW); + static const Event DEVICE_SENDING_COMMAND_FAILED = MAKE_EVENT(1, SEVERITY::LOW); + static const Event DEVICE_REQUESTING_REPLY_FAILED = MAKE_EVENT(2, SEVERITY::LOW); + static const Event DEVICE_READING_REPLY_FAILED = MAKE_EVENT(3, SEVERITY::LOW); + static const Event DEVICE_INTERPRETING_REPLY_FAILED = MAKE_EVENT(4, SEVERITY::LOW); + static const Event DEVICE_MISSED_REPLY = MAKE_EVENT(5, SEVERITY::LOW); + static const Event DEVICE_UNKNOWN_REPLY = MAKE_EVENT(6, SEVERITY::LOW); + static const Event DEVICE_UNREQUESTED_REPLY = MAKE_EVENT(7, SEVERITY::LOW); + static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, SEVERITY::LOW); //!< Indicates a SW bug in child class. + 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 SUBSYSTEM_ID = SUBSYSTEM_ID::CDH; - static const Event DEVICE_BUILDING_COMMAND_FAILED = MAKE_EVENT(0, SEVERITY::LOW); - static const Event DEVICE_SENDING_COMMAND_FAILED = MAKE_EVENT(1, SEVERITY::LOW); - static const Event DEVICE_REQUESTING_REPLY_FAILED = MAKE_EVENT(2, SEVERITY::LOW); - static const Event DEVICE_READING_REPLY_FAILED = MAKE_EVENT(3, SEVERITY::LOW); - static const Event DEVICE_INTERPRETING_REPLY_FAILED = MAKE_EVENT(4, SEVERITY::LOW); - static const Event DEVICE_MISSED_REPLY = MAKE_EVENT(5, SEVERITY::LOW); - static const Event DEVICE_UNKNOWN_REPLY = MAKE_EVENT(6, SEVERITY::LOW); - static const Event DEVICE_UNREQUESTED_REPLY = MAKE_EVENT(7, SEVERITY::LOW); - static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, SEVERITY::LOW); //!< Indicates a SW bug in child class. - 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 = 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); + static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3); + static const ReturnValue_t CANT_SWITCH_IOBOARD = MAKE_RETURN_CODE(0xA4); + static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA5); + static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA6); + 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); - static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF; + //standard codes used in scan for reply + // static const ReturnValue_t TOO_SHORT = MAKE_RETURN_CODE(0xB1); + static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB2); + static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB3); + static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB4); + static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB5); - // Standard codes used when building commands. - static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(0xA0); //!< Return this if no command sending in required - // Mostly used for internal handling. - static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA2); //!< If the command size is 0. Checked in DHB - static const ReturnValue_t NO_REPLY_EXPECTED = MAKE_RETURN_CODE(0xA3); //!< Used to indicate that this is a command-only command. - static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA4); //!< Command ID not in commandMap. Checked in DHB - static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA5); //!< Command was already executed. Checked in DHB - static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA6); - static const ReturnValue_t CANT_SWITCH_ADDRESS = MAKE_RETURN_CODE(0xA7); - static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA8); - static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA9); - static const ReturnValue_t BUSY = MAKE_RETURN_CODE(0xAA); - static const ReturnValue_t NON_OP_TEMPERATURE = MAKE_RETURN_CODE(0xAB); - static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xAC); + //standard codes used in interpret device reply + static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC1); //the device reported, that it did not execute the command + static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC2); + static const ReturnValue_t UNKNOW_DEVICE_REPLY = MAKE_RETURN_CODE(0xC3); //the deviceCommandId reported by scanforReply is unknown + static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC4); //syntax etc is correct but still not ok, eg parameters where none are expected - // Standard codes used in scanForReply - static const ReturnValue_t APERIODIC_REPLY = MAKE_RETURN_CODE(0xB1); //!< This is used to specify for replies from a device which are not replies to requests - static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB2); - static const ReturnValue_t IGNORE_REPLY_DATA = MAKE_RETURN_CODE(0xB3); //!< Ignore parts of the received packet - static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE(0xB4); //!< Ignore full received packet - static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB5); - static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB6); - static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB7); - - // Standard codes used in interpretDeviceReply - static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC1); //the device reported, that it did not execute the command - static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC2); - static const ReturnValue_t UNKNOW_DEVICE_REPLY = MAKE_RETURN_CODE(0xC3); //the deviceCommandId reported by scanforReply is unknown - static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC4); //syntax etc is correct but still not ok, eg parameters where none are expected - - // Standard codes used in buildCommandFromCommand - static const ReturnValue_t INVALID_COMMAND_PARAMETER = MAKE_RETURN_CODE(0xD0); - static const ReturnValue_t INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS = MAKE_RETURN_CODE(0xD1); - - // Standard codes used in getSwitches - static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(0xE1); //!< Return in getSwitches() to specify there are no switches - - // static const ReturnValue_t ONE_SWITCH = MAKE_RETURN_CODE(8); - // static const ReturnValue_t TWO_SWITCHES = MAKE_RETURN_CODE(9); - // where is this used? - // static const ReturnValue_t COMMAND_MAP_ERROR = MAKE_RETURN_CODE(11); - - /** - * Communication action that will be executed. - * - * This is used by the child class to tell the base class what to do. - */ - enum CommunicationAction_t: uint8_t { - SEND_WRITE,//!< Send write - GET_WRITE, //!< Get write - SEND_READ, //!< Send read - GET_READ, //!< Get read - NOTHING //!< Do nothing. - }; + //Standard codes used in buildCommandFromCommand + static const ReturnValue_t INVALID_COMMAND_PARAMETER = MAKE_RETURN_CODE( + 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 */ From 0cb2abfe7e2d902fdfd4ba676ee6ae6c049fa703 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 19 Apr 2020 13:26:40 +0200 Subject: [PATCH 016/653] old cookie added again will be replaced in separate branch/pull request --- devicehandlers/Cookie.h | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 devicehandlers/Cookie.h diff --git a/devicehandlers/Cookie.h b/devicehandlers/Cookie.h new file mode 100644 index 00000000..495c8c40 --- /dev/null +++ b/devicehandlers/Cookie.h @@ -0,0 +1,10 @@ +#ifndef COOKIE_H_ +#define COOKIE_H_ + +class Cookie{ +public: + virtual ~Cookie(){} +}; + + +#endif /* COOKIE_H_ */ From 0c0c8ec4486dffc3563f384ea95c8e8b02896f02 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 19 Apr 2020 13:29:50 +0200 Subject: [PATCH 017/653] device handler base indentation --- devicehandlers/DeviceHandlerBase.cpp | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 22d49d37..77483d06 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -21,20 +21,19 @@ DeviceHandlerBase::DeviceHandlerBase(uint32_t ioBoardAddress, 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(), ioBoardAddress(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; From 574d6051bab05db9edb7cd62d695758588b136e4 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 19 Apr 2020 13:41:43 +0200 Subject: [PATCH 018/653] new returnvalue for scanForReply to ignore full packet DeviceCommunicationIF sendMessage function takes const data pointer now --- devicehandlers/DeviceCommunicationIF.h | 25 +++++++++++++++++-- devicehandlers/DeviceHandlerBase.cpp | 2 ++ devicehandlers/DeviceHandlerBase.h | 34 +++++++++++++++++--------- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/devicehandlers/DeviceCommunicationIF.h b/devicehandlers/DeviceCommunicationIF.h index e0aca573..b24e7d37 100644 --- a/devicehandlers/DeviceCommunicationIF.h +++ b/devicehandlers/DeviceCommunicationIF.h @@ -39,14 +39,35 @@ 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 - @c RETURN_OK for successfull send + * - Everything else triggers sending failed event with + * returnvalue as parameter 1 + */ + 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 - @c RETURN_OK for successfull receive + * - Everything else triggers receiving failed with returnvalue + * as parameter 1 + */ virtual ReturnValue_t readReceivedMessage(Cookie *cookie, uint8_t **buffer, uint32_t *size) = 0; diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 77483d06..bd304603 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -538,6 +538,8 @@ void DeviceHandlerBase::doGetRead() { break; case IGNORE_REPLY_DATA: break; + case IGNORE_FULL_PACKET: + return; default: //We need to wait for timeout.. don't know what command failed and who sent it. replyRawReplyIfnotWiretapped(receivedData, foundLen); diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 756ad530..871c9153 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -143,8 +143,10 @@ 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 IGNORE_REPLY_DATA = MAKE_RETURN_CODE(6); + 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); //!< Ignore parts of the received packet + static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE(7); //!< Ignore full received packet + // static const ReturnValue_t ONE_SWITCH = MAKE_RETURN_CODE(8); // static const ReturnValue_t TWO_SWITCHES = MAKE_RETURN_CODE(9); static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(10); @@ -583,6 +585,7 @@ protected: * @return The current delay count. If the command does not exist (should never happen) it returns 0. */ uint8_t getReplyDelayCycles(DeviceCommandId_t deviceCommand); + /** * Scans a buffer for a valid reply. * @@ -594,16 +597,25 @@ protected: * Errors should be reported directly, the base class does NOT report any errors based on the return * value of this function. * - * @param start start of data - * @param len length of data - * @param[out] foundId the id of the packet starting at @c start - * @param[out] foundLen length of the packet found + * @param start start of remaining buffer to be scanned + * @param len length of remaining buffer to be scanned + * @param[out] foundId the id of the data found in the buffer. + * @param[out] foundLen length of the data found. Is to be set in function, buffer is scanned at previous position + foundLen. * @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 APERIODIC_REPLY if a valid reply is received that has not been requested by a command, but should be handled anyway (@see also fillCommandAndCookieMap() ) + * - @c RETURN_OK a valid packet was found at @c start, @c foundLen is valid + * - @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, + * e.g. checksum error, implies @c foundLen is valid, can be used to + * skip some bytes + * - @c DeviceHandlerIF::LENGTH_MISSMATCH @c len is invalid + * - @c DeviceHandlerIF::IGNORE_REPLY_DATA Ignore this specific part of + * the packet + * - @c DeviceHandlerIF::IGNORE_FULL_PACKET Ignore the packet + * - @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, DeviceCommandId_t *foundId, uint32_t *foundLen) = 0; From 7126c19ee05a17412107cf7dc738c967fb0d3c3a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 19 Apr 2020 14:03:47 +0200 Subject: [PATCH 019/653] Restructured header file Abstract functions are closer to the top because they must be implemented and documentation should be near the top. Important virtual functions moved up too. Additional documentation added and existing adapted to 80 column width. I tried to reduce the number of included files and sorted them a bit --- devicehandlers/DeviceHandlerBase.cpp | 177 ++++---- devicehandlers/DeviceHandlerBase.h | 606 ++++++++++++++++----------- 2 files changed, 449 insertions(+), 334 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index bd304603..e7fd744a 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -1,14 +1,14 @@ -#include -#include -#include -#include #include -#include -#include #include #include -#include #include +#include + +#include +#include +#include +#include +#include #include #include @@ -90,6 +90,85 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { return RETURN_OK; } +ReturnValue_t DeviceHandlerBase::initialize() { + ReturnValue_t result = SystemObject::initialize(); + if (result != RETURN_OK) { + return result; + } + + communicationInterface = objectManager->get( + deviceCommunicationId); + if (communicationInterface == NULL) { + return RETURN_FAILED; + } + + result = communicationInterface->open(&cookie, ioBoardAddress, + maxDeviceReplyLen); + if (result != RETURN_OK) { + return result; + } + + IPCStore = objectManager->get(objects::IPC_STORE); + if (IPCStore == NULL) { + return RETURN_FAILED; + } + + AcceptsDeviceResponsesIF *rawReceiver = objectManager->get< + AcceptsDeviceResponsesIF>(rawDataReceiverId); + + if (rawReceiver == NULL) { + return RETURN_FAILED; + } + + defaultRawReceiver = rawReceiver->getDeviceQueue(); + + powerSwitcher = objectManager->get(powerSwitcherId); + if (powerSwitcher == NULL) { + return RETURN_FAILED; + } + + result = healthHelper.initialize(); + if (result != RETURN_OK) { + return result; + } + + result = modeHelper.initialize(); + if (result != RETURN_OK) { + return result; + } + result = actionHelper.initialize(commandQueue); + if (result != RETURN_OK) { + return result; + } + result = fdirInstance->initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + result = parameterHelper.initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + result = hkSwitcher.initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + fillCommandAndReplyMap(); + + //Set temperature target state to NON_OP. + DataSet mySet; + PoolVariable thermalRequest(deviceThermalRequestPoolId, &mySet, + PoolVariableIF::VAR_WRITE); + mySet.read(); + thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; + mySet.commit(PoolVariableIF::VALID); + + return RETURN_OK; + +} + void DeviceHandlerBase::decrementDeviceReplyMap() { for (std::map::iterator iter = deviceReplyMap.begin(); iter != deviceReplyMap.end(); iter++) { @@ -454,7 +533,9 @@ 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 @@ -577,86 +658,6 @@ ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, *len = 0; return result; } - -} - -ReturnValue_t DeviceHandlerBase::initialize() { - ReturnValue_t result = SystemObject::initialize(); - if (result != RETURN_OK) { - return result; - } - - communicationInterface = objectManager->get( - deviceCommunicationId); - if (communicationInterface == NULL) { - return RETURN_FAILED; - } - - result = communicationInterface->open(&cookie, ioBoardAddress, - maxDeviceReplyLen); - if (result != RETURN_OK) { - return result; - } - - IPCStore = objectManager->get(objects::IPC_STORE); - if (IPCStore == NULL) { - return RETURN_FAILED; - } - - AcceptsDeviceResponsesIF *rawReceiver = objectManager->get< - AcceptsDeviceResponsesIF>(rawDataReceiverId); - - if (rawReceiver == NULL) { - return RETURN_FAILED; - } - - defaultRawReceiver = rawReceiver->getDeviceQueue(); - - powerSwitcher = objectManager->get(powerSwitcherId); - if (powerSwitcher == NULL) { - return RETURN_FAILED; - } - - result = healthHelper.initialize(); - if (result != RETURN_OK) { - return result; - } - - result = modeHelper.initialize(); - if (result != RETURN_OK) { - return result; - } - result = actionHelper.initialize(commandQueue); - if (result != RETURN_OK) { - return result; - } - result = fdirInstance->initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - - result = parameterHelper.initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - - result = hkSwitcher.initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - - fillCommandAndReplyMap(); - - //Set temperature target state to NON_OP. - DataSet mySet; - PoolVariable thermalRequest(deviceThermalRequestPoolId, &mySet, - PoolVariableIF::VAR_WRITE); - mySet.read(); - thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; - mySet.commit(PoolVariableIF::VALID); - - return RETURN_OK; - } void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len, diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 871c9153..f475fde6 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -1,26 +1,24 @@ #ifndef DEVICEHANDLERBASE_H_ #define DEVICEHANDLERBASE_H_ -#include +#include +#include +#include #include -#include #include #include #include -#include #include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include #include -#include + +#include +#include +#include +#include +#include + +#include namespace Factory{ void setStaticFrameworkObjectIds(); @@ -34,24 +32,48 @@ class StorageManagerIF; */ /** - * \brief This is the abstract base class for device handlers. - * + * @brief This is the abstract base class for device handlers. + * @details * 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 @endlink, + * and communication with commanding objects. * 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. NOTE: RMAP is a 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. * * 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). + * The following abstract methods must be implemented by a device handler: + * 1. doStartUp() + * 2. doShutDown() + * 3. buildTransitionDeviceCommand() + * 4. buildNormalDeviceCommand() + * 5. buildCommandFromCommand() + * 6. fillCommandAndReplyMap() + * 7. scanForReply() + * 8. interpretDeviceReply() * - * \ingroup devices + * Other important virtual methods with a default implementation + * are the getTransitionDelayMs() function and the getSwitches() function. + * Please ensure that getSwitches() returns DeviceHandlerIF::NO_SWITCHES if + * power switches are not implemented yet. Otherwise, the device handler will + * not transition to MODE_ON, even if setMode(MODE_ON) is called. + * If a transition to MODE_ON is desired without commanding, override the + * intialize() function and call setMode(_MODE_START_UP) before calling + * DeviceHandlerBase::initialize(). + * + * @ingroup devices */ class DeviceHandlerBase: public DeviceHandlerIF, public HasReturnvaluesIF, @@ -68,56 +90,335 @@ public: * * @param setObjectId the ObjectId to pass to the SystemObject() Constructor * @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() + * @param setDeviceSwitch the switch the device is connected to, + * for devices using two switches, overwrite getSwitches() + * @param deviceCommuncation Communcation Interface object which is used + * to implement communication functions + * @param thermalStatePoolId + * @param thermalRequestPoolId + * @param fdirInstance + * @param cmdQueueSize */ DeviceHandlerBase(uint32_t ioBoardAddress, object_id_t setObjectId, uint32_t maxDeviceReplyLen, uint8_t setDeviceSwitch, - object_id_t deviceCommunication, uint32_t thermalStatePoolId = - PoolVariableIF::NO_PARAMETER, + object_id_t deviceCommunication, + uint32_t thermalStatePoolId = PoolVariableIF::NO_PARAMETER, uint32_t thermalRequestPoolId = PoolVariableIF::NO_PARAMETER, FailureIsolationBase* fdirInstance = NULL, uint32_t cmdQueueSize = 20); - virtual MessageQueueId_t getCommandQueue(void) const; - - /** - * This function is a 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 - * 2. Handles Device State Modes by calling doStateMachine(). - * This function calls callChildStatemachine() which calls the abstract functions - * doStartUp() and doShutDown() - * 3. Check switch states by calling checkSwitchStates() - * 4. Decrements counter for timeout of replies by calling decrementDeviceReplyMap() - * 5. Performs FDIR check for failures - * 6. Calls hkSwitcher.performOperation() - * 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(). - * 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() - * @param counter Specifies which Action to perform - * @return RETURN_OK for successful execution - */ + * @brief This function is the device handler base core component and is + * called periodically. + * @details + * General sequence, showing where abstract virtual functions are called: + * If the State is SEND_WRITE: + * 1. Set the cookie state to COOKIE_UNUSED and read the command queue + * 2. Handles Device State Modes by calling doStateMachine(). + * This function calls callChildStatemachine() which calls the + * abstract functions doStartUp() and doShutDown() + * 3. Check switch states by calling checkSwitchStates() + * 4. Decrements counter for timeout of replies by calling + * decrementDeviceReplyMap() + * 5. Performs FDIR check for failures + * 6. Calls hkSwitcher.performOperation() + * 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 (incremented in PST). + * The child class tells base class what to do by setting this value. + * - 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() + * 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 + */ virtual ReturnValue_t performOperation(uint8_t counter); + /** + * @brief Initializes the device handler + * @details + * Initialize Device Handler as system object and + * initializes all important helper classes. + * Calls fillCommandAndReplyMap(). + * @return + */ virtual ReturnValue_t initialize(); - /** - * - * @param parentQueueId - */ - virtual void setParentQueue(MessageQueueId_t parentQueueId); /** * Destructor. */ virtual ~DeviceHandlerBase(); +protected: + /** + * @brief This is used to let the child class handle the transition from + * mode @c _MODE_START_UP to @c MODE_ON + * @details + * It is only called when the device handler is in mode @c _MODE_START_UP. + * That means, the device switch(es) are already set to on. + * Device handler commands are read and can be handled by the child class. + * If the child class handles a command, it should also send + * an reply accordingly. + * If an Command is not handled (ie #DeviceHandlerCommand is not @c CMD_NONE, + * the base class handles rejecting the command and sends a reply. + * The replies for mode transitions are handled by the base class. + * + * - If the device is started and ready for operation, the mode should be + * set to MODE_ON. It is possible to set the mode to _MODE_TO_ON to + * use the to on transition if available. + * - If the power-up fails, the mode should be set to _MODE_POWER_DOWN + * which will lead to the device being powered off. + * - If the device does not change the mode, the mode will be changed + * to _MODE_POWER_DOWN, after the timeout (from getTransitionDelay()) + * has passed. + * + * #transitionFailure can be set to a failure code indicating the reason + * for a failed transition + */ + virtual void doStartUp() = 0; + + /** + * @brief This is used to let the child class handle the transition + * from mode @c _MODE_SHUT_DOWN to @c _MODE_POWER_DOWN + * @details + * It is only called when the device handler is in mode @c _MODE_SHUT_DOWN. + * Device handler commands are read and can be handled by the child class. + * If the child class handles a command, it should also send an reply + * accordingly. + * If an Command is not handled (ie #DeviceHandlerCommand is not + * @c CMD_NONE, the base class handles rejecting the command and sends a + * reply. The replies for mode transitions are handled by the base class. + * + * - If the device ready to be switched off, + * the mode should be set to _MODE_POWER_DOWN. + * - If the device should not be switched off, the mode can be changed to + * _MODE_TO_ON (or MODE_ON if no transition is needed). + * - If the device does not change the mode, the mode will be changed to + * _MODE_POWER_DOWN, when the timeout (from getTransitionDelay()) + * has passed. + * + * #transitionFailure can be set to a failure code indicating the reason + * for a failed transition + */ + virtual void doShutDown() = 0; + + /** + * Build the device command to send for normal mode. + * + * This is only called in @c MODE_NORMAL. If multiple submodes for + * @c MODE_NORMAL are supported, different commands can built, + * depending on the submode. + * + * #rawPacket and #rawPacketLen must be set by this method to the + * packet to be sent. If variable command frequence is required, a counter + * can be used and the frequency in the reply map has to be set manually + * by calling updateReplyMap(). + * + * @param[out] id the device command id that has been built + * @return + * - @c RETURN_OK to send command after setting #rawPacket and #rawPacketLen. + * - @c NOTHING_TO_SEND when no command is to be sent. + * - Anything else triggers an even with the returnvalue as a parameter. + */ + virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) = 0; + + /** + * Build the device command to send for a transitional mode. + * + * This is only called in @c _MODE_TO_NORMAL, @c _MODE_TO_ON, @c _MODE_TO_RAW, + * @c _MODE_START_UP and @c _MODE_TO_POWER_DOWN. So it is used by doStartUp() + * and doShutDown() as well as doTransition() + * + * A good idea is to implement a flag indicating a command has to be built + * and a variable containing the command number to be built + * and filling them in doStartUp(), doShutDown() and doTransition() so no + * modes have to be checked here. + * + * #rawPacket and #rawPacketLen must be set by this method to the packet to be sent. + * + * @param[out] id the device command id built + * @return + * - @c RETURN_OK when a command is to be sent + * - @c NOTHING_TO_SEND when no command is to be sent + * - Anything else triggers an even with the returnvalue as a parameter + */ + virtual ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) = 0; + + /** + * @brief Build a device command packet from data supplied by a direct command. + * + * @details + * #rawPacket and #rawPacketLen should be set by this method to the packet to be sent. + * The existence of the command in the command map and the command size check + * against 0 are done by the base class. + * + * @param deviceCommand the command to build, already checked against deviceCommandMap + * @param commandData pointer to the data from the direct command + * @param commandDataLen length of commandData + * @return + * - @c RETURN_OK to send command after #rawPacket and #rawPacketLen have been set. + * - Anything else triggers an event with the returnvalue as a parameter + */ + virtual ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, + const uint8_t * commandData, size_t commandDataLen) = 0; + + /** + * @brief fill the #deviceCommandMap + * called by the initialize() of the base class + * @details + * This is used to let the base class know which replies are expected. + * There are different scenarios regarding this: + * + * - "Normal" commands. These are commands, that trigger a direct reply + * from the device. In this case, the id of the command should be added + * to the command map with a commandData_t where maxDelayCycles is set + * to the maximum expected number of PST cycles the reply will take. + * Then, scanForReply returns the id of the command and the base class + * can handle time-out and missing replies. + * + * - Periodic, unrequested replies. These are replies that, once enabled, + * are sent by the device on its own in a defined interval. + * In this case, the id of the reply or a placeholder id should be added + * to the deviceCommandMap with a commandData_t where maxDelayCycles is + * set to the maximum expected number of PST cycles between two replies + * (also a tolerance should be added, as an FDIR message will be + * generated if it is missed). + * + * (Robin) This part confuses me. "must do as soon as" implies that + * the developer must do something somewhere else in the code. Is + * that really the case? If I understood correctly, DHB performs + * almost everything (e.g. in erirm function) as long as the commands + * are inserted correctly. + * + * As soon as the replies are enabled, DeviceCommandInfo.periodic must + * be set to true, DeviceCommandInfo.delayCycles to + * DeviceCommandInfo.maxDelayCycles. + * From then on, the base class handles the reception. + * Then, scanForReply returns the id of the reply or the placeholder id + * and the base class will take care of checking that all replies are + * received and the interval is correct. + * When the replies are disabled, DeviceCommandInfo.periodic must be set + * to 0, DeviceCommandInfo.delayCycles to 0; + * + * - Aperiodic, unrequested replies. These are replies that are sent + * by the device without any preceding command and not in a defined + * interval. These are not entered in the deviceCommandMap but + * handled by returning @c APERIODIC_REPLY in scanForReply(). + */ + virtual void fillCommandAndReplyMap() = 0; + + /** + * @brief Scans a buffer for a valid reply. + * @details + * This is used by the base class to check the data received for valid packets. + * It only checks if a valid packet starts at @c start. + * It also only checks the structural validy of the packet, + * e.g. checksums lengths and protocol data. No information check is done, + * e.g. range checks etc. + * + * Errors should be reported directly, the base class does NOT report any + * errors based on the return value of this function. + * + * @param start start of remaining buffer to be scanned + * @param len length of remaining buffer to be scanned + * @param[out] foundId the id of the data found in the buffer. + * @param[out] foundLen length of the data found. Is to be set in function, + * buffer is scanned at previous position + foundLen. + * @return + * - @c RETURN_OK a valid packet was found at @c start, @c foundLen is valid + * - @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, + * e.g. checksum error, implies @c foundLen is valid, can be used to + * skip some bytes + * - @c DeviceHandlerIF::LENGTH_MISSMATCH @c len is invalid + * - @c DeviceHandlerIF::IGNORE_REPLY_DATA Ignore this specific part of + * the packet + * - @c DeviceHandlerIF::IGNORE_FULL_PACKET Ignore the packet + * - @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, + DeviceCommandId_t *foundId, uint32_t *foundLen) = 0; + + /** + * @brief Interpret a reply from the device. + * @details + * This is called after scanForReply() found a valid packet, it can be + * assumed that the length and structure is valid. + * This routine extracts the data from the packet into a DataSet and then + * calls handleDeviceTM(), which either sends a TM packet or stores the + * data in the DataPool depending on whether it was an external command. + * No packet length is given, as it should be defined implicitly by the id. + * + * @param id the id found by scanForReply() + * @param packet + * @return + * - @c RETURN_OK when the reply was interpreted. + * - @c RETURN_FAILED when the reply could not be interpreted, + * e.g. logical errors or range violations occurred + */ + + virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, + const uint8_t *packet) = 0; + + /** + * @brief Can be implemented by child handler to + * perform debugging + * @details Example: Calling this in performOperation + * to track values like mode. + * @param positionTracker Provide the child handler a way to know where the debugInterface was called + * @param objectId Provide the child handler object Id to specify actions for spefic devices + * @param parameter Supply a parameter of interest + * Please delete all debugInterface calls in DHB after debugging is finished ! + */ + virtual void debugInterface(uint8_t positionTracker = 0, + object_id_t objectId = 0, uint32_t parameter = 0); + + /** + * Get the time needed to transit from modeFrom to modeTo. + * + * Used for the following transitions: + * modeFrom -> modeTo: + * MODE_ON -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] + * MODE_NORMAL -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] + * MODE_RAW -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] + * _MODE_START_UP -> MODE_ON (do not include time to set the switches, the base class got you covered) + * + * The default implementation returns 0 ! + * @param modeFrom + * @param modeTo + * @return time in ms + */ + virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo); + + /** + * Return the switches connected to the device. + * + * The default implementation returns one switch set in the ctor. + * + * @param[out] switches pointer to an array of switches + * @param[out] numberOfSwitches length of returned array + * @return + * - @c RETURN_OK if the parameters were set + * - @c RETURN_FAILED if no switches exist + */ + virtual ReturnValue_t getSwitches(const uint8_t **switches, + uint8_t *numberOfSwitches); + +public: + /** + * @param parentQueueId + */ + virtual void setParentQueue(MessageQueueId_t parentQueueId); ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size); @@ -136,6 +437,8 @@ public: * @param task_ Pointer to the taskIF of this task */ virtual void setTaskIF(PeriodicTaskIF* task_); + virtual MessageQueueId_t getCommandQueue(void) const; + protected: /** * The Returnvalues id of this class, required by HasReturnvaluesIF @@ -347,41 +650,6 @@ protected: */ void setMode(Mode_t newMode, Submode_t submode); - /** - * This is used to let the child class handle the transition from mode @c _MODE_START_UP to @c MODE_ON - * - * It is only called when the device handler is in mode @c _MODE_START_UP. That means, the device switch(es) are already set to on. - * Device handler commands are read and can be handled by the child class. If the child class handles a command, it should also send - * an reply accordingly. - * If an Command is not handled (ie #DeviceHandlerCommand is not @c CMD_NONE, the base class handles rejecting the command and sends a reply. - * The replies for mode transitions are handled by the base class. - * - * If the device is started and ready for operation, the mode should be set to MODE_ON. It is possible to set the mode to _MODE_TO_ON to - * use the to on transition if available. - * If the power-up fails, the mode should be set to _MODE_POWER_DOWN which will lead to the device being powered off. - * If the device does not change the mode, the mode will be changed to _MODE_POWER_DOWN, after the timeout (from getTransitionDelay()) has passed. - * - * #transitionFailure can be set to a failure code indicating the reason for a failed transition - */ - virtual void doStartUp() = 0; - - /** - * This is used to let the child class handle the transition from mode @c _MODE_SHUT_DOWN to @c _MODE_POWER_DOWN - * - * It is only called when the device handler is in mode @c _MODE_SHUT_DOWN. - * Device handler commands are read and can be handled by the child class. If the child class handles a command, it should also send - * an reply accordingly. - * If an Command is not handled (ie #DeviceHandlerCommand is not @c CMD_NONE, the base class handles rejecting the command and sends a reply. - * The replies for mode transitions are handled by the base class. - * - * If the device ready to be switched off, the mode should be set to _MODE_POWER_DOWN. - * If the device should not be switched off, the mode can be changed to _MODE_TO_ON (or MODE_ON if no transition is needed). - * If the device does not change the mode, the mode will be changed to _MODE_POWER_DOWN, when the timeout (from getTransitionDelay()) has passed. - * - * #transitionFailure can be set to a failure code indicating the reason for a failed transition - */ - virtual void doShutDown() = 0; - /** * Do the transition to the main modes (MODE_ON, MODE_NORMAL and MODE_RAW). * @@ -411,24 +679,6 @@ protected: */ virtual void doTransition(Mode_t modeFrom, Submode_t subModeFrom); - /** - * Get the time needed to transit from modeFrom to modeTo. - * - * Used for the following transitions: - * modeFrom -> modeTo: - * MODE_ON -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] - * MODE_NORMAL -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] - * MODE_RAW -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] - * _MODE_START_UP -> MODE_ON (do not include time to set the switches, the base class got you covered) - * - * The default implementation returns 0; - * - * @param modeFrom - * @param modeTo - * @return time in ms - */ - virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo); - /** * Is the combination of mode and submode valid? * @@ -450,40 +700,6 @@ protected: */ virtual RmapAction_t getRmapAction(); - /** - * Build the device command to send for normal mode. - * - * This is only called in @c MODE_NORMAL. If multiple submodes for @c MODE_NORMAL are supported, - * different commands can built returned depending on the submode. - * - * #rawPacket and #rawPacketLen must be set by this method to the packet to be sent. - * - * @param[out] id the device command id that has been built - * @return - * - @c RETURN_OK when a command is to be sent - * - not @c RETURN_OK when no command is to be sent - */ - virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) = 0; - - /** - * Build the device command to send for a transitional mode. - * - * This is only called in @c _MODE_TO_NORMAL, @c _MODE_TO_ON, @c _MODE_TO_RAW, - * @c _MODE_START_UP and @c _MODE_TO_POWER_DOWN. So it is used by doStartUp() and doShutDown() as well as doTransition() - * - * A good idea is to implement a flag indicating a command has to be built and a variable containing the command number to be built - * and filling them in doStartUp(), doShutDown() and doTransition() so no modes have to be checked here. - * - * #rawPacket and #rawPacketLen must be set by this method to the packet to be sent. - * - * @param[out] id the device command id built - * @return - * - @c RETURN_OK when a command is to be sent - * - not @c RETURN_OK when no command is to be sent - */ - virtual ReturnValue_t buildTransitionDeviceCommand( - DeviceCommandId_t * id) = 0; - /** * Build the device command to send for raw mode. * @@ -504,41 +720,6 @@ protected: */ virtual ReturnValue_t buildChildRawCommand(); - /** - * Build a device command packet from data supplied by a direct command. - * - * #rawPacket and #rawPacketLen should be set by this method to the packet to be sent. - * - * @param deviceCommand the command to build, already checked against deviceCommandMap - * @param commandData pointer to the data from the direct command - * @param commandDataLen length of commandData - * @return - * - @c RETURN_OK when #rawPacket is valid - * - @c RETURN_FAILED when #rawPacket is invalid and no data should be sent - */ - virtual ReturnValue_t buildCommandFromCommand( - DeviceCommandId_t deviceCommand, const uint8_t * commandData, - size_t commandDataLen) = 0; - - /** - * fill the #deviceCommandMap - * - * called by the initialize() of the base class - * - * This is used to let the base class know which replies are expected. - * There are different scenarios regarding this: - * - "Normal" commands. These are commands, that trigger a direct reply from the device. In this case, the id of the command should be added to the command map - * with a commandData_t where maxDelayCycles is set to the maximum expected number of PST cycles the reply will take. Then, scanForReply returns the id of the command and the base class can handle time-out and missing replies. - * - Periodic, unrequested replies. These are replies that, once enabled, are sent by the device on its own in a defined interval. In this case, the id of the reply or a placeholder id should be added to the deviceCommandMap - * with a commandData_t where maxDelayCycles is set to the maximum expected number of PST cycles between two replies (also a tolerance should be added, as an FDIR message will be generated if it is missed). - * As soon as the replies are enabled, DeviceCommandInfo.periodic must be set to 1, DeviceCommandInfo.delayCycles to DeviceCommandInfo.MaxDelayCycles. From then on, the base class handles the reception. - * Then, scanForReply returns the id of the reply or the placeholder id and the base class will take care of checking that all replies are received and the interval is correct. - * When the replies are disabled, DeviceCommandInfo.periodic must be set to 0, DeviceCommandInfo.delayCycles to 0; - * - Aperiodic, unrequested replies. These are replies that are sent by the device without any preceding command and not in a defined interval. These are not entered in the deviceCommandMap but handled by returning @c APERIODIC_REPLY in scanForReply(). - * - */ - virtual void fillCommandAndReplyMap() = 0; - /** * This is a helper method to facilitate inserting entries in the command map. * @param deviceCommand Identifier of the command to add. @@ -586,58 +767,6 @@ protected: */ uint8_t getReplyDelayCycles(DeviceCommandId_t deviceCommand); - /** - * Scans a buffer for a valid reply. - * - * This is used by the base class to check the data received from the RMAP stack for valid packets. - * It only checks if a valid packet starts at @c start. - * It also only checks the structural validy of the packet, eg checksums lengths and protocol data. No - * information check is done, eg range checks etc. - * - * Errors should be reported directly, the base class does NOT report any errors based on the return - * value of this function. - * - * @param start start of remaining buffer to be scanned - * @param len length of remaining buffer to be scanned - * @param[out] foundId the id of the data found in the buffer. - * @param[out] foundLen length of the data found. Is to be set in function, buffer is scanned at previous position + foundLen. - * @return - * - @c RETURN_OK a valid packet was found at @c start, @c foundLen is valid - * - @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, - * e.g. checksum error, implies @c foundLen is valid, can be used to - * skip some bytes - * - @c DeviceHandlerIF::LENGTH_MISSMATCH @c len is invalid - * - @c DeviceHandlerIF::IGNORE_REPLY_DATA Ignore this specific part of - * the packet - * - @c DeviceHandlerIF::IGNORE_FULL_PACKET Ignore the packet - * - @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, - DeviceCommandId_t *foundId, uint32_t *foundLen) = 0; - - /** - * Interpret a reply from the device. - * - * This is called after scanForReply() found a valid packet, it can be assumed that the length and structure is valid. - * This routine extracts the data from the packet into a DataSet and then calls handleDeviceTM(), which either sends - * a TM packet or stores the data in the DataPool depending on whether the it was an external command. - * No packet length is given, as it should be defined implicitly by the id. - * - * @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 - */ - virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, - const uint8_t *packet) = 0; - /** * Construct a command reply containing a raw reply. * @@ -661,21 +790,6 @@ protected: */ void replyRawReplyIfnotWiretapped(const uint8_t *data, size_t len); - /** - * Return the switches connected to the device. - * - * The default implementation returns one switch set in the ctor. - * - * - * @param[out] switches pointer to an array of switches - * @param[out] numberOfSwitches length of returned array - * @return - * - @c RETURN_OK if the parameters were set - * - @c RETURN_FAILED if no switches exist - */ - virtual ReturnValue_t getSwitches(const uint8_t **switches, - uint8_t *numberOfSwitches); - /** * notify child about mode change */ From 1ec1d057b822df09aed7268a2dfb6bdeafe1a8b4 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 23 Mar 2020 18:05:39 +0100 Subject: [PATCH 020/653] renamed rmap to com (more generic) --- devicehandlers/DeviceHandlerBase.cpp | 5 +- devicehandlers/DeviceHandlerBase.h | 5 +- devicehandlers/DeviceHandlerIF.h | 137 +++++++++++++-------------- 3 files changed, 73 insertions(+), 74 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index e7fd744a..fa9c0248 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -67,7 +67,7 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { if (mode == MODE_OFF) { return RETURN_OK; } - switch (getRmapAction()) { + switch (getCommandQueue()) { case SEND_WRITE: if ((cookieInfo.state == COOKIE_UNUSED)) { buildInternalCommand(); @@ -689,8 +689,7 @@ void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len, } //Default child implementations - -DeviceHandlerBase::RmapAction_t DeviceHandlerBase::getRmapAction() { +DeviceHandlerIF::CommunicationAction_t DeviceHandlerBase::getComAction() { switch (pstStep) { case 0: return SEND_WRITE; diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index f475fde6..24d0c428 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -3,11 +3,11 @@ #include #include +#include #include #include #include #include -#include #include #include #include @@ -698,7 +698,8 @@ protected: * * @return The Rmap action to execute in this step */ - virtual RmapAction_t getRmapAction(); + + virtual CommunicationAction_t getComAction(); /** * Build the device command to send for raw mode. diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index fe0ee8e8..d347fd68 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -23,85 +23,84 @@ 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 = 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. - static const Mode_t MODE_RAW = 3; //!< The device is powered on and ready to perform operations. In this mode, raw commands can be sent. The device handler will send all replies received from the command back to the commanding object. - 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_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 - static const Mode_t _MODE_POWER_ON = TRANSITION_MODE_BASE_ACTION_MASK | 2; //!< This is a transitional state which can not be commanded. The device will be switched on in this state. After the command to set the switch on has been sent, the mode changes to @c MODE_WAIT_ON - static const Mode_t _MODE_WAIT_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 3; //!< This is a transitional state which can not be commanded. The switch has been commanded off and the handler waits for it to be off. When the switch is off, the mode changes to @c MODE_OFF. - static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4; //!< This is a transitional state which can not be commanded. The switch has been commanded on and the handler waits for it to be on. When the switch is on, the mode changes to @c MODE_TO_ON. - static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5; //!< This is a transitional state which can not be commanded. The switch has been commanded off and is off now. This state is only to do an RMAP cycle once more where the doSendRead() function will set the mode to MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board + // 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. + static const Mode_t MODE_RAW = 3; //!< The device is powered on and ready to perform operations. In this mode, raw commands can be sent. The device handler will send all replies received from the command back to the commanding object. + 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_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 + static const Mode_t _MODE_POWER_ON = TRANSITION_MODE_BASE_ACTION_MASK | 2; //!< This is a transitional state which can not be commanded. The device will be switched on in this state. After the command to set the switch on has been sent, the mode changes to @c MODE_WAIT_ON + static const Mode_t _MODE_WAIT_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 3; //!< This is a transitional state which can not be commanded. The switch has been commanded off and the handler waits for it to be off. When the switch is off, the mode changes to @c MODE_OFF. + static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4; //!< This is a transitional state which can not be commanded. The switch has been commanded on and the handler waits for it to be on. When the switch is on, the mode changes to @c MODE_TO_ON. + static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5; //!< This is a transitional state which can not be commanded. The switch has been commanded off and is off now. This state is only to do an RMAP cycle once more where the doSendRead() function will set the mode to MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board - static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CDH; - static const Event DEVICE_BUILDING_COMMAND_FAILED = MAKE_EVENT(0, SEVERITY::LOW); - static const Event DEVICE_SENDING_COMMAND_FAILED = MAKE_EVENT(1, SEVERITY::LOW); - static const Event DEVICE_REQUESTING_REPLY_FAILED = MAKE_EVENT(2, SEVERITY::LOW); - static const Event DEVICE_READING_REPLY_FAILED = MAKE_EVENT(3, SEVERITY::LOW); - static const Event DEVICE_INTERPRETING_REPLY_FAILED = MAKE_EVENT(4, SEVERITY::LOW); - static const Event DEVICE_MISSED_REPLY = MAKE_EVENT(5, SEVERITY::LOW); - static const Event DEVICE_UNKNOWN_REPLY = MAKE_EVENT(6, SEVERITY::LOW); - static const Event DEVICE_UNREQUESTED_REPLY = MAKE_EVENT(7, SEVERITY::LOW); - static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, SEVERITY::LOW); //!< Indicates a SW bug in child class. - 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 SUBSYSTEM_ID = SUBSYSTEM_ID::CDH; + static const Event DEVICE_BUILDING_COMMAND_FAILED = MAKE_EVENT(0, SEVERITY::LOW); + static const Event DEVICE_SENDING_COMMAND_FAILED = MAKE_EVENT(1, SEVERITY::LOW); + static const Event DEVICE_REQUESTING_REPLY_FAILED = MAKE_EVENT(2, SEVERITY::LOW); + static const Event DEVICE_READING_REPLY_FAILED = MAKE_EVENT(3, SEVERITY::LOW); + static const Event DEVICE_INTERPRETING_REPLY_FAILED = MAKE_EVENT(4, SEVERITY::LOW); + static const Event DEVICE_MISSED_REPLY = MAKE_EVENT(5, SEVERITY::LOW); + static const Event DEVICE_UNKNOWN_REPLY = MAKE_EVENT(6, SEVERITY::LOW); + static const Event DEVICE_UNREQUESTED_REPLY = MAKE_EVENT(7, SEVERITY::LOW); + static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, SEVERITY::LOW); //!< Indicates a SW bug in child class. + 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 = 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); - static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3); - static const ReturnValue_t CANT_SWITCH_IOBOARD = MAKE_RETURN_CODE(0xA4); - static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA5); - static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA6); - 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); + 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); + static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3); + static const ReturnValue_t CANT_SWITCH_IOBOARD = MAKE_RETURN_CODE(0xA4); + static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA5); + static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA6); + 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 + //standard codes used in scan for reply // static const ReturnValue_t TOO_SHORT = MAKE_RETURN_CODE(0xB1); - static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB2); - static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB3); - static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB4); - static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB5); + static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB2); + static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB3); + static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB4); + static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB5); - //standard codes used in interpret device reply - static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC1); //the device reported, that it did not execute the command - static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC2); - static const ReturnValue_t UNKNOW_DEVICE_REPLY = MAKE_RETURN_CODE(0xC3); //the deviceCommandId reported by scanforReply is unknown - static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC4); //syntax etc is correct but still not ok, eg parameters where none are expected + //standard codes used in interpret device reply + static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC1); //the device reported, that it did not execute the command + static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC2); + static const ReturnValue_t UNKNOW_DEVICE_REPLY = MAKE_RETURN_CODE(0xC3); //the deviceCommandId reported by scanforReply is unknown + static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC4); //syntax etc is correct but still not ok, eg parameters where none are expected - //Standard codes used in buildCommandFromCommand - static const ReturnValue_t INVALID_COMMAND_PARAMETER = MAKE_RETURN_CODE( - 0xD0); - static const ReturnValue_t INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS = - MAKE_RETURN_CODE(0xD1); + //Standard codes used in buildCommandFromCommand + static const ReturnValue_t INVALID_COMMAND_PARAMETER = MAKE_RETURN_CODE( + 0xD0); + static const ReturnValue_t INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS = + MAKE_RETURN_CODE(0xD1); + + /** + * Communication action which will be executed. + * + * This is used by the child class to tell the base class what to do. + */ + enum CommunicationAction_t { + SEND_WRITE,//!< RMAP send write + GET_WRITE, //!< RMAP get write + SEND_READ, //!< RMAP send read + GET_READ, //!< RMAP get read + NOTHING //!< Do nothing. + }; - /** - * 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 */ - virtual ~DeviceHandlerIF() { - - } + virtual ~DeviceHandlerIF() {} /** * This MessageQueue is used to command the device handler. From 62644bdfc95d145ad3f0f4d13525b1fc76238bb7 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 19 Apr 2020 14:45:28 +0200 Subject: [PATCH 021/653] DeviceHandlerIF fixed some indentation error still some unclarities about returnvalues so I added a comment on what the returnvalues in DHB and DH interface mean --- devicehandlers/DeviceHandlerBase.cpp | 2 +- devicehandlers/DeviceHandlerBase.h | 6 ++++ devicehandlers/DeviceHandlerIF.h | 44 ++++++++++++++++------------ 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index fa9c0248..ca8fa85c 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -1054,7 +1054,7 @@ ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage( if (result == RETURN_OK) { replyReturnvalueToCommand(RETURN_OK); } else { - replyReturnvalueToCommand(CANT_SWITCH_IOBOARD); + replyReturnvalueToCommand(CANT_SWITCH_IO_ADDRESS); } } return RETURN_OK; diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 24d0c428..4d3e3f4e 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -445,7 +445,13 @@ protected: */ static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE; + /** + * These returnvalues can be returned from abstract functions + * to alter the behaviour of DHB.For error values, refer to + * DeviceHandlerIF.h returnvalues. + */ static const ReturnValue_t INVALID_CHANNEL = MAKE_RETURN_CODE(4); + // Returnvalues for scanForReply() 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); //!< Ignore parts of the received packet static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE(7); //!< Ignore full received packet diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index d347fd68..04e94613 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -2,13 +2,15 @@ #define DEVICEHANDLERIF_H_ #include -#include -#include #include #include +#include +#include + /** - * This is the Interface used to communicate with a device handler. + * @brief This is the Interface used to communicate with a device handler. + * @details Includes all expected return values, events and modes. * */ class DeviceHandlerIF { @@ -22,15 +24,17 @@ 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. + + // 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. static const Mode_t MODE_RAW = 3; //!< The device is powered on and ready to perform operations. In this mode, raw commands can be sent. The device handler will send all replies received from the command back to the commanding object. 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 @@ -53,11 +57,12 @@ public: static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, SEVERITY::HIGH); static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF; + // Standard error codes when handling or building commands. 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); static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3); - static const ReturnValue_t CANT_SWITCH_IOBOARD = MAKE_RETURN_CODE(0xA4); + static const ReturnValue_t CANT_SWITCH_IO_ADDRESS = MAKE_RETURN_CODE(0xA4); static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA5); static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA6); static const ReturnValue_t BUSY = MAKE_RETURN_CODE(0xA7); @@ -65,35 +70,35 @@ public: 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); + // Standard error codes used in scan for reply + //static const ReturnValue_t TOO_SHORT = MAKE_RETURN_CODE(0xB1); static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB2); static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB3); static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB4); static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB5); - //standard codes used in interpret device reply + // Standard error codes used in interpret device reply static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC1); //the device reported, that it did not execute the command static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC2); static const ReturnValue_t UNKNOW_DEVICE_REPLY = MAKE_RETURN_CODE(0xC3); //the deviceCommandId reported by scanforReply is unknown static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC4); //syntax etc is correct but still not ok, eg parameters where none are expected - //Standard codes used in buildCommandFromCommand + // Standard error codes used in buildCommandFromCommand static const ReturnValue_t INVALID_COMMAND_PARAMETER = MAKE_RETURN_CODE( 0xD0); static const ReturnValue_t INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS = MAKE_RETURN_CODE(0xD1); /** - * Communication action which will be executed. + * Communication action that will be executed. * * This is used by the child class to tell the base class what to do. */ - enum CommunicationAction_t { - SEND_WRITE,//!< RMAP send write - GET_WRITE, //!< RMAP get write - SEND_READ, //!< RMAP send read - GET_READ, //!< RMAP get read + enum CommunicationAction_t: uint8_t { + SEND_WRITE,//!< Send write + GET_WRITE, //!< Get write + SEND_READ, //!< Send read + GET_READ, //!< Get read NOTHING //!< Do nothing. }; @@ -105,8 +110,9 @@ public: /** * This MessageQueue is used to command the device handler. * - * To command a device handler, a DeviceHandlerCommandMessage can be sent to this Queue. - * The handler replies with a DeviceHandlerCommandMessage containing the DeviceHandlerCommand_t reply. + * To command a device handler, a DeviceHandlerCommandMessage can be + * sent to this Queue. The handler replies with a + * DeviceHandlerCommandMessage containing the DeviceHandlerCommand_t reply. * * @return the id of the MessageQueue */ From 74b8c3eef47b39f01420456b7ce4a87eb7069089 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 19 Apr 2020 14:52:27 +0200 Subject: [PATCH 022/653] new returnvalue DeviceComIF explicitely setting receivedDataLen to 0 in readReceivedMessage() does not trigger error anymore --- devicehandlers/DeviceCommunicationIF.h | 6 ++++-- devicehandlers/DeviceHandlerBase.cpp | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/devicehandlers/DeviceCommunicationIF.h b/devicehandlers/DeviceCommunicationIF.h index b24e7d37..41d47cd3 100644 --- a/devicehandlers/DeviceCommunicationIF.h +++ b/devicehandlers/DeviceCommunicationIF.h @@ -8,6 +8,7 @@ class DeviceCommunicationIF: public HasReturnvaluesIF { public: static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_COMMUNICATION_IF; + // Standard error codes static const ReturnValue_t INVALID_COOKIE_TYPE = MAKE_RETURN_CODE(0x01); static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x02); static const ReturnValue_t INVALID_ADDRESS = MAKE_RETURN_CODE(0x03); @@ -16,9 +17,10 @@ public: static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0x06); static const ReturnValue_t CANT_CHANGE_REPLY_LEN = MAKE_RETURN_CODE(0x07); - virtual ~DeviceCommunicationIF() { + // Can be used in readReceivedMessage() + static const ReturnValue_t NO_REPLY_RECEIVED = MAKE_RETURN_CODE(0xA1); - } + virtual ~DeviceCommunicationIF() {} virtual ReturnValue_t open(Cookie **cookie, uint32_t address, uint32_t maxReplyLen) = 0; diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index ca8fa85c..30228dd4 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -588,7 +588,7 @@ void DeviceHandlerBase::doGetRead() { return; } - if (receivedDataLen == 0) + if (receivedDataLen == 0 or result == DeviceCommunicationIF::NO_REPLY_RECEIVED) return; if (wiretappingMode == RAW) { From eacedf7ed603fc68f507ee11c08e4787d3f5c079 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 19 Apr 2020 15:01:27 +0200 Subject: [PATCH 023/653] DHB: replyLen in replyMap now both maps are closer together now as well --- devicehandlers/DeviceHandlerBase.cpp | 39 +++++++++++-------- devicehandlers/DeviceHandlerBase.h | 58 ++++++++++++++-------------- 2 files changed, 52 insertions(+), 45 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 30228dd4..3e17b451 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -334,37 +334,35 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode, } } -ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap( - DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, - uint8_t periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) { -//No need to check, as we may try to insert multiple times. +ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, + uint16_t maxDelayCycles, size_t replyLen, uint8_t periodic, + bool hasDifferentReplyId, DeviceCommandId_t replyId) { + //No need to check, as we may try to insert multiple times. insertInCommandMap(deviceCommand); if (hasDifferentReplyId) { - return insertInReplyMap(replyId, maxDelayCycles, periodic); + return insertInReplyMap(replyId, maxDelayCycles, replyLen, periodic); } else { - return insertInReplyMap(deviceCommand, maxDelayCycles, periodic); + return insertInReplyMap(deviceCommand, maxDelayCycles, replyLen, periodic); } } ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId, - uint16_t maxDelayCycles, uint8_t periodic) { + uint16_t maxDelayCycles, size_t replyLen, uint8_t periodic) { DeviceReplyInfo info; info.maxDelayCycles = maxDelayCycles; info.periodic = periodic; info.delayCycles = 0; + info.replyLen = replyLen; info.command = deviceCommandMap.end(); - std::pair::iterator, bool> returnValue; - returnValue = deviceReplyMap.insert( - std::pair(replyId, info)); - if (returnValue.second) { + std::pair result = deviceReplyMap.emplace(replyId, info); + if (result.second) { return RETURN_OK; } else { return RETURN_FAILED; } } -ReturnValue_t DeviceHandlerBase::insertInCommandMap( - DeviceCommandId_t deviceCommand) { +ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceCommand) { DeviceCommandInfo info; info.expectedReplies = 0; info.isExecuting = false; @@ -380,9 +378,8 @@ ReturnValue_t DeviceHandlerBase::insertInCommandMap( } } -ReturnValue_t DeviceHandlerBase::updateReplyMapEntry( - DeviceCommandId_t deviceReply, uint16_t delayCycles, - uint16_t maxDelayCycles, uint8_t periodic) { +ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply, + uint16_t delayCycles, uint16_t maxDelayCycles, uint8_t periodic) { std::map::iterator iter = deviceReplyMap.find(deviceReply); if (iter == deviceReplyMap.end()) { @@ -551,7 +548,17 @@ void DeviceHandlerBase::doGetWrite() { void DeviceHandlerBase::doSendRead() { ReturnValue_t result; + size_t requestLen = 0; + DeviceReplyIter iter = deviceReplyMap.find(cookieInfo.pendingCommand->first); + if(iter != deviceReplyMap.end()) { + requestLen = iter->second.replyLen; + } + else { + requestLen = 0; + } + result = communicationInterface->requestReceiveMessage(cookie); + if (result == RETURN_OK) { cookieInfo.state = COOKIE_READ_SENT; } else { diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 4d3e3f4e..d774ce98 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -557,6 +557,29 @@ protected: */ Cookie *cookie; + struct DeviceCommandInfo { + bool isExecuting; //!< Indicates if the command is already executing. + uint8_t expectedReplies; //!< Dynamic value to indicate how many replies are expected. Inititated with 0. + MessageQueueId_t sendReplyTo; //!< if this is != NO_COMMANDER, DHB was commanded externally and shall report everything to commander. + }; + using DeviceCommandMap = std::map ; + + /** + * @brief Information about expected replies + * + * This is used to keep track of pending replies + */ + struct DeviceReplyInfo { + uint16_t maxDelayCycles; //!< The maximum number of cycles the handler should wait for a reply to this command. + uint16_t delayCycles; //!< The currently remaining cycles the handler should wait for a reply, 0 means there is no reply expected + size_t replyLen = 0; //!< Expected size of the reply. + 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. + }; + + using DeviceReplyMap = std::map ; + using DeviceReplyIter = DeviceReplyMap::iterator; + /** * The MessageQueue used to receive device handler commands and to send replies. */ @@ -736,7 +759,7 @@ protected: * @return RETURN_OK when the command was successfully inserted, COMMAND_MAP_ERROR else. */ ReturnValue_t insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, - uint16_t maxDelayCycles, uint8_t periodic = 0, + uint16_t maxDelayCycles, size_t replyLen = 0, uint8_t periodic = 0, bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0); /** * This is a helper method to insert replies in the reply map. @@ -747,7 +770,7 @@ protected: * @return RETURN_OK when the command was successfully inserted, COMMAND_MAP_ERROR else. */ ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, - uint16_t maxDelayCycles, uint8_t periodic = 0); + uint16_t maxDelayCycles, size_t replyLen = 0, uint8_t periodic = 0); /** * A simple command to add a command to the commandList. * @param deviceCommand The command to add @@ -802,13 +825,6 @@ protected: */ virtual void modeChanged(void); - struct DeviceCommandInfo { - bool isExecuting; //!< Indicates if the command is already executing. - uint8_t expectedReplies; //!< Dynamic value to indicate how many replies are expected. - MessageQueueId_t sendReplyTo; //!< if this is != NO_COMMANDER, DHB was commanded externally and shall report everything to commander. - }; - - typedef std::map DeviceCommandMap; /** * Enable the reply checking for a command * @@ -819,16 +835,16 @@ protected: * When found, copies maxDelayCycles to delayCycles in the reply information and sets the command to * expect one reply. * - * Can be overwritten by the child, if a command activates multiple replies or replyId differs from - * commandId. + * Can be overwritten by the child, if a command activates multiple replies + * or replyId differs from commandId. * Notes for child implementations: * - If the command was not found in the reply map, NO_REPLY_EXPECTED MUST be returned. * - A failure code may be returned if something went fundamentally wrong. * * @param deviceCommand * @return - RETURN_OK if a reply was activated. - * - NO_REPLY_EXPECTED if there was no reply found. This is not an error case as many commands - * do not expect a reply. + * - NO_REPLY_EXPECTED if there was no reply found. This is not an + * error case as many commands do not expect a reply. */ virtual ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator cmd, uint8_t expectedReplies = 1, bool useAlternateId = false, @@ -927,22 +943,6 @@ protected: bool commandIsExecuting(DeviceCommandId_t commandId); - /** - * Information about expected replies - * - * This is used to keep track of pending replies - */ - struct DeviceReplyInfo { - uint16_t maxDelayCycles; //!< The maximum number of cycles the handler should wait for a reply to this command. - uint16_t delayCycles; //!< The currently remaining cycles the handler should wait for a reply, 0 means there is no reply expected - 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. - */ - typedef std::map DeviceReplyMap; /** * This map is used to check and track correct reception of all replies. * From ce554c615c82c1d2295c1ce1ce4bdddf0202c76e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 19 Apr 2020 15:15:33 +0200 Subject: [PATCH 024/653] reduced massive ctor size this was done by moving zero or nullptr initialization into the header file --- devicehandlers/DeviceHandlerBase.cpp | 31 ++++++++++++++-------------- devicehandlers/DeviceHandlerBase.h | 26 +++++++++++------------ 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 3e17b451..5211cf92 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -21,24 +21,23 @@ DeviceHandlerBase::DeviceHandlerBase(uint32_t ioBoardAddress, 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), mode(MODE_OFF), submode(SUBMODE_NONE), + maxDeviceReplyLen(maxDeviceReplyLen), wiretappingMode(OFF), + storedRawData(StorageManagerIF::INVALID_ADDRESS), deviceCommunicationId( + deviceCommunication), deviceThermalStatePoolId(thermalStatePoolId), + deviceThermalRequestPoolId(thermalRequestPoolId), healthHelper(this, + setObjectId), modeHelper(this), parameterHelper(this), + childTransitionFailure(RETURN_OK), fdirInstance(fdirInstance), + hkSwitcher(this), defaultFDIRUsed(fdirInstance == nullptr), + switchOffWasReported(false), actionHelper(this, nullptr), cookieInfo(), + ioBoardAddress(ioBoardAddress), 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) { + if (this->fdirInstance == nullptr) { this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, defaultFDIRParentId); } @@ -55,7 +54,7 @@ DeviceHandlerBase::~DeviceHandlerBase() { ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { this->pstStep = counter; - if (counter == 0) { + if (getComAction() == SEND_WRITE) { cookieInfo.state = COOKIE_UNUSED; readCommandQueue(); doStateMachine(); @@ -67,7 +66,7 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { if (mode == MODE_OFF) { return RETURN_OK; } - switch (getCommandQueue()) { + switch (getComAction()) { case SEND_WRITE: if ((cookieInfo.state == COOKIE_UNUSED)) { buildInternalCommand(); diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index d774ce98..b7314d5b 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -473,11 +473,11 @@ protected: /** * Pointer to the raw packet that will be sent. */ - uint8_t *rawPacket; + uint8_t *rawPacket = nullptr; /** * Size of the #rawPacket. */ - uint32_t rawPacketLen; + uint32_t rawPacketLen = 0; /** * The mode the device handler is currently in. @@ -496,7 +496,7 @@ protected: /** * This is the counter value from performOperation(). */ - uint8_t pstStep; + uint8_t pstStep = 0; /** * This will be used in the RMAP getRead command as expected length, is set by the constructor, can be modiefied at will. @@ -519,7 +519,7 @@ protected: * 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 defaultRawReceiver; + MessageQueueId_t defaultRawReceiver = 0; store_address_t storedRawData; @@ -528,19 +528,19 @@ protected: * * if #isWiretappingActive all raw communication from and to the device will be sent to this queue */ - MessageQueueId_t requestedRawTraffic; + MessageQueueId_t requestedRawTraffic = 0; /** * the object used to set power switches */ - PowerSwitchIF *powerSwitcher; + PowerSwitchIF *powerSwitcher = nullptr; /** * Pointer to the IPCStore. * * This caches the pointer received from the objectManager in the constructor. */ - StorageManagerIF *IPCStore; + StorageManagerIF *IPCStore = nullptr; /** * cached for init @@ -550,12 +550,12 @@ protected: /** * Communication object used for device communication */ - DeviceCommunicationIF *communicationInterface; + DeviceCommunicationIF *communicationInterface = nullptr; /** * Cookie used for communication */ - Cookie *cookie; + Cookie *cookie = nullptr; struct DeviceCommandInfo { bool isExecuting; //!< Indicates if the command is already executing. @@ -583,7 +583,7 @@ protected: /** * The MessageQueue used to receive device handler commands and to send replies. */ - MessageQueueIF* commandQueue; + MessageQueueIF* commandQueue = nullptr; /** * this is the datapool variable with the thermal state of the device @@ -614,7 +614,7 @@ protected: */ ReturnValue_t childTransitionFailure; - uint32_t ignoreMissedRepliesCount; //!< Counts if communication channel lost a reply, so some missed replys can be ignored. + uint32_t ignoreMissedRepliesCount = 0; //!< Counts if communication channel lost a reply, so some missed replys can be ignored. FailureIsolationBase* fdirInstance; //!< Pointer to the used FDIR instance. If not provided by child, default class is instantiated. @@ -624,7 +624,7 @@ protected: bool switchOffWasReported; //!< Indicates if SWITCH_WENT_OFF was already thrown. - PeriodicTaskIF* executingTask;//!< Pointer to the task which executes this component, is invalid before setTaskIF was called. + PeriodicTaskIF* executingTask = nullptr;//!< Pointer to the task which executes this component, is invalid before setTaskIF was called. static object_id_t powerSwitcherId; //!< Object which switches power on and off. @@ -1004,7 +1004,7 @@ private: * * Set when setMode() is called. */ - uint32_t timeoutStart; + uint32_t timeoutStart = 0; /** * Delay for the current mode transition, used for time out From 520ed881bb77c07c6cf2ba86ce4a1dbfebfe4e20 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 19 Apr 2020 15:16:44 +0200 Subject: [PATCH 025/653] wrong function call fixed --- devicehandlers/DeviceHandlerBase.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 3e17b451..24b56572 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -55,7 +55,7 @@ DeviceHandlerBase::~DeviceHandlerBase() { ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { this->pstStep = counter; - if (counter == 0) { + if (getComAction() == SEND_WRITE) { cookieInfo.state = COOKIE_UNUSED; readCommandQueue(); doStateMachine(); @@ -67,7 +67,7 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { if (mode == MODE_OFF) { return RETURN_OK; } - switch (getCommandQueue()) { + switch (getComAction()) { case SEND_WRITE: if ((cookieInfo.state == COOKIE_UNUSED)) { buildInternalCommand(); From ff47fa191af805884b226e3f3940164c75152bee Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 19 Apr 2020 15:25:17 +0200 Subject: [PATCH 026/653] Communication interface rework As discussed, open/reOpen not used anymore, replaced by initializeInterface call. Using CookieIF. --- devicehandlers/DeviceCommunicationIF.h | 149 ++++++++++++++++++------- 1 file changed, 106 insertions(+), 43 deletions(-) diff --git a/devicehandlers/DeviceCommunicationIF.h b/devicehandlers/DeviceCommunicationIF.h index e0aca573..bb095116 100644 --- a/devicehandlers/DeviceCommunicationIF.h +++ b/devicehandlers/DeviceCommunicationIF.h @@ -1,63 +1,126 @@ #ifndef DEVICECOMMUNICATIONIF_H_ #define DEVICECOMMUNICATIONIF_H_ -#include +#include +#include #include +/** + * @defgroup interfaces Interfaces + * @brief Interfaces for flight software objects + */ +/** + * @defgroup comm Communication + * @brief Communication software components. + */ + +/** + * @brief This is an interface to decouple device communication from + * the device handler to allow reuse of these components. + * @details + * Documentation: Dissertation Baetz p.138. + * 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. + * The CommunicationMessage message type can be used to extend the + * functionality of the ComIF if a separate polling task is required. + * @ingroup interfaces + * @ingroup comm + */ class DeviceCommunicationIF: public HasReturnvaluesIF { public: 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); - static const ReturnValue_t INVALID_ADDRESS = MAKE_RETURN_CODE(0x03); - static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x04); - static const ReturnValue_t NULLPOINTER = MAKE_RETURN_CODE(0x05); - static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0x06); - static const ReturnValue_t CANT_CHANGE_REPLY_LEN = MAKE_RETURN_CODE(0x07); + //! This is returned in readReceivedMessage() if no reply was reived. + static const ReturnValue_t NO_REPLY_RECEIVED = MAKE_RETURN_CODE(0x01); - virtual ~DeviceCommunicationIF() { + //! General protocol error. Define more concrete errors in child handler + static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0x02); + //! If cookie is a null pointer + static const ReturnValue_t NULLPOINTER = MAKE_RETURN_CODE(0x03); + static const ReturnValue_t INVALID_COOKIE_TYPE = MAKE_RETURN_CODE(0x04); + // is this needed if there is no open/close call? + static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x05); + static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x06); - } - - virtual ReturnValue_t open(Cookie **cookie, uint32_t address, - uint32_t maxReplyLen) = 0; + virtual ~DeviceCommunicationIF() {} /** - * Use an existing cookie to open a connection to a new DeviceCommunication. - * The previous connection must not be closed. - * If the returnvalue is not RETURN_OK, the cookie is unchanged and - * can be used with the previous connection. + * @brief Device specific initialization, using the cookie. + * @details + * The cookie is already prepared in the factory. If the communication + * interface needs to be set up in some way and requires cookie information, + * this can be performed in this function, which is called on device handler + * initialization. + * @param cookie + * @return + * - @c RETURN_OK if initialization was successfull + * - Everything else triggers failure event with returnvalue as parameter 1 + */ + virtual ReturnValue_t initializeInterface(CookieIF * cookie) = 0; + + /** + * 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 + * - @c RETURN_OK for successfull send + * - Everything else triggers failure event with returnvalue as parameter 1 + */ + virtual ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t * sendData, + size_t sendLen) = 0; + + /** + * Called by DHB in the GET_WRITE doGetWrite(). + * Get send confirmation that the data in sendMessage() was sent successfully. + * @param cookie + * @return - @c RETURN_OK if data was sent successfull + * - Everything else triggers falure event with + * returnvalue as parameter 1 + */ + virtual ReturnValue_t getSendSuccess(CookieIF *cookie) = 0; + + /** + * Called by DHB in the SEND_WRITE doSendRead(). + * It is assumed that it is always possible to request a reply + * from a device. If a requestLen of 0 is supplied, no reply was enabled + * and communication specific action should be taken (e.g. read nothing + * or read everything). * * @param cookie - * @param address - * @param maxReplyLen - * @return + * @param requestLen Size of data to read + * @return - @c RETURN_OK to confirm the request for data has been sent. + * - Everything else triggers failure event with + * returnvalue as parameter 1 */ - virtual ReturnValue_t reOpen(Cookie *cookie, uint32_t address, - uint32_t maxReplyLen) = 0; - - virtual void close(Cookie *cookie) = 0; - - //SHOULDDO can data be const? - virtual ReturnValue_t sendMessage(Cookie *cookie, uint8_t *data, - uint32_t len) = 0; - - virtual ReturnValue_t getSendSuccess(Cookie *cookie) = 0; - - virtual ReturnValue_t requestReceiveMessage(Cookie *cookie) = 0; - - virtual ReturnValue_t readReceivedMessage(Cookie *cookie, uint8_t **buffer, - uint32_t *size) = 0; - - virtual ReturnValue_t setAddress(Cookie *cookie, uint32_t address) = 0; - - virtual uint32_t getAddress(Cookie *cookie) = 0; - - virtual ReturnValue_t setParameter(Cookie *cookie, uint32_t parameter) = 0; - - virtual uint32_t getParameter(Cookie *cookie) = 0; + virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie, size_t requestLen) = 0; + /** + * Called by DHB in the GET_WRITE doGetRead(). + * This function is used to receive data from the physical device + * by implementing and calling related drivers or wrapper functions. + * @param cookie + * @param buffer [out] Set reply here (by using *buffer = ...) + * @param size [out] size pointer to set (by using *size = ...). + * Set to 0 if no reply was received + * @return - @c RETURN_OK for successfull receive + * - @c NO_REPLY_RECEIVED if not reply was received. Setting size to + * 0 has the same effect + * - Everything else triggers failure event with + * returnvalue as parameter 1 + */ + virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, + size_t *size) = 0; }; #endif /* DEVICECOMMUNICATIONIF_H_ */ From 1820ad14b7f16511d06073fae3f1c5c9540c6309 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 19 Apr 2020 15:48:17 +0200 Subject: [PATCH 027/653] API change introduced, using new device comIF also changed child handler base. --- devicehandlers/ChildHandlerBase.cpp | 19 ++++++++++--------- devicehandlers/ChildHandlerBase.h | 8 ++++---- devicehandlers/DeviceHandlerBase.cpp | 24 ++++++++++++------------ devicehandlers/DeviceHandlerBase.h | 12 ++++++------ 4 files changed, 32 insertions(+), 31 deletions(-) diff --git a/devicehandlers/ChildHandlerBase.cpp b/devicehandlers/ChildHandlerBase.cpp index 50a5c07e..7144db8f 100644 --- a/devicehandlers/ChildHandlerBase.cpp +++ b/devicehandlers/ChildHandlerBase.cpp @@ -2,15 +2,16 @@ #include #include -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, FailureIsolationBase* customFdir, uint32_t cmdQueueSize) : - DeviceHandlerBase(ioBoardAddress, setObjectId, maxDeviceReplyLen, - setDeviceSwitch, deviceCommunication, thermalStatePoolId, - thermalRequestPoolId, (customFdir == NULL? &childHandlerFdir : customFdir), cmdQueueSize), parentId( - parent), childHandlerFdir(setObjectId) { +ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId, + object_id_t deviceCommunication, CookieIF * comCookie, + uint8_t setDeviceSwitch, uint32_t thermalStatePoolId, + uint32_t thermalRequestPoolId, uint32_t parent, + FailureIsolationBase* customFdir, size_t cmdQueueSize) : + DeviceHandlerBase(setObjectId, deviceCommunication, comCookie, + setDeviceSwitch, thermalStatePoolId,thermalRequestPoolId, + (customFdir == nullptr? &childHandlerFdir : customFdir), + cmdQueueSize), + parentId(parent), childHandlerFdir(setObjectId) { } ChildHandlerBase::~ChildHandlerBase() { diff --git a/devicehandlers/ChildHandlerBase.h b/devicehandlers/ChildHandlerBase.h index 3879f66f..59cf26b1 100644 --- a/devicehandlers/ChildHandlerBase.h +++ b/devicehandlers/ChildHandlerBase.h @@ -6,12 +6,12 @@ class ChildHandlerBase: public DeviceHandlerBase { public: - ChildHandlerBase(uint32_t ioBoardAddress, object_id_t setObjectId, - object_id_t deviceCommunication, uint32_t maxDeviceReplyLen, + ChildHandlerBase(object_id_t setObjectId, + object_id_t deviceCommunication, CookieIF * comCookie, uint8_t setDeviceSwitch, uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, uint32_t parent, - FailureIsolationBase* customFdir = NULL, - uint32_t cmdQueueSize = 20); + FailureIsolationBase* customFdir = nullptr, + size_t cmdQueueSize = 20); virtual ~ChildHandlerBase(); virtual ReturnValue_t initialize(); diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 05062ad6..e979799f 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -16,17 +16,17 @@ 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, - FailureIsolationBase* fdirInstance, uint32_t cmdQueueSize) : +DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, + object_id_t deviceCommunication, CookieIF * comCookie, + uint8_t setDeviceSwitch, uint32_t thermalStatePoolId, + uint32_t thermalRequestPoolId, FailureIsolationBase* fdirInstance, + size_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), + comCookie(comCookie), commandQueue(NULL), deviceThermalStatePoolId(thermalStatePoolId), deviceThermalRequestPoolId(thermalRequestPoolId), healthHelper(this, setObjectId), modeHelper(this), parameterHelper(this), childTransitionFailure(RETURN_OK), ignoreMissedRepliesCount(0), fdirInstance(fdirInstance), hkSwitcher(this), @@ -102,7 +102,7 @@ ReturnValue_t DeviceHandlerBase::initialize() { return RETURN_FAILED; } - result = communicationInterface->initializeInterface(cookie); + result = communicationInterface->initializeInterface(comCookie); if (result != RETURN_OK) { return result; } @@ -503,7 +503,7 @@ void DeviceHandlerBase::replyToReply(DeviceReplyMap::iterator iter, void DeviceHandlerBase::doSendWrite() { if (cookieInfo.state == COOKIE_WRITE_READY) { - ReturnValue_t result = communicationInterface->sendMessage(cookie, + ReturnValue_t result = communicationInterface->sendMessage(comCookie, rawPacket, rawPacketLen); if (result == RETURN_OK) { @@ -524,7 +524,7 @@ void DeviceHandlerBase::doGetWrite() { return; } cookieInfo.state = COOKIE_UNUSED; - ReturnValue_t result = communicationInterface->getSendSuccess(cookie); + ReturnValue_t result = communicationInterface->getSendSuccess(comCookie); if (result == RETURN_OK) { if (wiretappingMode == RAW) { replyRawData(rawPacket, rawPacketLen, requestedRawTraffic, true); @@ -556,7 +556,7 @@ void DeviceHandlerBase::doSendRead() { requestLen = 0; } - result = communicationInterface->requestReceiveMessage(cookie, requestLen); + result = communicationInterface->requestReceiveMessage(comCookie, requestLen); if (result == RETURN_OK) { cookieInfo.state = COOKIE_READ_SENT; @@ -584,8 +584,8 @@ void DeviceHandlerBase::doGetRead() { cookieInfo.state = COOKIE_UNUSED; - result = communicationInterface->readReceivedMessage(cookie, &receivedData, - &receivedDataLen); + result = communicationInterface->readReceivedMessage(comCookie, + &receivedData, &receivedDataLen); if (result != RETURN_OK) { triggerEvent(DEVICE_REQUESTING_REPLY_FAILED, result); diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 44ee636d..0f3633dd 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -27,7 +27,7 @@ void setStaticFrameworkObjectIds(); class StorageManagerIF; /** - * \defgroup devices Devices + * @defgroup devices Devices * Contains all devices and the DeviceHandlerBase class. */ @@ -99,12 +99,12 @@ public: * @param fdirInstance * @param cmdQueueSize */ - DeviceHandlerBase(uint32_t ioBoardAddress, object_id_t setObjectId, - uint32_t maxDeviceReplyLen, uint8_t setDeviceSwitch, - object_id_t deviceCommunication, + DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, + CookieIF * comCookie, uint8_t setDeviceSwitch, uint32_t thermalStatePoolId = PoolVariableIF::NO_PARAMETER, uint32_t thermalRequestPoolId = PoolVariableIF::NO_PARAMETER, - FailureIsolationBase* fdirInstance = NULL, uint32_t cmdQueueSize = 20); + FailureIsolationBase* fdirInstance = nullptr, + size_t cmdQueueSize = 20); /** * @brief This function is the device handler base core component and is @@ -555,7 +555,7 @@ protected: /** * Cookie used for communication */ - CookieIF *cookie; + CookieIF * comCookie; struct DeviceCommandInfo { bool isExecuting; //!< Indicates if the command is already executing. From 7f08bb35061885ab6c07125aa478d9096f562813 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 19 Apr 2020 15:54:28 +0200 Subject: [PATCH 028/653] removed ioboardAddress, max reply Len --- devicehandlers/DeviceHandlerBase.cpp | 6 +++--- devicehandlers/DeviceHandlerBase.h | 10 ---------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index e979799f..9d464973 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -22,8 +22,8 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, uint32_t thermalRequestPoolId, FailureIsolationBase* fdirInstance, size_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), + submode(SUBMODE_NONE), pstStep(0), wiretappingMode(OFF), + defaultRawReceiver(0), storedRawData(StorageManagerIF::INVALID_ADDRESS), requestedRawTraffic(0), powerSwitcher(NULL), IPCStore(NULL), deviceCommunicationId(deviceCommunication), communicationInterface(NULL), comCookie(comCookie), commandQueue(NULL), deviceThermalStatePoolId(thermalStatePoolId), @@ -31,7 +31,7 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t 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), + executingTask(NULL), actionHelper(this, NULL), cookieInfo(), timeoutStart(0), childTransitionDelay(5000), transitionSourceMode(_MODE_POWER_DOWN), transitionSourceSubMode(SUBMODE_NONE), deviceSwitch(setDeviceSwitch) { commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize, diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 0f3633dd..872903ca 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -498,11 +498,6 @@ protected: */ uint8_t pstStep; - /** - * This will be used in the RMAP getRead command as expected length, is set by the constructor, can be modiefied at will. - */ - const uint32_t maxDeviceReplyLen; - /** * wiretapping flag: * @@ -994,11 +989,6 @@ private: */ CookieInfo cookieInfo; - /** - * cached from ctor for initialize() - */ - const uint32_t ioBoardAddress; - /** * Used for timing out mode transitions. * From fd100cb9945f2c4d875a08db3ee72a3927fe10d2 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 19 Apr 2020 16:10:44 +0200 Subject: [PATCH 029/653] header function order change fillCOmmandANdREplyMAp is now closer to its helper functions --- devicehandlers/DeviceHandlerBase.h | 202 +++++++++++++++-------------- 1 file changed, 107 insertions(+), 95 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 2e125e84..f31e1b7b 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -268,51 +268,6 @@ protected: virtual ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t * commandData, size_t commandDataLen) = 0; - /** - * @brief fill the #deviceCommandMap - * called by the initialize() of the base class - * @details - * This is used to let the base class know which replies are expected. - * There are different scenarios regarding this: - * - * - "Normal" commands. These are commands, that trigger a direct reply - * from the device. In this case, the id of the command should be added - * to the command map with a commandData_t where maxDelayCycles is set - * to the maximum expected number of PST cycles the reply will take. - * Then, scanForReply returns the id of the command and the base class - * can handle time-out and missing replies. - * - * - Periodic, unrequested replies. These are replies that, once enabled, - * are sent by the device on its own in a defined interval. - * In this case, the id of the reply or a placeholder id should be added - * to the deviceCommandMap with a commandData_t where maxDelayCycles is - * set to the maximum expected number of PST cycles between two replies - * (also a tolerance should be added, as an FDIR message will be - * generated if it is missed). - * - * (Robin) This part confuses me. "must do as soon as" implies that - * the developer must do something somewhere else in the code. Is - * that really the case? If I understood correctly, DHB performs - * almost everything (e.g. in erirm function) as long as the commands - * are inserted correctly. - * - * As soon as the replies are enabled, DeviceCommandInfo.periodic must - * be set to true, DeviceCommandInfo.delayCycles to - * DeviceCommandInfo.maxDelayCycles. - * From then on, the base class handles the reception. - * Then, scanForReply returns the id of the reply or the placeholder id - * and the base class will take care of checking that all replies are - * received and the interval is correct. - * When the replies are disabled, DeviceCommandInfo.periodic must be set - * to 0, DeviceCommandInfo.delayCycles to 0; - * - * - Aperiodic, unrequested replies. These are replies that are sent - * by the device without any preceding command and not in a defined - * interval. These are not entered in the deviceCommandMap but - * handled by returning @c APERIODIC_REPLY in scanForReply(). - */ - virtual void fillCommandAndReplyMap() = 0; - /** * @brief Scans a buffer for a valid reply. * @details @@ -370,14 +325,114 @@ protected: virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) = 0; + /** + * @brief fill the #deviceCommandMap + * called by the initialize() of the base class + * @details + * This is used to let the base class know which replies are expected. + * There are different scenarios regarding this: + * + * - "Normal" commands. These are commands, that trigger a direct reply + * from the device. In this case, the id of the command should be added + * to the command map with a commandData_t where maxDelayCycles is set + * to the maximum expected number of PST cycles the reply will take. + * Then, scanForReply returns the id of the command and the base class + * can handle time-out and missing replies. + * + * - Periodic, unrequested replies. These are replies that, once enabled, + * are sent by the device on its own in a defined interval. + * In this case, the id of the reply or a placeholder id should be added + * to the deviceCommandMap with a commandData_t where maxDelayCycles is + * set to the maximum expected number of PST cycles between two replies + * (also a tolerance should be added, as an FDIR message will be + * generated if it is missed). + * + * (Robin) This part confuses me. "must do as soon as" implies that + * the developer must do something somewhere else in the code. Is + * that really the case? If I understood correctly, DHB performs + * almost everything (e.g. in erirm function) as long as the commands + * are inserted correctly. + * + * As soon as the replies are enabled, DeviceCommandInfo.periodic must + * be set to true, DeviceCommandInfo.delayCycles to + * DeviceCommandInfo.maxDelayCycles. + * From then on, the base class handles the reception. + * Then, scanForReply returns the id of the reply or the placeholder id + * and the base class will take care of checking that all replies are + * received and the interval is correct. + * When the replies are disabled, DeviceCommandInfo.periodic must be set + * to 0, DeviceCommandInfo.delayCycles to 0; + * + * - Aperiodic, unrequested replies. These are replies that are sent + * by the device without any preceding command and not in a defined + * interval. These are not entered in the deviceCommandMap but + * handled by returning @c APERIODIC_REPLY in scanForReply(). + */ + virtual void fillCommandAndReplyMap() = 0; + + /** + * This is a helper method to facilitate inserting entries in the command map. + * @param deviceCommand Identifier of the command to add. + * @param maxDelayCycles The maximum number of delay cycles the command + * waits until it times out. + * @param periodic Indicates if the command is periodic (i.e. it is sent + * by the device repeatedly without request) or not. Default is aperiodic (0) + * @return - @c RETURN_OK when the command was successfully inserted, + * - @c RETURN_FAILED else. + */ + ReturnValue_t insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, + uint16_t maxDelayCycles, size_t replyLen = 0, uint8_t periodic = 0, + bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0); + + /** + * @brief This is a helper method to insert replies in the reply map. + * @param deviceCommand Identifier of the reply to add. + * @param maxDelayCycles The maximum number of delay cycles the reply waits + * until it times out. + * @param periodic Indicates if the command is periodic (i.e. it is sent + * by the device repeatedly without request) or not. Default is aperiodic (0) + * @return - @c RETURN_OK when the command was successfully inserted, + * - @c RETURN_FAILED else. + */ + ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, + uint16_t maxDelayCycles, size_t replyLen = 0, uint8_t periodic = 0); + + /** + * @brief A simple command to add a command to the commandList. + * @param deviceCommand The command to add + * @return - @c RETURN_OK when the command was successfully inserted, + * - @c RETURN_FAILED else. + */ + ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand); + /** + * @brief This is a helper method to facilitate updating entries + * in the reply map. + * @param deviceCommand Identifier of the reply to update. + * @param delayCycles The current number of delay cycles to wait. + * As stated in #fillCommandAndCookieMap, to disable periodic commands, + * this is set to zero. + * @param maxDelayCycles The maximum number of delay cycles the reply waits + * until it times out. By passing 0 the entry remains untouched. + * @param periodic Indicates if the command is periodic (i.e. it is sent + * by the device repeatedly without request) or not.Default is aperiodic (0). + * Warning: The setting always overrides the value that was entered in the map. + * @return - @c RETURN_OK when the command was successfully inserted, + * - @c RETURN_FAILED else. + */ + ReturnValue_t updateReplyMapEntry(DeviceCommandId_t deviceReply, + uint16_t delayCycles, uint16_t maxDelayCycles, + uint8_t periodic = 0); + /** * @brief Can be implemented by child handler to * perform debugging * @details Example: Calling this in performOperation * to track values like mode. - * @param positionTracker Provide the child handler a way to know where the debugInterface was called - * @param objectId Provide the child handler object Id to specify actions for spefic devices - * @param parameter Supply a parameter of interest + * @param positionTracker Provide the child handler a way to know + * where the debugInterface was called + * @param objectId Provide the child handler object Id to + * specify actions for spefic devices + * @param parameter Supply a parameter of interest * Please delete all debugInterface calls in DHB after debugging is finished ! */ virtual void debugInterface(uint8_t positionTracker = 0, @@ -391,7 +446,8 @@ protected: * MODE_ON -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] * MODE_NORMAL -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] * MODE_RAW -> [MODE_ON, MODE_NORMAL, MODE_RAW, _MODE_POWER_DOWN] - * _MODE_START_UP -> MODE_ON (do not include time to set the switches, the base class got you covered) + * _MODE_START_UP -> MODE_ON (do not include time to set the switches, + * the base class got you covered) * * The default implementation returns 0 ! * @param modeFrom @@ -413,7 +469,6 @@ protected: */ virtual ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches); - public: /** * @param parentQueueId @@ -646,11 +701,6 @@ protected: void replyReturnvalueToCommand(ReturnValue_t status, uint32_t parameter = 0); - /** - * - - * @param parameter2 additional parameter - */ void replyToCommand(ReturnValue_t status, uint32_t parameter = 0); /** @@ -658,7 +708,8 @@ protected: * * Sets #timeoutStart with every call. * - * Sets #transitionTargetMode if necessary so transitional states can be entered from everywhere without breaking the state machine + * Sets #transitionTargetMode if necessary so transitional states can be + * entered from everywhere without breaking the state machine * (which relies on a correct #transitionTargetMode). * * The submode is left unchanged. @@ -745,45 +796,6 @@ protected: */ virtual ReturnValue_t buildChildRawCommand(); - /** - * This is a helper method to facilitate inserting entries in the command map. - * @param deviceCommand Identifier of the command to add. - * @param maxDelayCycles The maximum number of delay cycles the command waits until it times out. - * @param periodic Indicates if the command is periodic (i.e. it is sent by the device repeatedly without request) or not. - * Default is aperiodic (0) - * @return RETURN_OK when the command was successfully inserted, COMMAND_MAP_ERROR else. - */ - ReturnValue_t insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, - uint16_t maxDelayCycles, size_t replyLen = 0, uint8_t periodic = 0, - bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0); - /** - * This is a helper method to insert replies in the reply map. - * @param deviceCommand Identifier of the reply to add. - * @param maxDelayCycles The maximum number of delay cycles the reply waits until it times out. - * @param periodic Indicates if the command is periodic (i.e. it is sent by the device repeatedly without request) or not. - * Default is aperiodic (0) - * @return RETURN_OK when the command was successfully inserted, COMMAND_MAP_ERROR else. - */ - ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, - uint16_t maxDelayCycles, size_t replyLen = 0, uint8_t periodic = 0); - /** - * A simple command to add a command to the commandList. - * @param deviceCommand The command to add - * @return RETURN_OK if the command was successfully inserted, RETURN_FAILED else. - */ - ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand); - /** - * This is a helper method to facilitate updating entries in the reply map. - * @param deviceCommand Identifier of the reply to update. - * @param delayCycles The current number of delay cycles to wait. As stated in #fillCommandAndCookieMap, to disable periodic commands, this is set to zero. - * @param maxDelayCycles The maximum number of delay cycles the reply waits until it times out. By passing 0 the entry remains untouched. - * @param periodic Indicates if the command is periodic (i.e. it is sent by the device repeatedly without request) or not. - * Default is aperiodic (0). Warning: The setting always overrides the value that was entered in the map. - * @return RETURN_OK when the reply was successfully updated, COMMAND_MAP_ERROR else. - */ - ReturnValue_t updateReplyMapEntry(DeviceCommandId_t deviceReply, - uint16_t delayCycles, uint16_t maxDelayCycles, - uint8_t periodic = 0); /** * Returns the delay cycle count of a reply. * A count != 0 indicates that the command is already executed. From 3bd83c00f590dcb15dc37429f202c261928acdae Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 19 Apr 2020 21:52:13 +0200 Subject: [PATCH 030/653] freeRTOS with included with extern"C" --- osal/FreeRTOS/FixedTimeslotTask.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.h b/osal/FreeRTOS/FixedTimeslotTask.h index bed13051..d20b8268 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.h +++ b/osal/FreeRTOS/FixedTimeslotTask.h @@ -5,8 +5,10 @@ #include #include -#include +extern "C" { +#include "FreeRTOS.h" #include "task.h" +} class FixedTimeslotTask: public FixedTimeslotTaskIF { public: From 225e1b98a00f9a73efa840200f25780b7303c986 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 19 Apr 2020 22:10:02 +0200 Subject: [PATCH 031/653] some bugfixes in cpp file to enable compilation --- devicehandlers/DeviceHandlerBase.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index dff2a412..84e97819 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -1027,7 +1027,6 @@ void DeviceHandlerBase::replyRawReplyIfnotWiretapped(const uint8_t* data, ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage( CommandMessage * message) { - ReturnValue_t result; switch (message->getCommand()) { case DeviceHandlerMessage::CMD_WIRETAPPING: switch (DeviceHandlerMessage::getWiretappingMode(message)) { @@ -1050,17 +1049,17 @@ ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage( replyReturnvalueToCommand(RETURN_OK); return RETURN_OK; case DeviceHandlerMessage::CMD_SWITCH_IOBOARD: - if (mode != MODE_OFF) { - replyReturnvalueToCommand(WRONG_MODE_FOR_COMMAND); - } else { - result = switchCookieChannel( - DeviceHandlerMessage::getIoBoardObjectId(message)); - if (result == RETURN_OK) { - replyReturnvalueToCommand(RETURN_OK); - } else { - replyReturnvalueToCommand(CANT_SWITCH_IO_ADDRESS); - } - } +// if (mode != MODE_OFF) { +// replyReturnvalueToCommand(WRONG_MODE_FOR_COMMAND); +// } else { +//// result = switchCookieChannel( +//// DeviceHandlerMessage::getIoBoardObjectId(message)); +// if (result == RETURN_OK) { +// replyReturnvalueToCommand(RETURN_OK); +// } else { +// replyReturnvalueToCommand(CANT_SWITCH_IO_ADDRESS); +// } +// } return RETURN_OK; case DeviceHandlerMessage::CMD_RAW: if ((mode != MODE_RAW)) { @@ -1275,3 +1274,7 @@ void DeviceHandlerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) { void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_){ executingTask = task_; } + +// Default implementation empty. +void DeviceHandlerBase::debugInterface(uint8_t positionTracker, + object_id_t objectId, uint32_t parameter) {} From b78b3ac68a36248255c5859a5b89c4dfb27c1f1c Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 19 Apr 2020 22:17:14 +0200 Subject: [PATCH 032/653] added performOperationHook() --- devicehandlers/DeviceHandlerBase.cpp | 5 ++++- devicehandlers/DeviceHandlerBase.h | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 84e97819..3331f5f9 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -61,6 +61,7 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { decrementDeviceReplyMap(); fdirInstance->checkForFailures(); hkSwitcher.performOperation(); + performOperationHook(); } if (mode == MODE_OFF) { return RETURN_OK; @@ -1275,6 +1276,8 @@ void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_){ executingTask = task_; } -// Default implementation empty. +// Default implementations empty. void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t objectId, uint32_t parameter) {} + +void DeviceHandlerBase::performOperationHook() {} diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index f31e1b7b..d0c95a5a 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -469,6 +469,12 @@ protected: */ virtual ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches); + + /** + * @brief Hook function for child handlers which is called once per + * performOperation(). Default implementation is empty. + */ + virtual void performOperationHook(); public: /** * @param parentQueueId From ea904642d1c8b4085b03fdd2837912ebe242c20c Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 21 Apr 2020 16:16:02 +0200 Subject: [PATCH 033/653] CCSDS time possible bugfix for sscanf() --- timemanager/CCSDSTime.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/timemanager/CCSDSTime.cpp b/timemanager/CCSDSTime.cpp index 32032716..8a0e65b7 100644 --- a/timemanager/CCSDSTime.cpp +++ b/timemanager/CCSDSTime.cpp @@ -1,5 +1,6 @@ #include #include +#include #include CCSDSTime::CCSDSTime() { @@ -160,9 +161,10 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* uint8_t hour; uint8_t minute; float second; -//try Code A (yyyy-mm-dd) - int count = sscanf((char *) from, "%4hi-%2hhi-%2hiT%2hhi:%2hhi:%fZ", &year, - &month, &day, &hour, &minute, &second); + //try Code A (yyyy-mm-dd) + int count = sscanf((char *) from, "%4" SCNu16 "-%2" SCNu8 "-%2" SCNu16 + "T%2" SCNu8 ":%2" SCNu8 ":%fZ", &year, &month, &day, + &hour, &minute, &second); if (count == 6) { to->year = year; to->month = month; @@ -175,8 +177,8 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* } //try Code B (yyyy-ddd) - count = sscanf((char *) from, "%4hi-%3hiT%2hhi:%2hhi:%fZ", &year, &day, - &hour, &minute, &second); + count = sscanf((char *) from, "%4" SCNu16 "-%3" SCNu16 "T%2" SCNu8 + ":%2" SCNu8 ":%fZ", &year, &day, &hour, &minute, &second); if (count == 5) { uint8_t tempDay; ReturnValue_t result = CCSDSTime::convertDaysOfYear(day, year, &month, @@ -193,7 +195,6 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* to->usecond = (second - floor(second)) * 1000000; return RETURN_OK; } - return UNSUPPORTED_TIME_FORMAT; } From c30cae3431d586304bf0d3fd1c5d1ff05d7f9691 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 21 Apr 2020 16:32:39 +0200 Subject: [PATCH 034/653] added back NoC99 io section --- timemanager/CCSDSTime.cpp | 46 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/timemanager/CCSDSTime.cpp b/timemanager/CCSDSTime.cpp index 8a0e65b7..e00beb27 100644 --- a/timemanager/CCSDSTime.cpp +++ b/timemanager/CCSDSTime.cpp @@ -155,6 +155,51 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* if (length < 19) { return RETURN_FAILED; } + // Newlib nano can't parse uint8, see SCNu8 documentation and https://sourceware.org/newlib/README + // Suggestion: use uint16 all the time. This should work on all systems. +#ifdef NEWLIB_NANO_NO_C99_IO + uint16_t year; + uint16_t month; + uint16_t day; + uint16_t hour; + uint16_t minute; + float second; + int count = sscanf((char *) from, "%4" SCNu16 "-%2" SCNu16 "-%2" + SCNu16 "T%2" SCNu16 ":%2" SCNu16 ":%fZ", &year, &month, &day, &hour, + &minute, &second); + if (count == 6) { + to->year = year; + to->month = month; + to->day = day; + to->hour = hour; + to->minute = minute; + to->second = second; + to->usecond = (second - floor(second)) * 1000000; + return RETURN_OK; + } + + // try Code B (yyyy-ddd) + count = sscanf((char *) from, "%4" SCNu16 "-%3" SCNu16 "T%2" SCNu16 ":%2" + SCNu16 ":%fZ", &year, &day, &hour, &minute, &second); + if (count == 5) { + uint8_t tempDay; + ReturnValue_t result = CCSDSTime::convertDaysOfYear(day, year, + reinterpret_cast(&month), reinterpret_cast(&tempDay)); + if (result != RETURN_OK) { + return RETURN_FAILED; + } + to->year = year; + to->month = month; + to->day = tempDay; + to->hour = hour; + to->minute = minute; + to->second = second; + to->usecond = (second - floor(second)) * 1000000; + return RETURN_OK; + } + // Warning: Compiler/Linker fails ambiguously if library does not implement + // C99 I/O +#else uint16_t year; uint8_t month; uint16_t day; @@ -195,6 +240,7 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* to->usecond = (second - floor(second)) * 1000000; return RETURN_OK; } +#endif return UNSUPPORTED_TIME_FORMAT; } From 209332948168edcb994c44bd24c242c6c05c4af9 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Tue, 21 Apr 2020 21:34:03 +0200 Subject: [PATCH 035/653] working on updating SerializeIF, to quote Basti: This is going to be horrible --- container/FixedMap.h | 16 +- container/IndexedRingMemoryArray.h | 32 +-- datapool/DataPoolParameterWrapper.cpp | 6 +- datapool/PIDReader.h | 34 ++-- datapool/PoolRawAccess.cpp | 22 ++- datapool/PoolRawAccess.h | 16 +- datapool/PoolVariable.h | 30 +-- datapool/PoolVector.h | 6 +- devicehandlers/DeviceTmReportingWrapper.cpp | 8 +- globalfunctions/Type.cpp | 10 +- globalfunctions/Type.h | 16 +- globalfunctions/matching/MatchTree.h | 2 +- globalfunctions/matching/RangeMatcher.h | 29 +-- health/HealthTable.cpp | 6 +- memory/MemoryHelper.cpp | 6 +- osal/rtems/CpuUsage.cpp | 16 +- parameters/ParameterWrapper.cpp | 16 +- parameters/ParameterWrapper.h | 2 +- power/PowerComponent.cpp | 8 +- serialize/EndianSwapper.h | 46 ++++- serialize/SerialArrayListAdapter.h | 10 +- serialize/SerialBufferAdapter.cpp | 8 +- serialize/SerialLinkedListAdapter.h | 36 ++-- serialize/SerializeAdapter.h | 198 +++++++++---------- serialize/SerializeElement.h | 34 ++-- serialize/SerializeIF.h | 15 +- subsystem/Subsystem.cpp | 2 +- subsystem/modes/ModeDefinitions.h | 16 +- thermal/ThermalComponent.cpp | 8 +- tmstorage/TmStorePackets.h | 38 ++-- tmtcpacket/packetmatcher/ApidMatcher.h | 6 +- tmtcpacket/packetmatcher/ServiceMatcher.h | 6 +- tmtcpacket/packetmatcher/SubserviceMatcher.h | 6 +- tmtcservices/CommandingServiceBase.cpp | 2 +- tmtcservices/PusVerificationReport.cpp | 18 +- 35 files changed, 389 insertions(+), 341 deletions(-) diff --git a/container/FixedMap.h b/container/FixedMap.h index 0b84bf4e..eaf8a24c 100644 --- a/container/FixedMap.h +++ b/container/FixedMap.h @@ -150,13 +150,13 @@ public: virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, const uint32_t max_size, bool bigEndian) const { - ReturnValue_t result = SerializeAdapter::serialize(&this->_size, + ReturnValue_t result = SerializeAdapter::serialize(&this->_size, buffer, size, max_size, bigEndian); uint32_t i = 0; while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) { - result = SerializeAdapter::serialize(&theMap[i].first, buffer, + result = SerializeAdapter::serialize(&theMap[i].first, buffer, size, max_size, bigEndian); - result = SerializeAdapter::serialize(&theMap[i].second, buffer, size, + result = SerializeAdapter::serialize(&theMap[i].second, buffer, size, max_size, bigEndian); ++i; } @@ -168,9 +168,9 @@ public: uint32_t i = 0; for (i = 0; i < _size; ++i) { - printSize += SerializeAdapter::getSerializedSize( + printSize += SerializeAdapter::getSerializedSize( &theMap[i].first); - printSize += SerializeAdapter::getSerializedSize(&theMap[i].second); + printSize += SerializeAdapter::getSerializedSize(&theMap[i].second); } return printSize; @@ -178,16 +178,16 @@ public: virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, bool bigEndian) { - ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size, + ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size, buffer, size, bigEndian); if (this->_size > theMap.maxSize()) { return SerializeIF::TOO_MANY_ELEMENTS; } uint32_t i = 0; while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) { - result = SerializeAdapter::deSerialize(&theMap[i].first, buffer, + result = SerializeAdapter::deSerialize(&theMap[i].first, buffer, size, bigEndian); - result = SerializeAdapter::deSerialize(&theMap[i].second, buffer, size, + result = SerializeAdapter::deSerialize(&theMap[i].second, buffer, size, bigEndian); ++i; } diff --git a/container/IndexedRingMemoryArray.h b/container/IndexedRingMemoryArray.h index 992b7489..32b61c2d 100644 --- a/container/IndexedRingMemoryArray.h +++ b/container/IndexedRingMemoryArray.h @@ -70,7 +70,7 @@ public: 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); + ReturnValue_t result = SerializeAdapter::serialize(&blockStartAddress,buffer,size,max_size,bigEndian); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } @@ -78,17 +78,17 @@ public: if(result != HasReturnvaluesIF::RETURN_OK){ return result; } - result = AutoSerializeAdapter::serialize(&this->size,buffer,size,max_size,bigEndian); + result = SerializeAdapter::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); + result = SerializeAdapter::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); + ReturnValue_t result = SerializeAdapter::deSerialize(&blockStartAddress,buffer,size,bigEndian); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } @@ -96,11 +96,11 @@ public: if(result != HasReturnvaluesIF::RETURN_OK){ return result; } - result = AutoSerializeAdapter::deSerialize(&this->size,buffer,size,bigEndian); + result = SerializeAdapter::deSerialize(&this->size,buffer,size,bigEndian); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } - result = AutoSerializeAdapter::deSerialize(&this->storedPackets,buffer,size,bigEndian); + result = SerializeAdapter::deSerialize(&this->storedPackets,buffer,size,bigEndian); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } @@ -108,10 +108,10 @@ public: } uint32_t getSerializedSize() const { - uint32_t size = AutoSerializeAdapter::getSerializedSize(&blockStartAddress); + uint32_t size = SerializeAdapter::getSerializedSize(&blockStartAddress); size += indexType.getSerializedSize(); - size += AutoSerializeAdapter::getSerializedSize(&this->size); - size += AutoSerializeAdapter::getSerializedSize(&this->storedPackets); + size += SerializeAdapter::getSerializedSize(&this->size); + size += SerializeAdapter::getSerializedSize(&this->storedPackets); return size; } @@ -500,14 +500,14 @@ public: if(result != HasReturnvaluesIF::RETURN_OK){ return result; } - result = AutoSerializeAdapter::serialize(&this->size,buffer,size,max_size,bigEndian); + result = SerializeAdapter::serialize(&this->size,buffer,size,max_size,bigEndian); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } uint32_t i = 0; while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->size)) { - result = SerializeAdapter >::serialize(&this->entries[i], buffer, size, + result = SerializeAdapter::serialize(&this->entries[i], buffer, size, max_size, bigEndian); ++i; } @@ -515,7 +515,7 @@ public: return result; } uint16_t crc = Calculate_CRC(crcBuffer,(*size-oldSize)); - result = AutoSerializeAdapter::serialize(&crc,buffer,size,max_size,bigEndian); + result = SerializeAdapter::serialize(&crc,buffer,size,max_size,bigEndian); return result; } @@ -531,10 +531,10 @@ public: size += additionalInfo->getSerializedSize(); } size += currentWriteBlock->getSerializedSize(); - size += AutoSerializeAdapter::getSerializedSize(&this->size); + size += SerializeAdapter::getSerializedSize(&this->size); size += (this->entries[0].getSerializedSize()) * this->size; uint16_t crc = 0; - size += AutoSerializeAdapter::getSerializedSize(&crc); + size += SerializeAdapter::getSerializedSize(&crc); return size; } /** @@ -563,7 +563,7 @@ public: return result; } uint32_t tempSize = 0; - result = AutoSerializeAdapter::deSerialize(&tempSize,buffer,size,bigEndian); + result = SerializeAdapter::deSerialize(&tempSize,buffer,size,bigEndian); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } @@ -572,7 +572,7 @@ public: } uint32_t i = 0; while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->size)) { - result = SerializeAdapter >::deSerialize( + result = SerializeAdapter::deSerialize( &this->entries[i], buffer, size, bigEndian); ++i; diff --git a/datapool/DataPoolParameterWrapper.cpp b/datapool/DataPoolParameterWrapper.cpp index 0ff2121d..10fb5392 100644 --- a/datapool/DataPoolParameterWrapper.cpp +++ b/datapool/DataPoolParameterWrapper.cpp @@ -39,18 +39,18 @@ ReturnValue_t DataPoolParameterWrapper::serialize(uint8_t** buffer, uint32_t* size, const uint32_t max_size, bool bigEndian) const { ReturnValue_t result; - result = SerializeAdapter::serialize(&type, buffer, size, max_size, + result = SerializeAdapter::serialize(&type, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::serialize(&columns, buffer, size, + result = SerializeAdapter::serialize(&columns, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::serialize(&rows, buffer, size, max_size, + result = SerializeAdapter::serialize(&rows, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; diff --git a/datapool/PIDReader.h b/datapool/PIDReader.h index 299cc2fe..ac1d169e 100644 --- a/datapool/PIDReader.h +++ b/datapool/PIDReader.h @@ -17,7 +17,7 @@ protected: uint8_t valid; ReturnValue_t read() { uint8_t arrayIndex = DataPool::PIDToArrayIndex(parameterId); - PoolEntry* read_out = ::dataPool.getData( + PoolEntry *read_out = ::dataPool.getData( DataPool::PIDToDataPoolId(parameterId), arrayIndex); if (read_out != NULL) { valid = read_out->valid; @@ -43,7 +43,8 @@ protected: * Empty ctor for List initialization */ PIDReader() : - parameterId(PoolVariableIF::NO_PARAMETER), valid(PoolVariableIF::INVALID), value(0) { + parameterId(PoolVariableIF::NO_PARAMETER), valid( + PoolVariableIF::INVALID), value(0) { } public: @@ -63,9 +64,9 @@ public: * \param setWritable If this flag is set to true, changes in the value attribute can be * written back to the data pool, otherwise not. */ - PIDReader(uint32_t setParameterId, DataSetIF* dataSet) : - parameterId(setParameterId), valid( - PoolVariableIF::INVALID), value(0) { + PIDReader(uint32_t setParameterId, DataSetIF *dataSet) : + parameterId(setParameterId), valid(PoolVariableIF::INVALID), value( + 0) { if (dataSet != NULL) { dataSet->registerVariable(this); } @@ -74,7 +75,7 @@ public: /** * Copy ctor to copy classes containing Pool Variables. */ - PIDReader(const PIDReader& rhs) : + PIDReader(const PIDReader &rhs) : parameterId(rhs.parameterId), valid(rhs.valid), value(rhs.value) { } @@ -121,24 +122,25 @@ public: return value; } - PIDReader &operator=(T newValue) { + PIDReader& operator=(T newValue) { value = newValue; return *this; } - virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { - return SerializeAdapter::serialize(&value, buffer, size, max_size, - bigEndian); + virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, + size_t maxSize, Endianness streamEndianness) const override { + return SerializeAdapter::serialize(&value, buffer, size, maxSize, + streamEndianness); } - virtual uint32_t getSerializedSize() const { - return SerializeAdapter::getSerializedSize(&value); + virtual size_t getSerializedSize() const override { + return SerializeAdapter::getSerializedSize(&value); } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { - return SerializeAdapter::deSerialize(&value, buffer, size, bigEndian); + virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override { + return SerializeAdapter::deSerialize(&value, buffer, size, + streamEndianness); } }; diff --git a/datapool/PoolRawAccess.cpp b/datapool/PoolRawAccess.cpp index 555896bb..2053498b 100644 --- a/datapool/PoolRawAccess.cpp +++ b/datapool/PoolRawAccess.cpp @@ -145,10 +145,12 @@ uint16_t PoolRawAccess::getSizeTillEnd() const { return sizeTillEnd; } -ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { - if (typeSize + *size <= max_size) { - if (bigEndian) { +ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { + //TODO integer overflow + if (typeSize + *size <= maxSize) { +#error use endian swapper + if (1) { #ifndef BYTE_ORDER_SYSTEM #error BYTE_ORDER_SYSTEM not defined #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN @@ -169,16 +171,16 @@ ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, uint32_t* size, } } -uint32_t PoolRawAccess::getSerializedSize() const { +size_t PoolRawAccess::getSerializedSize() const { return typeSize; } -ReturnValue_t PoolRawAccess::deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { - *size -= typeSize; - if (*size >= 0) { +ReturnValue_t PoolRawAccess::deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) { - if (bigEndian) { + if (*size >= typeSize) { + *size -= typeSize; + if (1) { #ifndef BYTE_ORDER_SYSTEM #error BYTE_ORDER_SYSTEM not defined #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN diff --git a/datapool/PoolRawAccess.h b/datapool/PoolRawAccess.h index 3e2bd7ae..190c38a9 100644 --- a/datapool/PoolRawAccess.h +++ b/datapool/PoolRawAccess.h @@ -70,7 +70,7 @@ public: static const ReturnValue_t DATA_POOL_ACCESS_FAILED = MAKE_RETURN_CODE(0x02); uint8_t value[RAW_MAX_SIZE]; PoolRawAccess(uint32_t data_pool_id, uint8_t arrayEntry, - DataSetIF* data_set, ReadWriteMode_t setReadWriteMode = + DataSetIF *data_set, ReadWriteMode_t setReadWriteMode = PoolVariableIF::VAR_READ); /** * \brief The classes destructor is empty. If commit() was not called, the local value is @@ -97,7 +97,7 @@ public: * \return - \c RETURN_OK if entry could be acquired * - \c RETURN_FAILED else. */ - ReturnValue_t getEntryEndianSafe(uint8_t* buffer, uint32_t* size, + ReturnValue_t getEntryEndianSafe(uint8_t *buffer, uint32_t *size, uint32_t max_size); /** * With this method, the content can be set from a big endian buffer safely. @@ -106,7 +106,7 @@ public: * @return - \c RETURN_OK on success * - \c RETURN_FAILED on failure */ - ReturnValue_t setEntryFromBigEndian(const uint8_t* buffer, + ReturnValue_t setEntryFromBigEndian(const uint8_t *buffer, uint32_t setSize); /** * \brief This operation returns the type of the entry currently stored. @@ -140,13 +140,13 @@ public: */ uint16_t getSizeTillEnd() const; - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const; + ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const override; - uint32_t getSerializedSize() const; + size_t getSerializedSize() const override; - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian); + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override; }; #endif /* POOLRAWACCESS_H_ */ diff --git a/datapool/PoolVariable.h b/datapool/PoolVariable.h index 25345c0a..ce073426 100644 --- a/datapool/PoolVariable.h +++ b/datapool/PoolVariable.h @@ -58,7 +58,7 @@ protected: * The operation does NOT provide any mutual exclusive protection by itself. */ ReturnValue_t read() { - PoolEntry* read_out = ::dataPool.getData(dataPoolId, 1); + PoolEntry *read_out = ::dataPool.getData < T > (dataPoolId, 1); if (read_out != NULL) { valid = read_out->valid; value = *(read_out->address); @@ -79,7 +79,7 @@ protected: * */ ReturnValue_t commit() { - PoolEntry* write_back = ::dataPool.getData(dataPoolId, 1); + PoolEntry *write_back = ::dataPool.getData < T > (dataPoolId, 1); if ((write_back != NULL) && (readWriteMode != VAR_READ)) { write_back->valid = valid; *(write_back->address) = value; @@ -115,7 +115,7 @@ public: * \param setWritable If this flag is set to true, changes in the value attribute can be * written back to the data pool, otherwise not. */ - PoolVariable(uint32_t set_id, DataSetIF* dataSet, + PoolVariable(uint32_t set_id, DataSetIF *dataSet, ReadWriteMode_t setReadWriteMode) : dataPoolId(set_id), valid(PoolVariableIF::INVALID), readWriteMode( setReadWriteMode), value(0) { @@ -126,7 +126,7 @@ public: /** * Copy ctor to copy classes containing Pool Variables. */ - PoolVariable(const PoolVariable& rhs) : + PoolVariable(const PoolVariable &rhs) : dataPoolId(rhs.dataPoolId), valid(rhs.valid), readWriteMode( rhs.readWriteMode), value(rhs.value) { } @@ -184,29 +184,29 @@ public: return value; } - PoolVariable &operator=(T newValue) { + PoolVariable& operator=(T newValue) { value = newValue; return *this; } - PoolVariable &operator=(PoolVariable newPoolVariable) { + PoolVariable& operator=(PoolVariable newPoolVariable) { value = newPoolVariable.value; return *this; } - virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { - return SerializeAdapter::serialize(&value, buffer, size, max_size, - bigEndian); + virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, + size_t max_size, Endianness streamEndianness) const override { + return SerializeAdapter::serialize(&value, buffer, size, max_size, + streamEndianness); } - virtual uint32_t getSerializedSize() const { - return SerializeAdapter::getSerializedSize(&value); + virtual uint32_t getSerializedSize() const override { + return SerializeAdapter::getSerializedSize(&value); } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { - return SerializeAdapter::deSerialize(&value, buffer, size, bigEndian); + virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override { + return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness); } }; diff --git a/datapool/PoolVector.h b/datapool/PoolVector.h index d3617d17..3809f93b 100644 --- a/datapool/PoolVector.h +++ b/datapool/PoolVector.h @@ -202,7 +202,7 @@ public: uint16_t i; ReturnValue_t result; for (i = 0; i < vector_size; i++) { - result = SerializeAdapter::serialize(&(value[i]), buffer, size, + result = SerializeAdapter::serialize(&(value[i]), buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; @@ -212,7 +212,7 @@ public: } virtual uint32_t getSerializedSize() const { - return vector_size * SerializeAdapter::getSerializedSize(value); + return vector_size * SerializeAdapter::getSerializedSize(value); } virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, @@ -220,7 +220,7 @@ public: uint16_t i; ReturnValue_t result; for (i = 0; i < vector_size; i++) { - result = SerializeAdapter::deSerialize(&(value[i]), buffer, size, + result = SerializeAdapter::deSerialize(&(value[i]), buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; diff --git a/devicehandlers/DeviceTmReportingWrapper.cpp b/devicehandlers/DeviceTmReportingWrapper.cpp index 2c9e820f..55861c3c 100644 --- a/devicehandlers/DeviceTmReportingWrapper.cpp +++ b/devicehandlers/DeviceTmReportingWrapper.cpp @@ -13,12 +13,12 @@ DeviceTmReportingWrapper::~DeviceTmReportingWrapper() { ReturnValue_t DeviceTmReportingWrapper::serialize(uint8_t** buffer, uint32_t* size, const uint32_t max_size, bool bigEndian) const { - ReturnValue_t result = SerializeAdapter::serialize(&objectId, + ReturnValue_t result = SerializeAdapter::serialize(&objectId, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::serialize(&actionId, buffer, + result = SerializeAdapter::serialize(&actionId, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; @@ -32,12 +32,12 @@ uint32_t DeviceTmReportingWrapper::getSerializedSize() const { ReturnValue_t DeviceTmReportingWrapper::deSerialize(const uint8_t** buffer, int32_t* size, bool bigEndian) { - ReturnValue_t result = SerializeAdapter::deSerialize(&objectId, + ReturnValue_t result = SerializeAdapter::deSerialize(&objectId, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::deSerialize(&actionId, buffer, + result = SerializeAdapter::deSerialize(&actionId, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; diff --git a/globalfunctions/Type.cpp b/globalfunctions/Type.cpp index 814d26f4..b7b7fd82 100644 --- a/globalfunctions/Type.cpp +++ b/globalfunctions/Type.cpp @@ -68,13 +68,13 @@ ReturnValue_t Type::serialize(uint8_t** buffer, uint32_t* size, return result; } - result = SerializeAdapter::serialize(&ptc, buffer, size, max_size, + result = SerializeAdapter::serialize(&ptc, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::serialize(&pfc, buffer, size, max_size, + result = SerializeAdapter::serialize(&pfc, buffer, size, max_size, bigEndian); return result; @@ -83,20 +83,20 @@ ReturnValue_t Type::serialize(uint8_t** buffer, uint32_t* size, uint32_t Type::getSerializedSize() const { uint8_t dontcare = 0; - return 2 * SerializeAdapter::getSerializedSize(&dontcare); + return 2 * SerializeAdapter::getSerializedSize(&dontcare); } ReturnValue_t Type::deSerialize(const uint8_t** buffer, int32_t* size, bool bigEndian) { uint8_t ptc; uint8_t pfc; - ReturnValue_t result = SerializeAdapter::deSerialize(&ptc, buffer, + ReturnValue_t result = SerializeAdapter::deSerialize(&ptc, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::deSerialize(&pfc, buffer, size, + result = SerializeAdapter::deSerialize(&pfc, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; diff --git a/globalfunctions/Type.h b/globalfunctions/Type.h index 88df07b6..3ec250b0 100644 --- a/globalfunctions/Type.h +++ b/globalfunctions/Type.h @@ -22,7 +22,7 @@ public: Type(ActualType_t actualType); - Type(const Type& type); + Type(const Type &type); Type& operator=(Type rhs); @@ -30,8 +30,8 @@ public: operator ActualType_t() const; - bool operator==(const Type& rhs); - bool operator!=(const Type& rhs); + bool operator==(const Type &rhs); + bool operator!=(const Type &rhs); uint8_t getSize() const; @@ -39,13 +39,13 @@ public: static ActualType_t getActualType(uint8_t ptc, uint8_t pfc); - virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const; + virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, + size_t maxSize, Endianness streamEndianness) const override; - virtual uint32_t getSerializedSize() const; + virtual size_t getSerializedSize() const override; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian); + virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override; private: ActualType_t actualType; diff --git a/globalfunctions/matching/MatchTree.h b/globalfunctions/matching/MatchTree.h index 398cf3f0..0ee3890b 100644 --- a/globalfunctions/matching/MatchTree.h +++ b/globalfunctions/matching/MatchTree.h @@ -49,7 +49,7 @@ public: const uint32_t max_size, bool bigEndian) const { iterator iter = this->begin(); uint8_t count = this->countRight(iter); - ReturnValue_t result = SerializeAdapter::serialize(&count, + ReturnValue_t result = SerializeAdapter::serialize(&count, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; diff --git a/globalfunctions/matching/RangeMatcher.h b/globalfunctions/matching/RangeMatcher.h index 10e07173..c30406f6 100644 --- a/globalfunctions/matching/RangeMatcher.h +++ b/globalfunctions/matching/RangeMatcher.h @@ -4,7 +4,6 @@ #include #include - template class RangeMatcher: public SerializeableMatcherIF { public: @@ -27,34 +26,40 @@ public: } } - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { - ReturnValue_t result = SerializeAdapter::serialize(&lowerBound, buffer, size, max_size, bigEndian); + ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t max_size, + SerializeIF::Endianness streamEndianness) const override { + ReturnValue_t result = SerializeAdapter::serialize(&lowerBound, buffer, + size, max_size, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::serialize(&upperBound, buffer, size, max_size, bigEndian); + result = SerializeAdapter::serialize(&upperBound, buffer, size, + max_size, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - return SerializeAdapter::serialize(&inverted, buffer, size, max_size, bigEndian); + return SerializeAdapter::serialize(&inverted, buffer, size, max_size, + streamEndianness); } - uint32_t getSerializedSize() const { + uint32_t getSerializedSize() const override { return sizeof(lowerBound) + sizeof(upperBound) + sizeof(bool); } - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { - ReturnValue_t result = SerializeAdapter::deSerialize(&lowerBound, buffer, size, bigEndian); + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + SerializeIF::Endianness streamEndianness) override { + ReturnValue_t result = SerializeAdapter::deSerialize(&lowerBound, + buffer, size, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::deSerialize(&upperBound, buffer, size, bigEndian); + result = SerializeAdapter::deSerialize(&upperBound, buffer, size, + streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - return SerializeAdapter::deSerialize(&inverted, buffer, size, bigEndian); + return SerializeAdapter::deSerialize(&inverted, buffer, size, + streamEndianness); } protected: bool doMatch(T input) { diff --git a/health/HealthTable.cpp b/health/HealthTable.cpp index a575b282..48ee6679 100644 --- a/health/HealthTable.cpp +++ b/health/HealthTable.cpp @@ -67,16 +67,16 @@ void HealthTable::printAll(uint8_t* pointer, uint32_t maxSize) { mutex->lockMutex(MutexIF::NO_TIMEOUT); uint32_t size = 0; uint16_t count = healthMap.size(); - ReturnValue_t result = SerializeAdapter::serialize(&count, + ReturnValue_t result = SerializeAdapter::serialize(&count, &pointer, &size, maxSize, true); HealthMap::iterator iter; for (iter = healthMap.begin(); iter != healthMap.end() && result == HasReturnvaluesIF::RETURN_OK; ++iter) { - result = SerializeAdapter::serialize(&iter->first, + result = SerializeAdapter::serialize(&iter->first, &pointer, &size, maxSize, true); uint8_t health = iter->second; - result = SerializeAdapter::serialize(&health, &pointer, &size, + result = SerializeAdapter::serialize(&health, &pointer, &size, maxSize, true); } mutex->unlockMutex(); diff --git a/memory/MemoryHelper.cpp b/memory/MemoryHelper.cpp index 69830084..c89fd5a4 100644 --- a/memory/MemoryHelper.cpp +++ b/memory/MemoryHelper.cpp @@ -53,7 +53,7 @@ void MemoryHelper::completeLoad(ReturnValue_t errorCode, memcpy(copyHere, dataToCopy, size); break; case HasMemoryIF::POINTS_TO_VARIABLE: - EndianSwapper::swap(copyHere, dataToCopy, size); + EndianConverter::convertBigEndian(copyHere, dataToCopy, size); break; case HasMemoryIF::ACTIVITY_COMPLETED: case RETURN_OK: @@ -86,7 +86,7 @@ void MemoryHelper::completeDump(ReturnValue_t errorCode, case HasMemoryIF::POINTS_TO_VARIABLE: //"data" must be valid pointer! if (errorCode == HasMemoryIF::POINTS_TO_VARIABLE) { - EndianSwapper::swap(reservedSpaceInIPC, dataToCopy, size); + EndianConverter::convertBigEndian(reservedSpaceInIPC, dataToCopy, size); } else { memcpy(reservedSpaceInIPC, dataToCopy, size); } @@ -136,7 +136,7 @@ void MemoryHelper::swapMatrixCopy(uint8_t* out, const uint8_t *in, } while (totalSize > 0){ - EndianSwapper::swap(out,in,datatypeSize); + EndianConverter::convertBigEndian(out,in,datatypeSize); out += datatypeSize; in += datatypeSize; totalSize -= datatypeSize; diff --git a/osal/rtems/CpuUsage.cpp b/osal/rtems/CpuUsage.cpp index 9fc34ff1..903a4d0e 100644 --- a/osal/rtems/CpuUsage.cpp +++ b/osal/rtems/CpuUsage.cpp @@ -91,7 +91,7 @@ void CpuUsage::clear() { ReturnValue_t CpuUsage::serialize(uint8_t** buffer, uint32_t* size, const uint32_t max_size, bool bigEndian) const { - ReturnValue_t result = SerializeAdapter::serialize( + ReturnValue_t result = SerializeAdapter::serialize( &timeSinceLastReset, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; @@ -111,7 +111,7 @@ uint32_t CpuUsage::getSerializedSize() const { ReturnValue_t CpuUsage::deSerialize(const uint8_t** buffer, int32_t* size, bool bigEndian) { - ReturnValue_t result = SerializeAdapter::deSerialize( + ReturnValue_t result = SerializeAdapter::deSerialize( &timeSinceLastReset, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; @@ -122,7 +122,7 @@ ReturnValue_t CpuUsage::deSerialize(const uint8_t** buffer, int32_t* size, ReturnValue_t CpuUsage::ThreadData::serialize(uint8_t** buffer, uint32_t* size, const uint32_t max_size, bool bigEndian) const { - ReturnValue_t result = SerializeAdapter::serialize(&id, buffer, + ReturnValue_t result = SerializeAdapter::serialize(&id, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; @@ -133,12 +133,12 @@ ReturnValue_t CpuUsage::ThreadData::serialize(uint8_t** buffer, uint32_t* size, memcpy(*buffer, name, MAX_LENGTH_OF_THREAD_NAME); *size += MAX_LENGTH_OF_THREAD_NAME; *buffer += MAX_LENGTH_OF_THREAD_NAME; - result = SerializeAdapter::serialize(&timeRunning, + result = SerializeAdapter::serialize(&timeRunning, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::serialize(&percentUsage, + result = SerializeAdapter::serialize(&percentUsage, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; @@ -159,7 +159,7 @@ uint32_t CpuUsage::ThreadData::getSerializedSize() const { ReturnValue_t CpuUsage::ThreadData::deSerialize(const uint8_t** buffer, int32_t* size, bool bigEndian) { - ReturnValue_t result = SerializeAdapter::deSerialize(&id, buffer, + ReturnValue_t result = SerializeAdapter::deSerialize(&id, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; @@ -169,12 +169,12 @@ ReturnValue_t CpuUsage::ThreadData::deSerialize(const uint8_t** buffer, } memcpy(name, *buffer, MAX_LENGTH_OF_THREAD_NAME); *buffer -= MAX_LENGTH_OF_THREAD_NAME; - result = SerializeAdapter::deSerialize(&timeRunning, + result = SerializeAdapter::deSerialize(&timeRunning, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::deSerialize(&percentUsage, + result = SerializeAdapter::deSerialize(&percentUsage, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; diff --git a/parameters/ParameterWrapper.cpp b/parameters/ParameterWrapper.cpp index 8f661bb3..9dcbc6d5 100644 --- a/parameters/ParameterWrapper.cpp +++ b/parameters/ParameterWrapper.cpp @@ -24,18 +24,18 @@ ReturnValue_t ParameterWrapper::serialize(uint8_t** buffer, uint32_t* size, const uint32_t max_size, bool bigEndian) const { ReturnValue_t result; - result = SerializeAdapter::serialize(&type, buffer, size, max_size, + result = SerializeAdapter::serialize(&type, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::serialize(&columns, buffer, size, + result = SerializeAdapter::serialize(&columns, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::serialize(&rows, buffer, size, max_size, + result = SerializeAdapter::serialize(&rows, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; @@ -94,7 +94,7 @@ ReturnValue_t ParameterWrapper::serializeData(uint8_t** buffer, uint32_t* size, ReturnValue_t result; uint16_t dataSize = columns * rows; while (dataSize != 0) { - result = SerializeAdapter::serialize(element, buffer, size, max_size, + result = SerializeAdapter::serialize(element, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; @@ -123,7 +123,7 @@ ReturnValue_t ParameterWrapper::deSerializeData(uint8_t startingRow, + (((startingRow + fromRow) * columns) + startingColumn); for (uint8_t fromColumn = 0; fromColumn < fromColumns; fromColumn++) { - result = SerializeAdapter::deSerialize( + result = SerializeAdapter::deSerialize( dataWithDataType + fromColumn, &fromAsStream, &streamSize, true); if (result != HasReturnvaluesIF::RETURN_OK) { @@ -155,18 +155,18 @@ ReturnValue_t ParameterWrapper::deSerialize(const uint8_t** buffer, ReturnValue_t ParameterWrapper::set(const uint8_t* stream, int32_t streamSize, const uint8_t **remainingStream, int32_t *remainingSize) { - ReturnValue_t result = SerializeAdapter::deSerialize(&type, &stream, + ReturnValue_t result = SerializeAdapter::deSerialize(&type, &stream, &streamSize, true); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::deSerialize(&columns, &stream, + result = SerializeAdapter::deSerialize(&columns, &stream, &streamSize, true); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::deSerialize(&rows, &stream, &streamSize, + result = SerializeAdapter::deSerialize(&rows, &stream, &streamSize, true); if (result != HasReturnvaluesIF::RETURN_OK) { return result; diff --git a/parameters/ParameterWrapper.h b/parameters/ParameterWrapper.h index f61786b8..e6d29c59 100644 --- a/parameters/ParameterWrapper.h +++ b/parameters/ParameterWrapper.h @@ -54,7 +54,7 @@ public: const uint8_t *streamWithtype = (const uint8_t *) readonlyData; streamWithtype += (row * columns + column) * type.getSize(); int32_t size = type.getSize(); - return SerializeAdapter::deSerialize(value, &streamWithtype, + return SerializeAdapter::deSerialize(value, &streamWithtype, &size, true); } else { const T *dataWithType = (const T *) readonlyData; diff --git a/power/PowerComponent.cpp b/power/PowerComponent.cpp index 6a87d88b..53bb06c8 100644 --- a/power/PowerComponent.cpp +++ b/power/PowerComponent.cpp @@ -19,12 +19,12 @@ PowerComponent::PowerComponent(object_id_t setId, uint8_t moduleId, float min, f ReturnValue_t PowerComponent::serialize(uint8_t** buffer, uint32_t* size, const uint32_t max_size, bool bigEndian) const { - ReturnValue_t result = SerializeAdapter::serialize(&min, buffer, + ReturnValue_t result = SerializeAdapter::serialize(&min, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - return SerializeAdapter::serialize(&max, buffer, size, max_size, + return SerializeAdapter::serialize(&max, buffer, size, max_size, bigEndian); } @@ -58,12 +58,12 @@ float PowerComponent::getMax() { ReturnValue_t PowerComponent::deSerialize(const uint8_t** buffer, int32_t* size, bool bigEndian) { - ReturnValue_t result = SerializeAdapter::deSerialize(&min, buffer, + ReturnValue_t result = SerializeAdapter::deSerialize(&min, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - return SerializeAdapter::deSerialize(&max, buffer, size, bigEndian); + return SerializeAdapter::deSerialize(&max, buffer, size, bigEndian); } ReturnValue_t PowerComponent::getParameter(uint8_t domainId, diff --git a/serialize/EndianSwapper.h b/serialize/EndianSwapper.h index 6ff54444..e142c2a1 100644 --- a/serialize/EndianSwapper.h +++ b/serialize/EndianSwapper.h @@ -5,20 +5,20 @@ #include #include -class EndianSwapper { +class EndianConverter { private: - EndianSwapper() { + EndianConverter() { } ; public: template - static T swap(T in) { + static T convertBigEndian(T in) { #ifndef BYTE_ORDER_SYSTEM #error BYTE_ORDER_SYSTEM not defined #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN T tmp; - uint8_t *pointerOut = (uint8_t *) &tmp; - uint8_t *pointerIn = (uint8_t *) ∈ + uint8_t *pointerOut = (uint8_t*) &tmp; + uint8_t *pointerIn = (uint8_t*) ∈ for (uint8_t count = 0; count < sizeof(T); count++) { pointerOut[sizeof(T) - count - 1] = pointerIn[count]; } @@ -29,7 +29,8 @@ public: #error Unknown Byte Order #endif } - static void swap(uint8_t* out, const uint8_t* in, uint32_t size) { + static void convertBigEndian(uint8_t *out, const uint8_t *in, + uint32_t size) { #ifndef BYTE_ORDER_SYSTEM #error BYTE_ORDER_SYSTEM not defined #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN @@ -40,6 +41,39 @@ public: #elif BYTE_ORDER_SYSTEM == BIG_ENDIAN memcpy(out, in, size); return; +#endif + } + + template + static T convertLittleEndian(T in) { +#ifndef BYTE_ORDER_SYSTEM + #error BYTE_ORDER_SYSTEM not defined + #elif BYTE_ORDER_SYSTEM == BIG_ENDIAN + T tmp; + uint8_t *pointerOut = (uint8_t *) &tmp; + uint8_t *pointerIn = (uint8_t *) ∈ + for (uint8_t count = 0; count < sizeof(T); count++) { + pointerOut[sizeof(T) - count - 1] = pointerIn[count]; + } + return tmp; + #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN + return in; +#else + #error Unknown Byte Order + #endif + } + static void convertLittleEndian(uint8_t *out, const uint8_t *in, + uint32_t size) { +#ifndef BYTE_ORDER_SYSTEM + #error BYTE_ORDER_SYSTEM not defined + #elif BYTE_ORDER_SYSTEM == BIG_ENDIAN + for (uint8_t count = 0; count < size; count++) { + out[size - count - 1] = in[count]; + } + return; + #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN + memcpy(out, in, size); + return; #endif } }; diff --git a/serialize/SerialArrayListAdapter.h b/serialize/SerialArrayListAdapter.h index 5ffbc375..ab0c6c6f 100644 --- a/serialize/SerialArrayListAdapter.h +++ b/serialize/SerialArrayListAdapter.h @@ -27,11 +27,11 @@ public: static ReturnValue_t serialize(const ArrayList* list, uint8_t** buffer, uint32_t* size, const uint32_t max_size, bool bigEndian) { - ReturnValue_t result = SerializeAdapter::serialize(&list->size, + ReturnValue_t result = SerializeAdapter::serialize(&list->size, buffer, size, max_size, bigEndian); count_t i = 0; while ((result == HasReturnvaluesIF::RETURN_OK) && (i < list->size)) { - result = SerializeAdapter::serialize(&list->entries[i], buffer, size, + result = SerializeAdapter::serialize(&list->entries[i], buffer, size, max_size, bigEndian); ++i; } @@ -47,7 +47,7 @@ public: count_t i = 0; for (i = 0; i < list->size; ++i) { - printSize += SerializeAdapter::getSerializedSize(&list->entries[i]); + printSize += SerializeAdapter::getSerializedSize(&list->entries[i]); } return printSize; @@ -61,7 +61,7 @@ public: static ReturnValue_t deSerialize(ArrayList* list, const uint8_t** buffer, int32_t* size, bool bigEndian) { count_t tempSize = 0; - ReturnValue_t result = SerializeAdapter::deSerialize(&tempSize, + ReturnValue_t result = SerializeAdapter::deSerialize(&tempSize, buffer, size, bigEndian); if (tempSize > list->maxSize()) { return SerializeIF::TOO_MANY_ELEMENTS; @@ -69,7 +69,7 @@ public: list->size = tempSize; count_t i = 0; while ((result == HasReturnvaluesIF::RETURN_OK) && (i < list->size)) { - result = SerializeAdapter::deSerialize( + result = SerializeAdapter::deSerialize( &list->front()[i], buffer, size, bigEndian); ++i; diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index 3ed083bf..f78ec8ac 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -26,14 +26,14 @@ ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, uint32_t* size const uint32_t max_size, bool bigEndian) const { uint32_t serializedLength = bufferLength; if (serializeLength) { - serializedLength += AutoSerializeAdapter::getSerializedSize( + serializedLength += SerializeAdapter::getSerializedSize( &bufferLength); } if (*size + serializedLength > max_size) { return BUFFER_TOO_SHORT; } else { if (serializeLength) { - AutoSerializeAdapter::serialize(&bufferLength, buffer, size, + SerializeAdapter::serialize(&bufferLength, buffer, size, max_size, bigEndian); } if (this->constBuffer != NULL) { @@ -52,7 +52,7 @@ ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, uint32_t* size template uint32_t SerialBufferAdapter::getSerializedSize() const { if (serializeLength) { - return bufferLength + AutoSerializeAdapter::getSerializedSize(&bufferLength); + return bufferLength + SerializeAdapter::getSerializedSize(&bufferLength); } else { return bufferLength; } @@ -63,7 +63,7 @@ ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, //TODO Ignores Endian flag! if (buffer != NULL) { if(serializeLength){ - T serializedSize = AutoSerializeAdapter::getSerializedSize( + T serializedSize = SerializeAdapter::getSerializedSize( &bufferLength); if((*size - bufferLength - serializedSize) >= 0){ *buffer += serializedSize; diff --git a/serialize/SerialLinkedListAdapter.h b/serialize/SerialLinkedListAdapter.h index 29952c4a..7b10e331 100644 --- a/serialize/SerialLinkedListAdapter.h +++ b/serialize/SerialLinkedListAdapter.h @@ -31,32 +31,32 @@ public: SinglyLinkedList(), printCount(printCount) { } - virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const override { if (printCount) { count_t mySize = SinglyLinkedList::getSize(); - ReturnValue_t result = SerializeAdapter::serialize(&mySize, - buffer, size, max_size, bigEndian); + ReturnValue_t result = SerializeAdapter::serialize(&mySize, + buffer, size, maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } } - return serialize(SinglyLinkedList::start, buffer, size, max_size, - bigEndian); + return serialize(SinglyLinkedList::start, buffer, size, maxSize, + streamEndianness); } static ReturnValue_t serialize(const LinkedElement* element, - uint8_t** buffer, uint32_t* size, const uint32_t max_size, - bool bigEndian) { + uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; while ((result == HasReturnvaluesIF::RETURN_OK) && (element != NULL)) { - result = element->value->serialize(buffer, size, max_size, - bigEndian); + result = element->value->serialize(buffer, size, maxSize, + streamEndianness); element = element->getNext(); } return result; } - virtual uint32_t getSerializedSize() const { + virtual size_t getSerializedSize() const override { if (printCount) { return SerialLinkedListAdapter::getSerializedSize() + sizeof(count_t); @@ -64,8 +64,8 @@ public: return getSerializedSize(SinglyLinkedList::start); } } - static uint32_t getSerializedSize(const LinkedElement *element) { - uint32_t size = 0; + static size_t getSerializedSize(const LinkedElement *element) { + size_t size = 0; while (element != NULL) { size += element->value->getSerializedSize(); element = element->getNext(); @@ -73,16 +73,16 @@ public: return size; } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { - return deSerialize(SinglyLinkedList::start, buffer, size, bigEndian); + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override { + return deSerialize(SinglyLinkedList::start, buffer, size, streamEndianness); } static ReturnValue_t deSerialize(LinkedElement* element, - const uint8_t** buffer, int32_t* size, bool bigEndian) { + const uint8_t** buffer, size_t* size, Endianness streamEndianness) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; while ((result == HasReturnvaluesIF::RETURN_OK) && (element != NULL)) { - result = element->value->deSerialize(buffer, size, bigEndian); + result = element->value->deSerialize(buffer, size, streamEndianness); element = element->getNext(); } return result; diff --git a/serialize/SerializeAdapter.h b/serialize/SerializeAdapter.h index fd9e1b6a..73323c2a 100644 --- a/serialize/SerializeAdapter.h +++ b/serialize/SerializeAdapter.h @@ -10,116 +10,114 @@ /** * \ingroup serialize */ -template -class SerializeAdapter_ { -public: - static ReturnValue_t serialize(const T* object, uint8_t** buffer, - uint32_t* size, const uint32_t max_size, bool bigEndian) { - uint32_t ignoredSize = 0; - if (size == NULL) { - size = &ignoredSize; - } - if (sizeof(T) + *size <= max_size) { - T tmp; - if (bigEndian) { - tmp = EndianSwapper::swap(*object); - } else { - tmp = *object; - } - memcpy(*buffer, &tmp, sizeof(T)); - *size += sizeof(T); - (*buffer) += sizeof(T); - return HasReturnvaluesIF::RETURN_OK; - } else { - return SerializeIF::BUFFER_TOO_SHORT; - } - } - ReturnValue_t deSerialize(T* object, const uint8_t** buffer, int32_t* size, - bool bigEndian) { - T tmp; - *size -= sizeof(T); - if (*size >= 0) { - memcpy(&tmp, *buffer, sizeof(T)); - if (bigEndian) { - *object = EndianSwapper::swap(tmp); - } else { - *object = tmp; - } - *buffer += sizeof(T); - return HasReturnvaluesIF::RETURN_OK; - } else { - return SerializeIF::STREAM_TOO_SHORT; - } - } - - uint32_t getSerializedSize(const T * object) { - return sizeof(T); - } - -}; - -template -class SerializeAdapter_ { -public: - ReturnValue_t serialize(const T* object, uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { - uint32_t ignoredSize = 0; - if (size == NULL) { - size = &ignoredSize; - } - return object->serialize(buffer, size, max_size, bigEndian); - } - uint32_t getSerializedSize(const T* object) const { - return object->getSerializedSize(); - } - - ReturnValue_t deSerialize(T* object, const uint8_t** buffer, int32_t* size, - bool bigEndian) { - return object->deSerialize(buffer, size, bigEndian); - } -}; - -template class SerializeAdapter { -public: - static ReturnValue_t serialize(const T* object, uint8_t** buffer, - uint32_t* size, const uint32_t max_size, bool bigEndian) { - SerializeAdapter_::Is> adapter; - return adapter.serialize(object, buffer, size, max_size, bigEndian); - } - static uint32_t getSerializedSize(const T* object) { - SerializeAdapter_::Is> adapter; - return adapter.getSerializedSize(object); - } - - static ReturnValue_t deSerialize(T* object, const uint8_t** buffer, - int32_t* size, bool bigEndian) { - SerializeAdapter_::Is> adapter; - return adapter.deSerialize(object, buffer, size, bigEndian); - } -}; - - -class AutoSerializeAdapter { public: template - static ReturnValue_t serialize(const T* object, uint8_t** buffer, - uint32_t* size, const uint32_t max_size, bool bigEndian) { - SerializeAdapter_::Is> adapter; - return adapter.serialize(object, buffer, size, max_size, bigEndian); + static ReturnValue_t serialize(const T *object, uint8_t **buffer, + size_t *size, size_t maxSize, SerializeIF::Endianness streamEndianness) { + InternalSerializeAdapter::Is> adapter; + return adapter.serialize(object, buffer, size, maxSize, + streamEndianness); } template - static uint32_t getSerializedSize(const T* object) { - SerializeAdapter_::Is> adapter; + static uint32_t getSerializedSize(const T *object) { + InternalSerializeAdapter::Is> adapter; return adapter.getSerializedSize(object); } template - static ReturnValue_t deSerialize(T* object, const uint8_t** buffer, - int32_t* size, bool bigEndian) { - SerializeAdapter_::Is> adapter; - return adapter.deSerialize(object, buffer, size, bigEndian); + static ReturnValue_t deSerialize(T *object, const uint8_t **buffer, + size_t *size, SerializeIF::Endianness streamEndianness) { + InternalSerializeAdapter::Is> adapter; + return adapter.deSerialize(object, buffer, size, streamEndianness); } +private: + template + class InternalSerializeAdapter { + public: + static ReturnValue_t serialize(const T *object, uint8_t **buffer, + size_t *size, size_t max_size, SerializeIF::Endianness streamEndianness) { + size_t ignoredSize = 0; + if (size == NULL) { + size = &ignoredSize; + } + //TODO check integer overflow of *size + if (sizeof(T) + *size <= max_size) { + T tmp; + switch (streamEndianness) { + case SerializeIF::Endianness::BIG: + tmp = EndianConverter::convertBigEndian(*object); + break; + case SerializeIF::Endianness::LITTLE: + tmp = EndianConverter::convertLittleEndian(*object); + break; + default: + case SerializeIF::Endianness::MACHINE: + tmp = *object; + break; + } + memcpy(*buffer, &tmp, sizeof(T)); + *size += sizeof(T); + (*buffer) += sizeof(T); + return HasReturnvaluesIF::RETURN_OK; + } else { + return SerializeIF::BUFFER_TOO_SHORT; + } + } + + ReturnValue_t deSerialize(T *object, const uint8_t **buffer, + size_t *size, SerializeIF::Endianness streamEndianness) { + T tmp; + if (*size >= sizeof(T)) { + *size -= sizeof(T); + memcpy(&tmp, *buffer, sizeof(T)); + switch (streamEndianness) { + case SerializeIF::Endianness::BIG: + *object = EndianConverter::convertBigEndian(tmp); + break; + case SerializeIF::Endianness::LITTLE: + *object = EndianConverter::convertLittleEndian(tmp); + break; + default: + case SerializeIF::Endianness::MACHINE: + *object = tmp; + break; + } + + *buffer += sizeof(T); + return HasReturnvaluesIF::RETURN_OK; + } else { + return SerializeIF::STREAM_TOO_SHORT; + } + } + + uint32_t getSerializedSize(const T *object) { + return sizeof(T); + } + + }; + + template + class InternalSerializeAdapter { + public: + ReturnValue_t serialize(const T *object, uint8_t **buffer, + size_t *size, size_t max_size, + SerializeIF::Endianness streamEndianness) const { + size_t ignoredSize = 0; + if (size == NULL) { + size = &ignoredSize; + } + return object->serialize(buffer, size, max_size, streamEndianness); + } + uint32_t getSerializedSize(const T *object) const { + return object->getSerializedSize(); + } + + ReturnValue_t deSerialize(T *object, const uint8_t **buffer, + size_t *size, SerializeIF::Endianness streamEndianness) { + return object->deSerialize(buffer, size, streamEndianness); + } + }; }; #endif /* SERIALIZEADAPTER_H_ */ diff --git a/serialize/SerializeElement.h b/serialize/SerializeElement.h index db7db20a..22e9838c 100644 --- a/serialize/SerializeElement.h +++ b/serialize/SerializeElement.h @@ -9,41 +9,43 @@ * \ingroup serialize */ template -class SerializeElement : public SerializeIF, public LinkedElement { +class SerializeElement: public SerializeIF, public LinkedElement { public: - template - SerializeElement(Args... args) : LinkedElement(this), entry(std::forward(args)...) { + template + SerializeElement(Args ... args) : + LinkedElement(this), entry(std::forward(args)...) { } - SerializeElement() : LinkedElement(this) { + SerializeElement() : + LinkedElement(this) { } T entry; - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { - return SerializeAdapter::serialize(&entry, buffer, size, max_size, bigEndian); + ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, + Endianness streamEndianness) const override { + return SerializeAdapter::serialize(&entry, buffer, size, maxSize, + streamEndianness); } - uint32_t getSerializedSize() const { - return SerializeAdapter::getSerializedSize(&entry); + uint32_t getSerializedSize() const override { + return SerializeAdapter::getSerializedSize(&entry); } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { - return SerializeAdapter::deSerialize(&entry, buffer, size, bigEndian); + virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override { + return SerializeAdapter::deSerialize(&entry, buffer, size, + streamEndianness); } operator T() { return entry; } - SerializeElement &operator=(T newValue) { + SerializeElement& operator=(T newValue) { entry = newValue; return *this; } - T *operator->() { + T* operator->() { return &entry; } }; - - #endif /* SERIALIZEELEMENT_H_ */ diff --git a/serialize/SerializeIF.h b/serialize/SerializeIF.h index 701fbf56..6c875a5c 100644 --- a/serialize/SerializeIF.h +++ b/serialize/SerializeIF.h @@ -2,6 +2,7 @@ #define SERIALIZEIF_H_ #include +#include /** * \defgroup serialize Serialization @@ -14,6 +15,10 @@ */ class SerializeIF { public: + enum class Endianness : uint8_t { + BIG, LITTLE, MACHINE + }; + static const uint8_t INTERFACE_ID = CLASS_ID::SERIALIZE_IF; static const ReturnValue_t BUFFER_TOO_SHORT = MAKE_RETURN_CODE(1); static const ReturnValue_t STREAM_TOO_SHORT = MAKE_RETURN_CODE(2); @@ -22,13 +27,13 @@ public: virtual ~SerializeIF() { } - virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const = 0; + virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, + size_t max_size, Endianness streamEndianness) const = 0; - virtual uint32_t getSerializedSize() const = 0; + virtual size_t getSerializedSize() const = 0; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) = 0; + virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) = 0; }; diff --git a/subsystem/Subsystem.cpp b/subsystem/Subsystem.cpp index e1ec544b..ef706dd7 100644 --- a/subsystem/Subsystem.cpp +++ b/subsystem/Subsystem.cpp @@ -169,7 +169,7 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage* message) { if (result == RETURN_OK) { Mode_t fallbackId; int32_t size = sizeRead; - result = SerializeAdapter::deSerialize(&fallbackId, + result = SerializeAdapter::deSerialize(&fallbackId, &pointer, &size, true); if (result == RETURN_OK) { result = SerialArrayListAdapter::deSerialize( diff --git a/subsystem/modes/ModeDefinitions.h b/subsystem/modes/ModeDefinitions.h index 8e7531f3..3e749dd8 100644 --- a/subsystem/modes/ModeDefinitions.h +++ b/subsystem/modes/ModeDefinitions.h @@ -23,26 +23,26 @@ public: ReturnValue_t result; - result = SerializeAdapter::serialize(&value1, buffer, size, + result = SerializeAdapter::serialize(&value1, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::serialize(&value2, buffer, size, + result = SerializeAdapter::serialize(&value2, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::serialize(&value3, buffer, size, + result = SerializeAdapter::serialize(&value3, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::serialize(&value4, buffer, size, + result = SerializeAdapter::serialize(&value4, buffer, size, max_size, bigEndian); return result; @@ -57,25 +57,25 @@ public: bool bigEndian) { ReturnValue_t result; - result = SerializeAdapter::deSerialize(&value1, buffer, size, + result = SerializeAdapter::deSerialize(&value1, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::deSerialize(&value2, buffer, size, + result = SerializeAdapter::deSerialize(&value2, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::deSerialize(&value3, buffer, size, + result = SerializeAdapter::deSerialize(&value3, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::deSerialize(&value4, buffer, size, + result = SerializeAdapter::deSerialize(&value4, buffer, size, bigEndian); return result; diff --git a/thermal/ThermalComponent.cpp b/thermal/ThermalComponent.cpp index bf6f7398..93513e16 100644 --- a/thermal/ThermalComponent.cpp +++ b/thermal/ThermalComponent.cpp @@ -47,13 +47,13 @@ ReturnValue_t ThermalComponent::setLimits(const uint8_t* data, uint32_t size) { return MonitoringIF::INVALID_SIZE; } int32_t readSize = size; - SerializeAdapter::deSerialize(&nopParameters.lowerNopLimit, &data, + SerializeAdapter::deSerialize(&nopParameters.lowerNopLimit, &data, &readSize, true); - SerializeAdapter::deSerialize(¶meters.lowerOpLimit, &data, + SerializeAdapter::deSerialize(¶meters.lowerOpLimit, &data, &readSize, true); - SerializeAdapter::deSerialize(¶meters.upperOpLimit, &data, + SerializeAdapter::deSerialize(¶meters.upperOpLimit, &data, &readSize, true); - SerializeAdapter::deSerialize(&nopParameters.upperNopLimit, &data, + SerializeAdapter::deSerialize(&nopParameters.upperNopLimit, &data, &readSize, true); return HasReturnvaluesIF::RETURN_OK; } diff --git a/tmstorage/TmStorePackets.h b/tmstorage/TmStorePackets.h index 6eea6f58..4e7160fb 100644 --- a/tmstorage/TmStorePackets.h +++ b/tmstorage/TmStorePackets.h @@ -34,12 +34,12 @@ public: uint16_t ssc; ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, const uint32_t max_size, bool bigEndian) const { - ReturnValue_t result = SerializeAdapter::serialize(&apid, + ReturnValue_t result = SerializeAdapter::serialize(&apid, buffer, size, max_size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - return SerializeAdapter::serialize(&ssc, buffer, size, + return SerializeAdapter::serialize(&ssc, buffer, size, max_size, bigEndian); } @@ -50,12 +50,12 @@ public: ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, bool bigEndian) { - ReturnValue_t result = SerializeAdapter::deSerialize(&apid, + ReturnValue_t result = SerializeAdapter::deSerialize(&apid, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - return SerializeAdapter::deSerialize(&ssc, buffer, size, + return SerializeAdapter::deSerialize(&ssc, buffer, size, bigEndian); } }; @@ -220,23 +220,23 @@ public: ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, const uint32_t max_size, bool bigEndian) const { - ReturnValue_t result = AutoSerializeAdapter::serialize(&apid,buffer,size,max_size,bigEndian); + ReturnValue_t result = SerializeAdapter::serialize(&apid,buffer,size,max_size,bigEndian); if(result!=HasReturnvaluesIF::RETURN_OK){ return result; } - result = AutoSerializeAdapter::serialize(&sourceSequenceCount,buffer,size,max_size,bigEndian); + result = SerializeAdapter::serialize(&sourceSequenceCount,buffer,size,max_size,bigEndian); if(result!=HasReturnvaluesIF::RETURN_OK){ return result; } - result = AutoSerializeAdapter::serialize(&serviceType,buffer,size,max_size,bigEndian); + result = SerializeAdapter::serialize(&serviceType,buffer,size,max_size,bigEndian); if(result!=HasReturnvaluesIF::RETURN_OK){ return result; } - result = AutoSerializeAdapter::serialize(&serviceSubtype,buffer,size,max_size,bigEndian); + result = SerializeAdapter::serialize(&serviceSubtype,buffer,size,max_size,bigEndian); if(result!=HasReturnvaluesIF::RETURN_OK){ return result; } - result = AutoSerializeAdapter::serialize(&subCounter,buffer,size,max_size,bigEndian); + result = SerializeAdapter::serialize(&subCounter,buffer,size,max_size,bigEndian); if(result!=HasReturnvaluesIF::RETURN_OK){ return result; } @@ -246,11 +246,11 @@ public: uint32_t getSerializedSize() const { uint32_t size = 0; - size += AutoSerializeAdapter::getSerializedSize(&apid); - size += AutoSerializeAdapter::getSerializedSize(&sourceSequenceCount); - size += AutoSerializeAdapter::getSerializedSize(&serviceType); - size += AutoSerializeAdapter::getSerializedSize(&serviceSubtype); - size += AutoSerializeAdapter::getSerializedSize(&subCounter); + size += SerializeAdapter::getSerializedSize(&apid); + size += SerializeAdapter::getSerializedSize(&sourceSequenceCount); + size += SerializeAdapter::getSerializedSize(&serviceType); + size += SerializeAdapter::getSerializedSize(&serviceSubtype); + size += SerializeAdapter::getSerializedSize(&subCounter); SerialBufferAdapter adapter(rawTimestamp,sizeof(rawTimestamp)); size += adapter.getSerializedSize(); return size; @@ -259,27 +259,27 @@ public: ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, bool bigEndian) { - ReturnValue_t result = AutoSerializeAdapter::deSerialize(&apid, buffer, + ReturnValue_t result = SerializeAdapter::deSerialize(&apid, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = AutoSerializeAdapter::deSerialize(&sourceSequenceCount, buffer, + result = SerializeAdapter::deSerialize(&sourceSequenceCount, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = AutoSerializeAdapter::deSerialize(&serviceType, buffer, size, + result = SerializeAdapter::deSerialize(&serviceType, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = AutoSerializeAdapter::deSerialize(&serviceSubtype, buffer, + result = SerializeAdapter::deSerialize(&serviceSubtype, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = AutoSerializeAdapter::deSerialize(&subCounter, buffer, size, + result = SerializeAdapter::deSerialize(&subCounter, buffer, size, bigEndian); if (result != HasReturnvaluesIF::RETURN_OK) { return result; diff --git a/tmtcpacket/packetmatcher/ApidMatcher.h b/tmtcpacket/packetmatcher/ApidMatcher.h index 1f194968..d5d96f2d 100644 --- a/tmtcpacket/packetmatcher/ApidMatcher.h +++ b/tmtcpacket/packetmatcher/ApidMatcher.h @@ -24,14 +24,14 @@ public: } ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, const uint32_t max_size, bool bigEndian) const { - return SerializeAdapter::serialize(&apid, buffer, size, max_size, bigEndian); + return SerializeAdapter::serialize(&apid, buffer, size, max_size, bigEndian); } uint32_t getSerializedSize() const { - return SerializeAdapter::getSerializedSize(&apid); + return SerializeAdapter::getSerializedSize(&apid); } ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, bool bigEndian) { - return SerializeAdapter::deSerialize(&apid, buffer, size, bigEndian); + return SerializeAdapter::deSerialize(&apid, buffer, size, bigEndian); } }; diff --git a/tmtcpacket/packetmatcher/ServiceMatcher.h b/tmtcpacket/packetmatcher/ServiceMatcher.h index 1a6781b4..b0623780 100644 --- a/tmtcpacket/packetmatcher/ServiceMatcher.h +++ b/tmtcpacket/packetmatcher/ServiceMatcher.h @@ -24,14 +24,14 @@ public: } ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, const uint32_t max_size, bool bigEndian) const { - return SerializeAdapter::serialize(&service, buffer, size, max_size, bigEndian); + return SerializeAdapter::serialize(&service, buffer, size, max_size, bigEndian); } uint32_t getSerializedSize() const { - return SerializeAdapter::getSerializedSize(&service); + return SerializeAdapter::getSerializedSize(&service); } ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, bool bigEndian) { - return SerializeAdapter::deSerialize(&service, buffer, size, bigEndian); + return SerializeAdapter::deSerialize(&service, buffer, size, bigEndian); } }; diff --git a/tmtcpacket/packetmatcher/SubserviceMatcher.h b/tmtcpacket/packetmatcher/SubserviceMatcher.h index 1b589b20..90370af1 100644 --- a/tmtcpacket/packetmatcher/SubserviceMatcher.h +++ b/tmtcpacket/packetmatcher/SubserviceMatcher.h @@ -22,14 +22,14 @@ public: } ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, const uint32_t max_size, bool bigEndian) const { - return SerializeAdapter::serialize(&subService, buffer, size, max_size, bigEndian); + return SerializeAdapter::serialize(&subService, buffer, size, max_size, bigEndian); } uint32_t getSerializedSize() const { - return SerializeAdapter::getSerializedSize(&subService); + return SerializeAdapter::getSerializedSize(&subService); } ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, bool bigEndian) { - return SerializeAdapter::deSerialize(&subService, buffer, size, bigEndian); + return SerializeAdapter::deSerialize(&subService, buffer, size, bigEndian); } private: uint8_t subService; diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index d70b9042..5b9e7b68 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -236,7 +236,7 @@ void CommandingServiceBase::sendTmPacket(uint8_t subservice, uint8_t buffer[sizeof(object_id_t)]; uint8_t* pBuffer = buffer; uint32_t size = 0; - SerializeAdapter::serialize(&objectId, &pBuffer, &size, + SerializeAdapter::serialize(&objectId, &pBuffer, &size, sizeof(object_id_t), true); TmPacketStored tmPacketStored(this->apid, this->service, subservice, this->tmPacketCounter, data, dataLen, buffer, size); diff --git a/tmtcservices/PusVerificationReport.cpp b/tmtcservices/PusVerificationReport.cpp index 1bc53c2a..e1dad2be 100644 --- a/tmtcservices/PusVerificationReport.cpp +++ b/tmtcservices/PusVerificationReport.cpp @@ -108,12 +108,12 @@ PusSuccessReport::PusSuccessReport(uint16_t setPacketId, uint16_t setSequenceControl, uint8_t setStep) : reportSize(0), pBuffer(reportBuffer) { //Serialization won't fail, because we know the necessary max-size of the buffer. - SerializeAdapter::serialize(&setPacketId, &pBuffer, &reportSize, + SerializeAdapter::serialize(&setPacketId, &pBuffer, &reportSize, sizeof(reportBuffer), true); - SerializeAdapter::serialize(&setSequenceControl, &pBuffer, + SerializeAdapter::serialize(&setSequenceControl, &pBuffer, &reportSize, sizeof(reportBuffer), true); if (setStep != 0) { - SerializeAdapter::serialize(&setStep, &pBuffer, &reportSize, + SerializeAdapter::serialize(&setStep, &pBuffer, &reportSize, sizeof(reportBuffer), true); } } @@ -135,19 +135,19 @@ PusFailureReport::PusFailureReport(uint16_t setPacketId, uint8_t setStep, uint32_t parameter1, uint32_t parameter2) : reportSize(0), pBuffer(reportBuffer) { //Serialization won't fail, because we know the necessary max-size of the buffer. - SerializeAdapter::serialize(&setPacketId, &pBuffer, &reportSize, + SerializeAdapter::serialize(&setPacketId, &pBuffer, &reportSize, sizeof(reportBuffer), true); - SerializeAdapter::serialize(&setSequenceControl, &pBuffer, + SerializeAdapter::serialize(&setSequenceControl, &pBuffer, &reportSize, sizeof(reportBuffer), true); if (setStep != 0) { - SerializeAdapter::serialize(&setStep, &pBuffer, &reportSize, + SerializeAdapter::serialize(&setStep, &pBuffer, &reportSize, sizeof(reportBuffer), true); } - SerializeAdapter::serialize(&setErrorCode, &pBuffer, + SerializeAdapter::serialize(&setErrorCode, &pBuffer, &reportSize, sizeof(reportBuffer), true); - SerializeAdapter::serialize(¶meter1, &pBuffer, &reportSize, + SerializeAdapter::serialize(¶meter1, &pBuffer, &reportSize, sizeof(reportBuffer), true); - SerializeAdapter::serialize(¶meter2, &pBuffer, &reportSize, + SerializeAdapter::serialize(¶meter2, &pBuffer, &reportSize, sizeof(reportBuffer), true); } From cf3190a90445d6b0f93986b40e22036e3fde4d92 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Tue, 21 Apr 2020 22:28:43 +0200 Subject: [PATCH 036/653] Actually, not that horrible, thanks to sed --- action/ActionHelper.cpp | 6 +- action/CommandActionHelper.cpp | 39 ++++--- container/FixedMap.h | 22 ++-- container/IndexedRingMemoryArray.h | 60 +++++------ datapool/DataPool.cpp | 4 +- datapool/DataPoolAdmin.cpp | 6 +- datapool/DataPoolParameterWrapper.cpp | 20 ++-- datapool/DataPoolParameterWrapper.h | 10 +- datapool/DataSet.cpp | 18 ++-- datapool/DataSet.h | 10 +- datapool/PoolRawAccess.cpp | 6 +- datapool/PoolRawAccess.h | 6 +- datapool/PoolVariable.h | 6 +- datapool/PoolVector.h | 14 +-- devicehandlers/DeviceTmReportingWrapper.cpp | 18 ++-- devicehandlers/DeviceTmReportingWrapper.h | 10 +- events/eventmatching/EventRangeMatcherBase.h | 14 +-- globalfunctions/Type.cpp | 22 ++-- globalfunctions/conversion.cpp | 104 ------------------- globalfunctions/conversion.h | 24 ----- globalfunctions/matching/MatchTree.h | 20 ++-- globalfunctions/matching/RangeMatcher.h | 10 +- health/HealthTable.cpp | 10 +- health/HealthTable.h | 2 +- monitoring/LimitViolationReporter.cpp | 6 +- osal/rtems/CpuUsage.cpp | 36 +++---- osal/rtems/CpuUsage.h | 20 ++-- parameters/ParameterHelper.cpp | 6 +- parameters/ParameterWrapper.cpp | 92 ++++++++-------- parameters/ParameterWrapper.h | 22 ++-- power/Fuse.cpp | 14 +-- power/Fuse.h | 27 ++--- power/PowerComponent.cpp | 20 ++-- power/PowerComponent.h | 10 +- serialize/SerialArrayListAdapter.h | 30 +++--- serialize/SerialBufferAdapter.cpp | 12 +-- serialize/SerialBufferAdapter.h | 10 +- serialize/SerialFixedArrayListAdapter.h | 14 +-- serialize/SerializeElement.h | 2 +- serialize/SerializeIF.h | 2 +- subsystem/Subsystem.cpp | 39 ++++--- subsystem/modes/ModeDefinitions.h | 26 ++--- thermal/ThermalComponent.cpp | 10 +- tmstorage/TmStorePackets.h | 52 +++++----- tmtcpacket/packetmatcher/ApidMatcher.h | 14 +-- tmtcpacket/packetmatcher/ServiceMatcher.h | 14 +-- tmtcpacket/packetmatcher/SubserviceMatcher.h | 14 +-- tmtcpacket/pus/TmPacketStored.cpp | 33 +++--- tmtcservices/CommandingServiceBase.cpp | 4 +- tmtcservices/PusVerificationReport.cpp | 28 ++--- tmtcservices/PusVerificationReport.h | 6 +- 51 files changed, 458 insertions(+), 566 deletions(-) delete mode 100644 globalfunctions/conversion.cpp delete mode 100644 globalfunctions/conversion.h diff --git a/action/ActionHelper.cpp b/action/ActionHelper.cpp index 9c1475f1..f93afaa8 100644 --- a/action/ActionHelper.cpp +++ b/action/ActionHelper.cpp @@ -71,18 +71,18 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t rep CommandMessage reply; store_address_t storeAddress; uint8_t *dataPtr; - uint32_t maxSize = data->getSerializedSize(); + size_t maxSize = data->getSerializedSize(); if (maxSize == 0) { //No error, there's simply nothing to report. return HasReturnvaluesIF::RETURN_OK; } - uint32_t size = 0; + size_t size = 0; ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize, &dataPtr); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = data->serialize(&dataPtr, &size, maxSize, true); + result = data->serialize(&dataPtr, &size, maxSize, SerializeIF::Endianness::BIG); if (result != HasReturnvaluesIF::RETURN_OK) { ipcStore->deleteData(storeAddress); return result; diff --git a/action/CommandActionHelper.cpp b/action/CommandActionHelper.cpp index 05eb9346..6a26453c 100644 --- a/action/CommandActionHelper.cpp +++ b/action/CommandActionHelper.cpp @@ -4,30 +4,31 @@ #include #include -CommandActionHelper::CommandActionHelper(CommandsActionsIF* setOwner) : +CommandActionHelper::CommandActionHelper(CommandsActionsIF *setOwner) : owner(setOwner), queueToUse(NULL), ipcStore( - NULL), commandCount(0), lastTarget(0) { + NULL), commandCount(0), lastTarget(0) { } CommandActionHelper::~CommandActionHelper() { } ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo, - ActionId_t actionId, SerializeIF* data) { - HasActionsIF* receiver = objectManager->get(commandTo); + ActionId_t actionId, SerializeIF *data) { + HasActionsIF *receiver = objectManager->get(commandTo); if (receiver == NULL) { return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS; } store_address_t storeId; - uint8_t* storePointer; - uint32_t maxSize = data->getSerializedSize(); + uint8_t *storePointer; + size_t maxSize = data->getSerializedSize(); ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize, &storePointer); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - uint32_t size = 0; - result = data->serialize(&storePointer, &size, maxSize, true); + size_t size = 0; + result = data->serialize(&storePointer, &size, maxSize, + SerializeIF::Endianness::BIG); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -35,11 +36,11 @@ ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo, } ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo, - ActionId_t actionId, const uint8_t* data, uint32_t size) { + ActionId_t actionId, const uint8_t *data, uint32_t size) { // if (commandCount != 0) { // return CommandsFunctionsIF::ALREADY_COMMANDING; // } - HasActionsIF* receiver = objectManager->get(commandTo); + HasActionsIF *receiver = objectManager->get(commandTo); if (receiver == NULL) { return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS; } @@ -71,13 +72,13 @@ ReturnValue_t CommandActionHelper::initialize() { } queueToUse = owner->getCommandQueuePtr(); - if(queueToUse == NULL){ + if (queueToUse == NULL) { return HasReturnvaluesIF::RETURN_FAILED; } return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t CommandActionHelper::handleReply(CommandMessage* reply) { +ReturnValue_t CommandActionHelper::handleReply(CommandMessage *reply) { if (reply->getSender() != lastTarget) { return HasReturnvaluesIF::RETURN_FAILED; } @@ -88,7 +89,8 @@ ReturnValue_t CommandActionHelper::handleReply(CommandMessage* reply) { return HasReturnvaluesIF::RETURN_OK; case ActionMessage::COMPLETION_FAILED: commandCount--; - owner->completionFailedReceived(ActionMessage::getActionId(reply), ActionMessage::getReturnCode(reply)); + owner->completionFailedReceived(ActionMessage::getActionId(reply), + ActionMessage::getReturnCode(reply)); return HasReturnvaluesIF::RETURN_OK; case ActionMessage::STEP_SUCCESS: owner->stepSuccessfulReceived(ActionMessage::getActionId(reply), @@ -96,11 +98,13 @@ ReturnValue_t CommandActionHelper::handleReply(CommandMessage* reply) { return HasReturnvaluesIF::RETURN_OK; case ActionMessage::STEP_FAILED: commandCount--; - owner->stepFailedReceived(ActionMessage::getActionId(reply), ActionMessage::getStep(reply), + owner->stepFailedReceived(ActionMessage::getActionId(reply), + ActionMessage::getStep(reply), ActionMessage::getReturnCode(reply)); return HasReturnvaluesIF::RETURN_OK; case ActionMessage::DATA_REPLY: - extractDataForOwner(ActionMessage::getActionId(reply), ActionMessage::getStoreId(reply)); + extractDataForOwner(ActionMessage::getActionId(reply), + ActionMessage::getStoreId(reply)); return HasReturnvaluesIF::RETURN_OK; default: return HasReturnvaluesIF::RETURN_FAILED; @@ -111,8 +115,9 @@ uint8_t CommandActionHelper::getCommandCount() const { return commandCount; } -void CommandActionHelper::extractDataForOwner(ActionId_t actionId, store_address_t storeId) { - const uint8_t * data = NULL; +void CommandActionHelper::extractDataForOwner(ActionId_t actionId, + store_address_t storeId) { + const uint8_t *data = NULL; uint32_t size = 0; ReturnValue_t result = ipcStore->getData(storeId, &data, &size); if (result != HasReturnvaluesIF::RETURN_OK) { diff --git a/container/FixedMap.h b/container/FixedMap.h index eaf8a24c..ac170bd2 100644 --- a/container/FixedMap.h +++ b/container/FixedMap.h @@ -148,22 +148,22 @@ public: return theMap.maxSize(); } - virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { ReturnValue_t result = SerializeAdapter::serialize(&this->_size, - buffer, size, max_size, bigEndian); + buffer, size, maxSize, streamEndianness); uint32_t i = 0; while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) { result = SerializeAdapter::serialize(&theMap[i].first, buffer, - size, max_size, bigEndian); + size, maxSize, streamEndianness); result = SerializeAdapter::serialize(&theMap[i].second, buffer, size, - max_size, bigEndian); + maxSize, streamEndianness); ++i; } return result; } - virtual uint32_t getSerializedSize() const { + virtual size_t getSerializedSize() const { uint32_t printSize = sizeof(_size); uint32_t i = 0; @@ -176,19 +176,19 @@ public: return printSize; } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) { ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size, - buffer, size, bigEndian); + buffer, size, streamEndianness); if (this->_size > theMap.maxSize()) { return SerializeIF::TOO_MANY_ELEMENTS; } uint32_t i = 0; while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) { result = SerializeAdapter::deSerialize(&theMap[i].first, buffer, - size, bigEndian); + size, streamEndianness); result = SerializeAdapter::deSerialize(&theMap[i].second, buffer, size, - bigEndian); + streamEndianness); ++i; } return result; diff --git a/container/IndexedRingMemoryArray.h b/container/IndexedRingMemoryArray.h index 32b61c2d..6e7f330c 100644 --- a/container/IndexedRingMemoryArray.h +++ b/container/IndexedRingMemoryArray.h @@ -68,46 +68,46 @@ public: return this->storedPackets; } - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { - ReturnValue_t result = SerializeAdapter::serialize(&blockStartAddress,buffer,size,max_size,bigEndian); + ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { + ReturnValue_t result = SerializeAdapter::serialize(&blockStartAddress,buffer,size,maxSize,streamEndianness); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } - result = indexType.serialize(buffer,size,max_size,bigEndian); + result = indexType.serialize(buffer,size,maxSize,streamEndianness); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } - result = SerializeAdapter::serialize(&this->size,buffer,size,max_size,bigEndian); + result = SerializeAdapter::serialize(&this->size,buffer,size,maxSize,streamEndianness); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } - result = SerializeAdapter::serialize(&this->storedPackets,buffer,size,max_size,bigEndian); + result = SerializeAdapter::serialize(&this->storedPackets,buffer,size,maxSize,streamEndianness); return result; } - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian){ - ReturnValue_t result = SerializeAdapter::deSerialize(&blockStartAddress,buffer,size,bigEndian); + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness){ + ReturnValue_t result = SerializeAdapter::deSerialize(&blockStartAddress,buffer,size,streamEndianness); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } - result = indexType.deSerialize(buffer,size,bigEndian); + result = indexType.deSerialize(buffer,size,streamEndianness); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } - result = SerializeAdapter::deSerialize(&this->size,buffer,size,bigEndian); + result = SerializeAdapter::deSerialize(&this->size,buffer,size,streamEndianness); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } - result = SerializeAdapter::deSerialize(&this->storedPackets,buffer,size,bigEndian); + result = SerializeAdapter::deSerialize(&this->storedPackets,buffer,size,streamEndianness); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } return result; } - uint32_t getSerializedSize() const { + size_t getSerializedSize() const { uint32_t size = SerializeAdapter::getSerializedSize(&blockStartAddress); size += indexType.getSerializedSize(); size += SerializeAdapter::getSerializedSize(&this->size); @@ -485,22 +485,22 @@ public: * Parameters according to HasSerializeIF * @param buffer * @param size - * @param max_size - * @param bigEndian + * @param maxSize + * @param streamEndianness * @return */ - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const{ + ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const{ uint8_t* crcBuffer = *buffer; uint32_t oldSize = *size; if(additionalInfo!=NULL){ - additionalInfo->serialize(buffer,size,max_size,bigEndian); + additionalInfo->serialize(buffer,size,maxSize,streamEndianness); } - ReturnValue_t result = currentWriteBlock->serialize(buffer,size,max_size,bigEndian); + ReturnValue_t result = currentWriteBlock->serialize(buffer,size,maxSize,streamEndianness); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } - result = SerializeAdapter::serialize(&this->size,buffer,size,max_size,bigEndian); + result = SerializeAdapter::serialize(&this->size,buffer,size,maxSize,streamEndianness); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } @@ -508,14 +508,14 @@ public: uint32_t i = 0; while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->size)) { result = SerializeAdapter::serialize(&this->entries[i], buffer, size, - max_size, bigEndian); + maxSize, streamEndianness); ++i; } if(result != HasReturnvaluesIF::RETURN_OK){ return result; } uint16_t crc = Calculate_CRC(crcBuffer,(*size-oldSize)); - result = SerializeAdapter::serialize(&crc,buffer,size,max_size,bigEndian); + result = SerializeAdapter::serialize(&crc,buffer,size,maxSize,streamEndianness); return result; } @@ -524,7 +524,7 @@ public: * Get the serialized Size of the index * @return The serialized size of the index */ - uint32_t getSerializedSize() const { + size_t getSerializedSize() const { uint32_t size = 0; if(additionalInfo!=NULL){ @@ -542,28 +542,28 @@ public: * CRC Has to be checked before! * @param buffer * @param size - * @param bigEndian + * @param streamEndianness * @return */ - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian){ + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness){ ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; if(additionalInfo!=NULL){ - result = additionalInfo->deSerialize(buffer,size,bigEndian); + result = additionalInfo->deSerialize(buffer,size,streamEndianness); } if(result != HasReturnvaluesIF::RETURN_OK){ return result; } Index tempIndex; - result = tempIndex.deSerialize(buffer,size,bigEndian); + result = tempIndex.deSerialize(buffer,size,streamEndianness); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } uint32_t tempSize = 0; - result = SerializeAdapter::deSerialize(&tempSize,buffer,size,bigEndian); + result = SerializeAdapter::deSerialize(&tempSize,buffer,size,streamEndianness); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } @@ -574,7 +574,7 @@ public: while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->size)) { result = SerializeAdapter::deSerialize( &this->entries[i], buffer, size, - bigEndian); + streamEndianness); ++i; } if(result != HasReturnvaluesIF::RETURN_OK){ diff --git a/datapool/DataPool.cpp b/datapool/DataPool.cpp index 89543d77..6604dc23 100644 --- a/datapool/DataPool.cpp +++ b/datapool/DataPool.cpp @@ -39,10 +39,10 @@ PoolEntryIF* DataPool::getRawData( uint32_t data_pool_id ) { } } -//uint8_t DataPool::getRawData( uint32_t data_pool_id, uint8_t* address, uint16_t* size, uint32_t max_size ) { +//uint8_t DataPool::getRawData( uint32_t data_pool_id, uint8_t* address, uint16_t* size, uint32_t maxSize ) { // std::map::iterator it = this->data_pool.find( data_pool_id ); // if ( it != this->data_pool.end() ) { -// if ( it->second->getByteSize() <= max_size ) { +// if ( it->second->getByteSize() <= maxSize ) { // *size = it->second->getByteSize(); // memcpy( address, it->second->getRawData(), *size ); // return DP_SUCCESSFUL; diff --git a/datapool/DataPoolAdmin.cpp b/datapool/DataPoolAdmin.cpp index fe6b9215..8bf7f6b3 100644 --- a/datapool/DataPoolAdmin.cpp +++ b/datapool/DataPoolAdmin.cpp @@ -261,7 +261,7 @@ ReturnValue_t DataPoolAdmin::handleParameterCommand(CommandMessage* command) { //identical to ParameterHelper::sendParameter() ReturnValue_t DataPoolAdmin::sendParameter(MessageQueueId_t to, uint32_t id, const DataPoolParameterWrapper* wrapper) { - uint32_t serializedSize = wrapper->getSerializedSize(); + size_t serializedSize = wrapper->getSerializedSize(); uint8_t *storeElement; store_address_t address; @@ -272,10 +272,10 @@ ReturnValue_t DataPoolAdmin::sendParameter(MessageQueueId_t to, uint32_t id, return result; } - uint32_t storeElementSize = 0; + size_t storeElementSize = 0; result = wrapper->serialize(&storeElement, &storeElementSize, - serializedSize, true); + serializedSize, SerializeIF::Endianness::BIG); if (result != HasReturnvaluesIF::RETURN_OK) { storage->deleteData(address); diff --git a/datapool/DataPoolParameterWrapper.cpp b/datapool/DataPoolParameterWrapper.cpp index 10fb5392..e08eba5b 100644 --- a/datapool/DataPoolParameterWrapper.cpp +++ b/datapool/DataPoolParameterWrapper.cpp @@ -36,22 +36,22 @@ ReturnValue_t DataPoolParameterWrapper::set(uint8_t domainId, } ReturnValue_t DataPoolParameterWrapper::serialize(uint8_t** buffer, - uint32_t* size, const uint32_t max_size, bool bigEndian) const { + size_t* size, size_t maxSize, Endianness streamEndianness) const { ReturnValue_t result; - result = SerializeAdapter::serialize(&type, buffer, size, max_size, - bigEndian); + result = SerializeAdapter::serialize(&type, buffer, size, maxSize, + streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } result = SerializeAdapter::serialize(&columns, buffer, size, - max_size, bigEndian); + maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::serialize(&rows, buffer, size, max_size, - bigEndian); + result = SerializeAdapter::serialize(&rows, buffer, size, maxSize, + streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -60,7 +60,7 @@ ReturnValue_t DataPoolParameterWrapper::serialize(uint8_t** buffer, DataSet mySet; PoolRawAccess raw(poolId, index, &mySet,PoolVariableIF::VAR_READ); mySet.read(); - result = raw.serialize(buffer,size,max_size,bigEndian); + result = raw.serialize(buffer,size,maxSize,streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK){ return result; } @@ -69,8 +69,8 @@ ReturnValue_t DataPoolParameterWrapper::serialize(uint8_t** buffer, } //same as ParameterWrapper -uint32_t DataPoolParameterWrapper::getSerializedSize() const { - uint32_t serializedSize = 0; +size_t DataPoolParameterWrapper::getSerializedSize() const { + size_t serializedSize = 0; serializedSize += type.getSerializedSize(); serializedSize += sizeof(rows); serializedSize += sizeof(columns); @@ -80,7 +80,7 @@ uint32_t DataPoolParameterWrapper::getSerializedSize() const { } ReturnValue_t DataPoolParameterWrapper::deSerialize(const uint8_t** buffer, - int32_t* size, bool bigEndian) { + size_t* size, Endianness streamEndianness) { return HasReturnvaluesIF::RETURN_FAILED; } diff --git a/datapool/DataPoolParameterWrapper.h b/datapool/DataPoolParameterWrapper.h index faadf659..a3dbdc04 100644 --- a/datapool/DataPoolParameterWrapper.h +++ b/datapool/DataPoolParameterWrapper.h @@ -11,13 +11,13 @@ public: 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 ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const override; - virtual uint32_t getSerializedSize() const; + virtual size_t getSerializedSize() const override; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian); + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; ReturnValue_t copyFrom(const ParameterWrapper *from, uint16_t startWritingAtIndex); diff --git a/datapool/DataSet.cpp b/datapool/DataSet.cpp index b4725c73..94cdcf0c 100644 --- a/datapool/DataSet.cpp +++ b/datapool/DataSet.cpp @@ -106,12 +106,12 @@ uint8_t DataSet::lockDataPool() { return ::dataPool.lockDataPool(); } -ReturnValue_t DataSet::serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { +ReturnValue_t DataSet::serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { ReturnValue_t result = RETURN_FAILED; for (uint16_t count = 0; count < fill_count; count++) { - result = registeredVariables[count]->serialize(buffer, size, max_size, - bigEndian); + result = registeredVariables[count]->serialize(buffer, size, maxSize, + streamEndianness); if (result != RETURN_OK) { return result; } @@ -119,8 +119,8 @@ ReturnValue_t DataSet::serialize(uint8_t** buffer, uint32_t* size, return result; } -uint32_t DataSet::getSerializedSize() const { - uint32_t size = 0; +size_t DataSet::getSerializedSize() const { + size_t size = 0; for (uint16_t count = 0; count < fill_count; count++) { size += registeredVariables[count]->getSerializedSize(); } @@ -136,12 +136,12 @@ void DataSet::setValid(uint8_t valid) { } } -ReturnValue_t DataSet::deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { +ReturnValue_t DataSet::deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) { ReturnValue_t result = RETURN_FAILED; for (uint16_t count = 0; count < fill_count; count++) { result = registeredVariables[count]->deSerialize(buffer, size, - bigEndian); + streamEndianness); if (result != RETURN_OK) { return result; } diff --git a/datapool/DataSet.h b/datapool/DataSet.h index 982be692..3d211537 100644 --- a/datapool/DataSet.h +++ b/datapool/DataSet.h @@ -146,13 +146,13 @@ public: */ void setValid(uint8_t valid); - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const; + ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const override; - uint32_t getSerializedSize() const; + size_t getSerializedSize() const override; - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian); + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; }; diff --git a/datapool/PoolRawAccess.cpp b/datapool/PoolRawAccess.cpp index 2053498b..94766d87 100644 --- a/datapool/PoolRawAccess.cpp +++ b/datapool/PoolRawAccess.cpp @@ -69,12 +69,12 @@ uint8_t* PoolRawAccess::getEntry() { } ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer, - uint32_t* writtenBytes, uint32_t max_size) { + uint32_t* writtenBytes, uint32_t maxSize) { uint8_t* data_ptr = getEntry(); // debug << "PoolRawAccess::getEntry: Array position: " << index * size_of_type << " Size of T: " << (int)size_of_type << " ByteSize: " << byte_size << " Position: " << *size << std::endl; if (typeSize == 0) return DATA_POOL_ACCESS_FAILED; - if (typeSize > max_size) + if (typeSize > maxSize) return INCORRECT_SIZE; #ifndef BYTE_ORDER_SYSTEM #error BYTE_ORDER_SYSTEM not defined @@ -149,7 +149,7 @@ ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, size_t* size, size_t maxSize, Endianness streamEndianness) const { //TODO integer overflow if (typeSize + *size <= maxSize) { -#error use endian swapper +#warning use endian swapper if (1) { #ifndef BYTE_ORDER_SYSTEM #error BYTE_ORDER_SYSTEM not defined diff --git a/datapool/PoolRawAccess.h b/datapool/PoolRawAccess.h index 190c38a9..8cc8f3f0 100644 --- a/datapool/PoolRawAccess.h +++ b/datapool/PoolRawAccess.h @@ -90,15 +90,15 @@ public: * \details It makes use of the getEntry call of this function, but additionally flips the * bytes to big endian, which is the default for external communication (as House- * keeping telemetry). To achieve this, the data is copied directly to the passed - * buffer, if it fits in the given max_size. + * buffer, if it fits in the given maxSize. * \param buffer A pointer to a buffer to write to * \param writtenBytes The number of bytes written is returned with this value. - * \param max_size The maximum size that the function may write to buffer. + * \param maxSize The maximum size that the function may write to buffer. * \return - \c RETURN_OK if entry could be acquired * - \c RETURN_FAILED else. */ ReturnValue_t getEntryEndianSafe(uint8_t *buffer, uint32_t *size, - uint32_t max_size); + uint32_t maxSize); /** * With this method, the content can be set from a big endian buffer safely. * @param buffer Pointer to the data to set diff --git a/datapool/PoolVariable.h b/datapool/PoolVariable.h index ce073426..c1a57539 100644 --- a/datapool/PoolVariable.h +++ b/datapool/PoolVariable.h @@ -195,12 +195,12 @@ public: } virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, - size_t max_size, Endianness streamEndianness) const override { - return SerializeAdapter::serialize(&value, buffer, size, max_size, + size_t maxSize, Endianness streamEndianness) const override { + return SerializeAdapter::serialize(&value, buffer, size, maxSize, streamEndianness); } - virtual uint32_t getSerializedSize() const override { + virtual size_t getSerializedSize() const override { return SerializeAdapter::getSerializedSize(&value); } diff --git a/datapool/PoolVector.h b/datapool/PoolVector.h index 3809f93b..50724054 100644 --- a/datapool/PoolVector.h +++ b/datapool/PoolVector.h @@ -197,13 +197,13 @@ public: return *this; } - virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { uint16_t i; ReturnValue_t result; for (i = 0; i < vector_size; i++) { result = SerializeAdapter::serialize(&(value[i]), buffer, size, - max_size, bigEndian); + maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -211,17 +211,17 @@ public: return result; } - virtual uint32_t getSerializedSize() const { + virtual size_t getSerializedSize() const { return vector_size * SerializeAdapter::getSerializedSize(value); } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) { uint16_t i; ReturnValue_t result; for (i = 0; i < vector_size; i++) { result = SerializeAdapter::deSerialize(&(value[i]), buffer, size, - bigEndian); + streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } diff --git a/devicehandlers/DeviceTmReportingWrapper.cpp b/devicehandlers/DeviceTmReportingWrapper.cpp index 55861c3c..ce5eb109 100644 --- a/devicehandlers/DeviceTmReportingWrapper.cpp +++ b/devicehandlers/DeviceTmReportingWrapper.cpp @@ -12,35 +12,35 @@ DeviceTmReportingWrapper::~DeviceTmReportingWrapper() { } ReturnValue_t DeviceTmReportingWrapper::serialize(uint8_t** buffer, - uint32_t* size, const uint32_t max_size, bool bigEndian) const { + size_t* size, size_t maxSize, Endianness streamEndianness) const { ReturnValue_t result = SerializeAdapter::serialize(&objectId, - buffer, size, max_size, bigEndian); + buffer, size, maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } result = SerializeAdapter::serialize(&actionId, buffer, - size, max_size, bigEndian); + size, maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - return data->serialize(buffer, size, max_size, bigEndian); + return data->serialize(buffer, size, maxSize, streamEndianness); } -uint32_t DeviceTmReportingWrapper::getSerializedSize() const { +size_t DeviceTmReportingWrapper::getSerializedSize() const { return sizeof(objectId) + sizeof(ActionId_t) + data->getSerializedSize(); } ReturnValue_t DeviceTmReportingWrapper::deSerialize(const uint8_t** buffer, - int32_t* size, bool bigEndian) { + size_t* size, Endianness streamEndianness) { ReturnValue_t result = SerializeAdapter::deSerialize(&objectId, - buffer, size, bigEndian); + buffer, size, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } result = SerializeAdapter::deSerialize(&actionId, buffer, - size, bigEndian); + size, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - return data->deSerialize(buffer, size, bigEndian); + return data->deSerialize(buffer, size, streamEndianness); } diff --git a/devicehandlers/DeviceTmReportingWrapper.h b/devicehandlers/DeviceTmReportingWrapper.h index 1cd9470d..4432b7f1 100644 --- a/devicehandlers/DeviceTmReportingWrapper.h +++ b/devicehandlers/DeviceTmReportingWrapper.h @@ -11,13 +11,13 @@ public: SerializeIF *data); virtual ~DeviceTmReportingWrapper(); - virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const; + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const override; - virtual uint32_t getSerializedSize() const; + virtual size_t getSerializedSize() const override; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian); + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; private: object_id_t objectId; ActionId_t actionId; diff --git a/events/eventmatching/EventRangeMatcherBase.h b/events/eventmatching/EventRangeMatcherBase.h index 921a5d6a..587669ba 100644 --- a/events/eventmatching/EventRangeMatcherBase.h +++ b/events/eventmatching/EventRangeMatcherBase.h @@ -11,16 +11,16 @@ class EventRangeMatcherBase: public SerializeableMatcherIF { public: EventRangeMatcherBase(T from, T till, bool inverted) : rangeMatcher(from, till, inverted) { } virtual ~EventRangeMatcherBase() { } - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { - return rangeMatcher.serialize(buffer, size, max_size, bigEndian); + ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { + return rangeMatcher.serialize(buffer, size, maxSize, streamEndianness); } - uint32_t getSerializedSize() const { + size_t getSerializedSize() const { return rangeMatcher.getSerializedSize(); } - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { - return rangeMatcher.deSerialize(buffer, size, bigEndian); + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) { + return rangeMatcher.deSerialize(buffer, size, streamEndianness); } protected: RangeMatcher rangeMatcher; diff --git a/globalfunctions/Type.cpp b/globalfunctions/Type.cpp index b7b7fd82..a481f768 100644 --- a/globalfunctions/Type.cpp +++ b/globalfunctions/Type.cpp @@ -59,8 +59,8 @@ uint8_t Type::getSize() const { } } -ReturnValue_t Type::serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { +ReturnValue_t Type::serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { uint8_t ptc; uint8_t pfc; ReturnValue_t result = getPtcPfc(&ptc, &pfc); @@ -68,36 +68,36 @@ ReturnValue_t Type::serialize(uint8_t** buffer, uint32_t* size, return result; } - result = SerializeAdapter::serialize(&ptc, buffer, size, max_size, - bigEndian); + result = SerializeAdapter::serialize(&ptc, buffer, size, maxSize, + streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::serialize(&pfc, buffer, size, max_size, - bigEndian); + result = SerializeAdapter::serialize(&pfc, buffer, size, maxSize, + streamEndianness); return result; } -uint32_t Type::getSerializedSize() const { +size_t Type::getSerializedSize() const { uint8_t dontcare = 0; return 2 * SerializeAdapter::getSerializedSize(&dontcare); } -ReturnValue_t Type::deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { +ReturnValue_t Type::deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) { uint8_t ptc; uint8_t pfc; ReturnValue_t result = SerializeAdapter::deSerialize(&ptc, buffer, - size, bigEndian); + size, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } result = SerializeAdapter::deSerialize(&pfc, buffer, size, - bigEndian); + streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } diff --git a/globalfunctions/conversion.cpp b/globalfunctions/conversion.cpp deleted file mode 100644 index d4f542bd..00000000 --- a/globalfunctions/conversion.cpp +++ /dev/null @@ -1,104 +0,0 @@ -#include -#include -#include - - - -//SHOULDDO: This shall be optimized (later)! -void convertToByteStream( uint16_t value, uint8_t* buffer, uint32_t* size ) { - buffer[0] = (value & 0xFF00) >> 8; - buffer[1] = (value & 0x00FF); - *size += 2; -} - -void convertToByteStream( uint32_t value, uint8_t* buffer, uint32_t* size ) { - buffer[0] = (value & 0xFF000000) >> 24; - buffer[1] = (value & 0x00FF0000) >> 16; - buffer[2] = (value & 0x0000FF00) >> 8; - buffer[3] = (value & 0x000000FF); - *size +=4; -} - -void convertToByteStream( int16_t value, uint8_t* buffer, uint32_t* size ) { - buffer[0] = (value & 0xFF00) >> 8; - buffer[1] = (value & 0x00FF); - *size += 2; -} - -void convertToByteStream( int32_t value, uint8_t* buffer, uint32_t* size ) { - buffer[0] = (value & 0xFF000000) >> 24; - buffer[1] = (value & 0x00FF0000) >> 16; - buffer[2] = (value & 0x0000FF00) >> 8; - buffer[3] = (value & 0x000000FF); - *size += 4; -} - -//void convertToByteStream( uint64_t value, uint8_t* buffer, uint32_t* size ) { -// buffer[0] = (value & 0xFF00000000000000) >> 56; -// buffer[1] = (value & 0x00FF000000000000) >> 48; -// buffer[2] = (value & 0x0000FF0000000000) >> 40; -// buffer[3] = (value & 0x000000FF00000000) >> 32; -// buffer[4] = (value & 0x00000000FF000000) >> 24; -// buffer[5] = (value & 0x0000000000FF0000) >> 16; -// buffer[6] = (value & 0x000000000000FF00) >> 8; -// buffer[7] = (value & 0x00000000000000FF); -// *size+=8; -//} -// -//void convertToByteStream( int64_t value, uint8_t* buffer, uint32_t* size ) { -// buffer[0] = (value & 0xFF00000000000000) >> 56; -// buffer[1] = (value & 0x00FF000000000000) >> 48; -// buffer[2] = (value & 0x0000FF0000000000) >> 40; -// buffer[3] = (value & 0x000000FF00000000) >> 32; -// buffer[4] = (value & 0x00000000FF000000) >> 24; -// buffer[5] = (value & 0x0000000000FF0000) >> 16; -// buffer[6] = (value & 0x000000000000FF00) >> 8; -// buffer[7] = (value & 0x00000000000000FF); -// *size+=8; -//} - -void convertToByteStream( float in_value, uint8_t* buffer, uint32_t* size ) { -#ifndef BYTE_ORDER_SYSTEM - #error BYTE_ORDER_SYSTEM not defined -#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN - union float_union { - float value; - uint8_t chars[4]; - }; - float_union temp; - temp.value = in_value; - buffer[0] = temp.chars[3]; - buffer[1] = temp.chars[2]; - buffer[2] = temp.chars[1]; - buffer[3] = temp.chars[0]; - *size += 4; -#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN - memcpy(buffer, &in_value, sizeof(in_value)); - *size += sizeof(in_value); -#endif -} - -void convertToByteStream( double in_value, uint8_t* buffer, uint32_t* size ) { -#ifndef BYTE_ORDER_SYSTEM - #error BYTE_ORDER_SYSTEM not defined -#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN - union double_union { - double value; - uint8_t chars[8]; - }; - double_union temp; - temp.value = in_value; - buffer[0] = temp.chars[7]; - buffer[1] = temp.chars[6]; - buffer[2] = temp.chars[5]; - buffer[3] = temp.chars[4]; - buffer[4] = temp.chars[3]; - buffer[5] = temp.chars[2]; - buffer[6] = temp.chars[1]; - buffer[7] = temp.chars[0]; - *size += 8; -#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN - memcpy(buffer, &in_value, sizeof(in_value)); - *size += sizeof(in_value); -#endif -} diff --git a/globalfunctions/conversion.h b/globalfunctions/conversion.h deleted file mode 100644 index 0d1ca1a6..00000000 --- a/globalfunctions/conversion.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef CONVERSION_H_ -#define CONVERSION_H_ - - -#include - - -void convertToByteStream( uint16_t value, uint8_t* buffer, uint32_t* size ); - -void convertToByteStream( uint32_t value, uint8_t* buffer, uint32_t* size ); - -void convertToByteStream( int16_t value, uint8_t* buffer, uint32_t* size ); - -void convertToByteStream( int32_t value, uint8_t* buffer, uint32_t* size ); - -//void convertToByteStream( uint64_t value, uint8_t* buffer, uint32_t* size ); -// -//void convertToByteStream( int64_t value, uint8_t* buffer, uint32_t* size ); - -void convertToByteStream( float value, uint8_t* buffer, uint32_t* size ); - -void convertToByteStream( double value, uint8_t* buffer, uint32_t* size ); - -#endif /* CONVERSION_H_ */ diff --git a/globalfunctions/matching/MatchTree.h b/globalfunctions/matching/MatchTree.h index 0ee3890b..b54f5492 100644 --- a/globalfunctions/matching/MatchTree.h +++ b/globalfunctions/matching/MatchTree.h @@ -45,38 +45,38 @@ public: return matchSubtree(iter, number); } - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { + ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, SerializeIF::Endianness streamEndianness) const override { iterator iter = this->begin(); uint8_t count = this->countRight(iter); ReturnValue_t result = SerializeAdapter::serialize(&count, - buffer, size, max_size, bigEndian); + buffer, size, maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } if (iter == this->end()) { return HasReturnvaluesIF::RETURN_OK; } - result = iter->serialize(buffer, size, max_size, bigEndian); + result = iter->serialize(buffer, size, maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } if (maxDepth > 0) { MatchTree temp(iter.left(), maxDepth - 1); - result = temp.serialize(buffer, size, max_size, bigEndian); + result = temp.serialize(buffer, size, maxSize, streamEndianness); } if (result != HasReturnvaluesIF::RETURN_OK) { return result; } iter = iter.right(); while (iter != this->end()) { - result = iter->serialize(buffer, size, max_size, bigEndian); + result = iter->serialize(buffer, size, maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } if (maxDepth > 0) { MatchTree temp(iter.left(), maxDepth - 1); - result = temp.serialize(buffer, size, max_size, bigEndian); + result = temp.serialize(buffer, size, maxSize, streamEndianness); } if (result != HasReturnvaluesIF::RETURN_OK) { return result; @@ -86,7 +86,7 @@ public: return result; } - uint32_t getSerializedSize() const { + size_t getSerializedSize() const override { //Analogous to serialize! uint32_t size = 1; //One for count iterator iter = this->begin(); @@ -115,8 +115,8 @@ public: return size; } - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) override { return HasReturnvaluesIF::RETURN_OK; } diff --git a/globalfunctions/matching/RangeMatcher.h b/globalfunctions/matching/RangeMatcher.h index c30406f6..6fee1f52 100644 --- a/globalfunctions/matching/RangeMatcher.h +++ b/globalfunctions/matching/RangeMatcher.h @@ -26,23 +26,23 @@ public: } } - ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t max_size, + ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, SerializeIF::Endianness streamEndianness) const override { ReturnValue_t result = SerializeAdapter::serialize(&lowerBound, buffer, - size, max_size, streamEndianness); + size, maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } result = SerializeAdapter::serialize(&upperBound, buffer, size, - max_size, streamEndianness); + maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - return SerializeAdapter::serialize(&inverted, buffer, size, max_size, + return SerializeAdapter::serialize(&inverted, buffer, size, maxSize, streamEndianness); } - uint32_t getSerializedSize() const override { + size_t getSerializedSize() const override { return sizeof(lowerBound) + sizeof(upperBound) + sizeof(bool); } diff --git a/health/HealthTable.cpp b/health/HealthTable.cpp index 48ee6679..bd6606db 100644 --- a/health/HealthTable.cpp +++ b/health/HealthTable.cpp @@ -63,21 +63,21 @@ bool HealthTable::hasHealth(object_id_t object) { return exits; } -void HealthTable::printAll(uint8_t* pointer, uint32_t maxSize) { +void HealthTable::printAll(uint8_t* pointer, size_t maxSize) { mutex->lockMutex(MutexIF::NO_TIMEOUT); - uint32_t size = 0; + size_t size = 0; uint16_t count = healthMap.size(); ReturnValue_t result = SerializeAdapter::serialize(&count, - &pointer, &size, maxSize, true); + &pointer, &size, maxSize, SerializeIF::Endianness::BIG); HealthMap::iterator iter; for (iter = healthMap.begin(); iter != healthMap.end() && result == HasReturnvaluesIF::RETURN_OK; ++iter) { result = SerializeAdapter::serialize(&iter->first, - &pointer, &size, maxSize, true); + &pointer, &size, maxSize, SerializeIF::Endianness::BIG); uint8_t health = iter->second; result = SerializeAdapter::serialize(&health, &pointer, &size, - maxSize, true); + maxSize, SerializeIF::Endianness::BIG); } mutex->unlockMutex(); } diff --git a/health/HealthTable.h b/health/HealthTable.h index 32a7eee2..2c74bda4 100644 --- a/health/HealthTable.h +++ b/health/HealthTable.h @@ -21,7 +21,7 @@ public: virtual HasHealthIF::HealthState getHealth(object_id_t); virtual uint32_t getPrintSize(); - virtual void printAll(uint8_t *pointer, uint32_t maxSize); + virtual void printAll(uint8_t *pointer, size_t maxSize); protected: MutexIF* mutex; diff --git a/monitoring/LimitViolationReporter.cpp b/monitoring/LimitViolationReporter.cpp index 760e8b93..489a8f9e 100644 --- a/monitoring/LimitViolationReporter.cpp +++ b/monitoring/LimitViolationReporter.cpp @@ -17,7 +17,7 @@ ReturnValue_t LimitViolationReporter::sendLimitViolationReport(const SerializeIF } store_address_t storeId; uint8_t* dataTarget = NULL; - uint32_t maxSize = data->getSerializedSize(); + size_t maxSize = data->getSerializedSize(); if (maxSize > MonitoringIF::VIOLATION_REPORT_MAX_SIZE) { return MonitoringIF::INVALID_SIZE; } @@ -26,8 +26,8 @@ ReturnValue_t LimitViolationReporter::sendLimitViolationReport(const SerializeIF if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - uint32_t size = 0; - result = data->serialize(&dataTarget, &size, maxSize, true); + size_t size = 0; + result = data->serialize(&dataTarget, &size, maxSize, SerializeIF::Endianness::BIG); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } diff --git a/osal/rtems/CpuUsage.cpp b/osal/rtems/CpuUsage.cpp index 903a4d0e..61b66c3d 100644 --- a/osal/rtems/CpuUsage.cpp +++ b/osal/rtems/CpuUsage.cpp @@ -89,15 +89,15 @@ void CpuUsage::clear() { threadData.clear(); } -ReturnValue_t CpuUsage::serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { +ReturnValue_t CpuUsage::serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { ReturnValue_t result = SerializeAdapter::serialize( - &timeSinceLastReset, buffer, size, max_size, bigEndian); + &timeSinceLastReset, buffer, size, maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } return SerialArrayListAdapter::serialize(&threadData, buffer, - size, max_size, bigEndian); + size, maxSize, streamEndianness); } uint32_t CpuUsage::getSerializedSize() const { @@ -109,37 +109,37 @@ uint32_t CpuUsage::getSerializedSize() const { return size; } -ReturnValue_t CpuUsage::deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { +ReturnValue_t CpuUsage::deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) { ReturnValue_t result = SerializeAdapter::deSerialize( - &timeSinceLastReset, buffer, size, bigEndian); + &timeSinceLastReset, buffer, size, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } return SerialArrayListAdapter::deSerialize(&threadData, buffer, - size, bigEndian); + size, streamEndianness); } -ReturnValue_t CpuUsage::ThreadData::serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { +ReturnValue_t CpuUsage::ThreadData::serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { ReturnValue_t result = SerializeAdapter::serialize(&id, buffer, - size, max_size, bigEndian); + size, maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - if (*size + MAX_LENGTH_OF_THREAD_NAME > max_size) { + if (*size + MAX_LENGTH_OF_THREAD_NAME > maxSize) { return BUFFER_TOO_SHORT; } memcpy(*buffer, name, MAX_LENGTH_OF_THREAD_NAME); *size += MAX_LENGTH_OF_THREAD_NAME; *buffer += MAX_LENGTH_OF_THREAD_NAME; result = SerializeAdapter::serialize(&timeRunning, - buffer, size, max_size, bigEndian); + buffer, size, maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } result = SerializeAdapter::serialize(&percentUsage, - buffer, size, max_size, bigEndian); + buffer, size, maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -158,9 +158,9 @@ uint32_t CpuUsage::ThreadData::getSerializedSize() const { } ReturnValue_t CpuUsage::ThreadData::deSerialize(const uint8_t** buffer, - int32_t* size, bool bigEndian) { + int32_t* size, Endianness streamEndianness) { ReturnValue_t result = SerializeAdapter::deSerialize(&id, buffer, - size, bigEndian); + size, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -170,12 +170,12 @@ ReturnValue_t CpuUsage::ThreadData::deSerialize(const uint8_t** buffer, memcpy(name, *buffer, MAX_LENGTH_OF_THREAD_NAME); *buffer -= MAX_LENGTH_OF_THREAD_NAME; result = SerializeAdapter::deSerialize(&timeRunning, - buffer, size, bigEndian); + buffer, size, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } result = SerializeAdapter::deSerialize(&percentUsage, - buffer, size, bigEndian); + buffer, size, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } diff --git a/osal/rtems/CpuUsage.h b/osal/rtems/CpuUsage.h index 3d317e4e..eb03c5e3 100644 --- a/osal/rtems/CpuUsage.h +++ b/osal/rtems/CpuUsage.h @@ -18,13 +18,13 @@ public: float timeRunning; float percentUsage; - virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const; + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const override; - virtual uint32_t getSerializedSize() const; + virtual size_t getSerializedSize() const override; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian); + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; }; CpuUsage(); @@ -41,13 +41,13 @@ public: void clear(); - virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const; + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const override; - virtual uint32_t getSerializedSize() const; + virtual size_t getSerializedSize() const override; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian); + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; }; #endif /* CPUUSAGE_H_ */ diff --git a/parameters/ParameterHelper.cpp b/parameters/ParameterHelper.cpp index 75b71a7e..725fa1d7 100644 --- a/parameters/ParameterHelper.cpp +++ b/parameters/ParameterHelper.cpp @@ -83,7 +83,7 @@ ReturnValue_t ParameterHelper::handleParameterMessage(CommandMessage *message) { ReturnValue_t ParameterHelper::sendParameter(MessageQueueId_t to, uint32_t id, const ParameterWrapper* description) { - uint32_t serializedSize = description->getSerializedSize(); + size_t serializedSize = description->getSerializedSize(); uint8_t *storeElement; store_address_t address; @@ -94,10 +94,10 @@ ReturnValue_t ParameterHelper::sendParameter(MessageQueueId_t to, uint32_t id, return result; } - uint32_t storeElementSize = 0; + size_t storeElementSize = 0; result = description->serialize(&storeElement, &storeElementSize, - serializedSize, true); + serializedSize, SerializeIF::Endianness::BIG); if (result != HasReturnvaluesIF::RETURN_OK) { storage->deleteData(address); diff --git a/parameters/ParameterWrapper.cpp b/parameters/ParameterWrapper.cpp index 9dcbc6d5..602ec361 100644 --- a/parameters/ParameterWrapper.cpp +++ b/parameters/ParameterWrapper.cpp @@ -2,41 +2,41 @@ ParameterWrapper::ParameterWrapper() : pointsToStream(false), type(Type::UNKNOWN_TYPE), rows(0), columns(0), data( - NULL), readonlyData(NULL) { + NULL), readonlyData(NULL) { } ParameterWrapper::ParameterWrapper(Type type, uint8_t rows, uint8_t columns, - void* data) : + void *data) : pointsToStream(false), type(type), rows(rows), columns(columns), data( data), readonlyData(data) { } ParameterWrapper::ParameterWrapper(Type type, uint8_t rows, uint8_t columns, - const void* data) : + const void *data) : pointsToStream(false), type(type), rows(rows), columns(columns), data( - NULL), readonlyData(data) { + NULL), readonlyData(data) { } ParameterWrapper::~ParameterWrapper() { } -ReturnValue_t ParameterWrapper::serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { +ReturnValue_t ParameterWrapper::serialize(uint8_t **buffer, size_t *size, + size_t maxSize, Endianness streamEndianness) const { ReturnValue_t result; - result = SerializeAdapter::serialize(&type, buffer, size, max_size, - bigEndian); + result = SerializeAdapter::serialize(&type, buffer, size, maxSize, + streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::serialize(&columns, buffer, size, - max_size, bigEndian); + result = SerializeAdapter::serialize(&columns, buffer, size, maxSize, + streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::serialize(&rows, buffer, size, max_size, - bigEndian); + result = SerializeAdapter::serialize(&rows, buffer, size, maxSize, + streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -47,28 +47,33 @@ ReturnValue_t ParameterWrapper::serialize(uint8_t** buffer, uint32_t* size, } switch (type) { case Type::UINT8_T: - result = serializeData(buffer, size, max_size, bigEndian); + result = serializeData(buffer, size, maxSize, + streamEndianness); break; case Type::INT8_T: - result = serializeData(buffer, size, max_size, bigEndian); + result = serializeData(buffer, size, maxSize, streamEndianness); break; case Type::UINT16_T: - result = serializeData(buffer, size, max_size, bigEndian); + result = serializeData(buffer, size, maxSize, + streamEndianness); break; case Type::INT16_T: - result = serializeData(buffer, size, max_size, bigEndian); + result = serializeData(buffer, size, maxSize, + streamEndianness); break; case Type::UINT32_T: - result = serializeData(buffer, size, max_size, bigEndian); + result = serializeData(buffer, size, maxSize, + streamEndianness); break; case Type::INT32_T: - result = serializeData(buffer, size, max_size, bigEndian); + result = serializeData(buffer, size, maxSize, + streamEndianness); break; case Type::FLOAT: - result = serializeData(buffer, size, max_size, bigEndian); + result = serializeData(buffer, size, maxSize, streamEndianness); break; case Type::DOUBLE: - result = serializeData(buffer, size, max_size, bigEndian); + result = serializeData(buffer, size, maxSize, streamEndianness); break; default: result = UNKNOW_DATATYPE; @@ -77,7 +82,7 @@ ReturnValue_t ParameterWrapper::serialize(uint8_t** buffer, uint32_t* size, return result; } -uint32_t ParameterWrapper::getSerializedSize() const { +size_t ParameterWrapper::getSerializedSize() const { uint32_t serializedSize = 0; serializedSize += type.getSerializedSize(); serializedSize += sizeof(rows); @@ -88,14 +93,14 @@ uint32_t ParameterWrapper::getSerializedSize() const { } template -ReturnValue_t ParameterWrapper::serializeData(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { +ReturnValue_t ParameterWrapper::serializeData(uint8_t **buffer, size_t *size, + size_t maxSize, Endianness streamEndianness) const { const T *element = (const T*) readonlyData; ReturnValue_t result; uint16_t dataSize = columns * rows; while (dataSize != 0) { - result = SerializeAdapter::serialize(element, buffer, size, max_size, - bigEndian); + result = SerializeAdapter::serialize(element, buffer, size, maxSize, + streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -111,21 +116,21 @@ ReturnValue_t ParameterWrapper::deSerializeData(uint8_t startingRow, uint8_t fromColumns) { //treat from as a continuous Stream as we copy all of it - const uint8_t *fromAsStream = (const uint8_t *) from; - int32_t streamSize = fromRows * fromColumns * sizeof(T); + const uint8_t *fromAsStream = (const uint8_t*) from; + size_t streamSize = fromRows * fromColumns * sizeof(T); ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; for (uint8_t fromRow = 0; fromRow < fromRows; fromRow++) { //get the start element of this row in data - T *dataWithDataType = ((T *) data) + T *dataWithDataType = ((T*) data) + (((startingRow + fromRow) * columns) + startingColumn); for (uint8_t fromColumn = 0; fromColumn < fromColumns; fromColumn++) { result = SerializeAdapter::deSerialize( dataWithDataType + fromColumn, &fromAsStream, &streamSize, - true); + SerializeIF::Endianness::BIG); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -136,13 +141,14 @@ ReturnValue_t ParameterWrapper::deSerializeData(uint8_t startingRow, } -ReturnValue_t ParameterWrapper::deSerialize(const uint8_t** buffer, - int32_t* size, bool bigEndian) { - return deSerialize(buffer, size, bigEndian, 0); +ReturnValue_t ParameterWrapper::deSerialize(const uint8_t **buffer, + size_t *size, Endianness streamEndianness) { + return deSerialize(buffer, size, streamEndianness, 0); } -ReturnValue_t ParameterWrapper::deSerialize(const uint8_t** buffer, - int32_t* size, bool bigEndian, uint16_t startWritingAtIndex) { +ReturnValue_t ParameterWrapper::deSerialize(const uint8_t **buffer, + size_t *size, Endianness streamEndianness, + uint16_t startWritingAtIndex) { ParameterWrapper streamDescription; ReturnValue_t result = streamDescription.set(*buffer, *size, buffer, size); @@ -153,26 +159,26 @@ ReturnValue_t ParameterWrapper::deSerialize(const uint8_t** buffer, return copyFrom(&streamDescription, startWritingAtIndex); } -ReturnValue_t ParameterWrapper::set(const uint8_t* stream, int32_t streamSize, - const uint8_t **remainingStream, int32_t *remainingSize) { +ReturnValue_t ParameterWrapper::set(const uint8_t *stream, size_t streamSize, + const uint8_t **remainingStream, size_t *remainingSize) { ReturnValue_t result = SerializeAdapter::deSerialize(&type, &stream, - &streamSize, true); + &streamSize, SerializeIF::Endianness::BIG); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = SerializeAdapter::deSerialize(&columns, &stream, - &streamSize, true); + result = SerializeAdapter::deSerialize(&columns, &stream, &streamSize, + SerializeIF::Endianness::BIG); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } result = SerializeAdapter::deSerialize(&rows, &stream, &streamSize, - true); + SerializeIF::Endianness::BIG); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - int32_t dataSize = type.getSize() * rows * columns; + size_t dataSize = type.getSize() * rows * columns; if (streamSize < dataSize) { return SerializeIF::STREAM_TOO_SHORT; @@ -194,7 +200,7 @@ ReturnValue_t ParameterWrapper::set(const uint8_t* stream, int32_t streamSize, return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper* from, +ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from, uint16_t startWritingAtIndex) { if (data == NULL) { return READONLY; @@ -261,7 +267,7 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper* from, } } else { //need a type to do arithmetic - uint8_t *toDataWithType = (uint8_t *) data; + uint8_t *toDataWithType = (uint8_t*) data; for (uint8_t fromRow = 0; fromRow < from->rows; fromRow++) { memcpy( toDataWithType diff --git a/parameters/ParameterWrapper.h b/parameters/ParameterWrapper.h index e6d29c59..a00c997c 100644 --- a/parameters/ParameterWrapper.h +++ b/parameters/ParameterWrapper.h @@ -25,16 +25,16 @@ public: const void *data); virtual ~ParameterWrapper(); - virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const; + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const override; - virtual uint32_t getSerializedSize() const; + virtual size_t getSerializedSize() const override; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian); + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian, uint16_t startWritingAtIndex = 0); + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness, uint16_t startWritingAtIndex = 0); template ReturnValue_t getElement(T *value, uint8_t row = 0, uint8_t column = 0) const { @@ -111,8 +111,8 @@ public: void setMatrix(const T& member) { this->set(member[0], sizeof(member)/sizeof(member[0]), sizeof(member[0])/sizeof(member[0][0])); } - ReturnValue_t set(const uint8_t *stream, int32_t streamSize, - const uint8_t **remainingStream = NULL, int32_t *remainingSize = + ReturnValue_t set(const uint8_t *stream, size_t streamSize, + const uint8_t **remainingStream = NULL, size_t *remainingSize = NULL); ReturnValue_t copyFrom(const ParameterWrapper *from, @@ -128,8 +128,8 @@ private: const void *readonlyData; template - ReturnValue_t serializeData(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const; + ReturnValue_t serializeData(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const; template ReturnValue_t deSerializeData(uint8_t startingRow, uint8_t startingColumn, diff --git a/power/Fuse.cpp b/power/Fuse.cpp index dd5d3e3f..db24100b 100644 --- a/power/Fuse.cpp +++ b/power/Fuse.cpp @@ -86,12 +86,12 @@ ReturnValue_t Fuse::check() { return result; } -ReturnValue_t Fuse::serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { +ReturnValue_t Fuse::serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { ReturnValue_t result = RETURN_FAILED; for (DeviceList::const_iterator iter = devices.begin(); iter != devices.end(); iter++) { - result = (*iter)->serialize(buffer, size, max_size, bigEndian); + result = (*iter)->serialize(buffer, size, maxSize, streamEndianness); if (result != RETURN_OK) { return result; } @@ -99,7 +99,7 @@ ReturnValue_t Fuse::serialize(uint8_t** buffer, uint32_t* size, return RETURN_OK; } -uint32_t Fuse::getSerializedSize() const { +size_t Fuse::getSerializedSize() const { uint32_t size = 0; for (DeviceList::const_iterator iter = devices.begin(); iter != devices.end(); iter++) { @@ -108,12 +108,12 @@ uint32_t Fuse::getSerializedSize() const { return size; } -ReturnValue_t Fuse::deSerialize(const uint8_t** buffer, int32_t* size, -bool bigEndian) { +ReturnValue_t Fuse::deSerialize(const uint8_t** buffer, size_t* size, +Endianness streamEndianness) { ReturnValue_t result = RETURN_FAILED; for (DeviceList::iterator iter = devices.begin(); iter != devices.end(); iter++) { - result = (*iter)->deSerialize(buffer, size, bigEndian); + result = (*iter)->deSerialize(buffer, size, streamEndianness); if (result != RETURN_OK) { return result; } diff --git a/power/Fuse.h b/power/Fuse.h index 6da24178..4e22e3ed 100644 --- a/power/Fuse.h +++ b/power/Fuse.h @@ -11,14 +11,15 @@ #include #include -namespace Factory{ +namespace Factory { void setStaticFrameworkObjectIds(); } class Fuse: public SystemObject, public HasHealthIF, public HasReturnvaluesIF, - public ReceivesParameterMessagesIF { + public ReceivesParameterMessagesIF, + public SerializeIF { friend void (Factory::setStaticFrameworkObjectIds)(); private: static constexpr float RESIDUAL_POWER = 0.005 * 28.5; //!< This is the upper limit of residual power lost by fuses and switches. Worst case is Fuse and one of two switches on. See PCDU ICD 1.9 p29 bottom @@ -40,7 +41,7 @@ public: Fuse(object_id_t fuseObjectId, uint8_t fuseId, VariableIds ids, float maxCurrent, uint16_t confirmationCount = 2); virtual ~Fuse(); - void addDevice(PowerComponentIF* set); + void addDevice(PowerComponentIF *set); float getPower(); bool isPowerValid(); @@ -49,11 +50,11 @@ public: uint8_t getFuseId() const; ReturnValue_t initialize(); DeviceList devices; - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const; - uint32_t getSerializedSize() const; - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian); + ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const override; + size_t getSerializedSize() const override; + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + SerializeIF::Endianness streamEndianness) override; void setAllMonitorsToUnchecked(); ReturnValue_t performOperation(uint8_t opCode); MessageQueueId_t getCommandQueue() const; @@ -62,13 +63,13 @@ public: HasHealthIF::HealthState getHealth(); ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, - ParameterWrapper *parameterWrapper, - const ParameterWrapper *newValues, uint16_t startAtIndex); + ParameterWrapper *parameterWrapper, + const ParameterWrapper *newValues, uint16_t startAtIndex); private: uint8_t oldFuseState; uint8_t fuseId; - PowerSwitchIF* powerIF; //could be static in our case. + PowerSwitchIF *powerIF; //could be static in our case. AbsLimitMonitor currentLimit; class PowerMonitor: public MonitorReporter { public: @@ -88,11 +89,11 @@ private: PIDReader current; PIDReader state; db_float_t power; - MessageQueueIF* commandQueue; + MessageQueueIF *commandQueue; ParameterHelper parameterHelper; HealthHelper healthHelper; static object_id_t powerSwitchId; - void calculatePowerLimits(float* low, float* high); + void calculatePowerLimits(float *low, float *high); void calculateFusePower(); void checkFuseState(); void reportEvents(Event event); diff --git a/power/PowerComponent.cpp b/power/PowerComponent.cpp index 53bb06c8..cd116a86 100644 --- a/power/PowerComponent.cpp +++ b/power/PowerComponent.cpp @@ -17,18 +17,18 @@ PowerComponent::PowerComponent(object_id_t setId, uint8_t moduleId, float min, f twoSwitches), min(min), max(max), moduleId(moduleId) { } -ReturnValue_t PowerComponent::serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { +ReturnValue_t PowerComponent::serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { ReturnValue_t result = SerializeAdapter::serialize(&min, buffer, - size, max_size, bigEndian); + size, maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - return SerializeAdapter::serialize(&max, buffer, size, max_size, - bigEndian); + return SerializeAdapter::serialize(&max, buffer, size, maxSize, + streamEndianness); } -uint32_t PowerComponent::getSerializedSize() const { +size_t PowerComponent::getSerializedSize() const { return sizeof(min) + sizeof(max); } @@ -56,14 +56,14 @@ float PowerComponent::getMax() { return max; } -ReturnValue_t PowerComponent::deSerialize(const uint8_t** buffer, int32_t* size, -bool bigEndian) { +ReturnValue_t PowerComponent::deSerialize(const uint8_t** buffer, size_t* size, +Endianness streamEndianness) { ReturnValue_t result = SerializeAdapter::deSerialize(&min, buffer, - size, bigEndian); + size, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - return SerializeAdapter::deSerialize(&max, buffer, size, bigEndian); + return SerializeAdapter::deSerialize(&max, buffer, size, streamEndianness); } ReturnValue_t PowerComponent::getParameter(uint8_t domainId, diff --git a/power/PowerComponent.h b/power/PowerComponent.h index a82fe1d7..61ab3674 100644 --- a/power/PowerComponent.h +++ b/power/PowerComponent.h @@ -19,13 +19,13 @@ public: float getMin(); float getMax(); - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const; + ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const override; - uint32_t getSerializedSize() const; + size_t getSerializedSize() const override; - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian); + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, ParameterWrapper *parameterWrapper, diff --git a/serialize/SerialArrayListAdapter.h b/serialize/SerialArrayListAdapter.h index ab0c6c6f..bcd99818 100644 --- a/serialize/SerialArrayListAdapter.h +++ b/serialize/SerialArrayListAdapter.h @@ -20,25 +20,25 @@ public: SerialArrayListAdapter(ArrayList *adaptee) : adaptee(adaptee) { } - virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { - return serialize(adaptee, buffer, size, max_size, bigEndian); + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { + return serialize(adaptee, buffer, size, maxSize, streamEndianness); } - static ReturnValue_t serialize(const ArrayList* list, uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) { + static ReturnValue_t serialize(const ArrayList* list, uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) { ReturnValue_t result = SerializeAdapter::serialize(&list->size, - buffer, size, max_size, bigEndian); + buffer, size, maxSize, streamEndianness); count_t i = 0; while ((result == HasReturnvaluesIF::RETURN_OK) && (i < list->size)) { result = SerializeAdapter::serialize(&list->entries[i], buffer, size, - max_size, bigEndian); + maxSize, streamEndianness); ++i; } return result; } - virtual uint32_t getSerializedSize() const { + virtual size_t getSerializedSize() const { return getSerializedSize(adaptee); } @@ -53,16 +53,16 @@ public: return printSize; } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { - return deSerialize(adaptee, buffer, size, bigEndian); + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) { + return deSerialize(adaptee, buffer, size, streamEndianness); } - static ReturnValue_t deSerialize(ArrayList* list, const uint8_t** buffer, int32_t* size, - bool bigEndian) { + static ReturnValue_t deSerialize(ArrayList* list, const uint8_t** buffer, size_t* size, + Endianness streamEndianness) { count_t tempSize = 0; ReturnValue_t result = SerializeAdapter::deSerialize(&tempSize, - buffer, size, bigEndian); + buffer, size, streamEndianness); if (tempSize > list->maxSize()) { return SerializeIF::TOO_MANY_ELEMENTS; } @@ -71,7 +71,7 @@ public: while ((result == HasReturnvaluesIF::RETURN_OK) && (i < list->size)) { result = SerializeAdapter::deSerialize( &list->front()[i], buffer, size, - bigEndian); + streamEndianness); ++i; } return result; diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index f78ec8ac..d4d8d1c7 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -22,19 +22,19 @@ SerialBufferAdapter::~SerialBufferAdapter() { } template -ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { +ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { uint32_t serializedLength = bufferLength; if (serializeLength) { serializedLength += SerializeAdapter::getSerializedSize( &bufferLength); } - if (*size + serializedLength > max_size) { + if (*size + serializedLength > maxSize) { return BUFFER_TOO_SHORT; } else { if (serializeLength) { SerializeAdapter::serialize(&bufferLength, buffer, size, - max_size, bigEndian); + maxSize, streamEndianness); } if (this->constBuffer != NULL) { memcpy(*buffer, this->constBuffer, bufferLength); @@ -50,7 +50,7 @@ ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, uint32_t* size } template -uint32_t SerialBufferAdapter::getSerializedSize() const { +size_t SerialBufferAdapter::getSerializedSize() const { if (serializeLength) { return bufferLength + SerializeAdapter::getSerializedSize(&bufferLength); } else { @@ -59,7 +59,7 @@ uint32_t SerialBufferAdapter::getSerializedSize() const { } template ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, - int32_t* size, bool bigEndian) { + size_t* size, Endianness streamEndianness) { //TODO Ignores Endian flag! if (buffer != NULL) { if(serializeLength){ diff --git a/serialize/SerialBufferAdapter.h b/serialize/SerialBufferAdapter.h index 7cd75d55..78d42b80 100644 --- a/serialize/SerialBufferAdapter.h +++ b/serialize/SerialBufferAdapter.h @@ -16,13 +16,13 @@ public: virtual ~SerialBufferAdapter(); - virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const; + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const override; - virtual uint32_t getSerializedSize() const; + virtual size_t getSerializedSize() const override; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian); + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; private: bool serializeLength; const uint8_t *constBuffer; diff --git a/serialize/SerialFixedArrayListAdapter.h b/serialize/SerialFixedArrayListAdapter.h index 16919b62..a2e683bf 100644 --- a/serialize/SerialFixedArrayListAdapter.h +++ b/serialize/SerialFixedArrayListAdapter.h @@ -13,16 +13,16 @@ public: template SerialFixedArrayListAdapter(Args... args) : FixedArrayList(std::forward(args)...) { } - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { - return SerialArrayListAdapter::serialize(this, buffer, size, max_size, bigEndian); + ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { + return SerialArrayListAdapter::serialize(this, buffer, size, maxSize, streamEndianness); } - uint32_t getSerializedSize() const { + size_t getSerializedSize() const { return SerialArrayListAdapter::getSerializedSize(this); } - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { - return SerialArrayListAdapter::deSerialize(this, buffer, size, bigEndian); + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) { + return SerialArrayListAdapter::deSerialize(this, buffer, size, streamEndianness); } }; diff --git a/serialize/SerializeElement.h b/serialize/SerializeElement.h index 22e9838c..3941e9fb 100644 --- a/serialize/SerializeElement.h +++ b/serialize/SerializeElement.h @@ -26,7 +26,7 @@ public: streamEndianness); } - uint32_t getSerializedSize() const override { + size_t getSerializedSize() const override { return SerializeAdapter::getSerializedSize(&entry); } diff --git a/serialize/SerializeIF.h b/serialize/SerializeIF.h index 6c875a5c..14244a7a 100644 --- a/serialize/SerializeIF.h +++ b/serialize/SerializeIF.h @@ -28,7 +28,7 @@ public: } virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, - size_t max_size, Endianness streamEndianness) const = 0; + size_t maxSize, Endianness streamEndianness) const = 0; virtual size_t getSerializedSize() const = 0; diff --git a/subsystem/Subsystem.cpp b/subsystem/Subsystem.cpp index ef706dd7..2e8a325a 100644 --- a/subsystem/Subsystem.cpp +++ b/subsystem/Subsystem.cpp @@ -13,7 +13,7 @@ Subsystem::Subsystem(object_id_t setObjectId, object_id_t parent, false), uptimeStartTable(0), currentTargetTable(), targetMode( 0), targetSubmode(SUBMODE_NONE), initialMode(0), currentSequenceIterator(), modeTables( maxNumberOfTables), modeSequences(maxNumberOfSequences), IPCStore( - NULL) + NULL) #ifdef USE_MODESTORE ,modeStore(NULL) #endif @@ -75,7 +75,8 @@ void Subsystem::performChildOperation() { if (isInTransition) { if (commandsOutstanding <= 0) { //all children of the current table were commanded and replied if (currentSequenceIterator.value == NULL) { //we're through with this sequence - if (checkStateAgainstTable(currentTargetTable, targetSubmode) == RETURN_OK) { + if (checkStateAgainstTable(currentTargetTable, targetSubmode) + == RETURN_OK) { setMode(targetMode, targetSubmode); isInTransition = false; return; @@ -86,7 +87,8 @@ void Subsystem::performChildOperation() { } } if (currentSequenceIterator->checkSuccess()) { - if (checkStateAgainstTable(getCurrentTable(), targetSubmode) != RETURN_OK) { + if (checkStateAgainstTable(getCurrentTable(), targetSubmode) + != RETURN_OK) { transitionFailed(TABLE_CHECK_FAILED, currentSequenceIterator->getTableId()); return; @@ -117,7 +119,8 @@ void Subsystem::performChildOperation() { childrenChangedHealth = false; startTransition(mode, submode); } else if (childrenChangedMode) { - if (checkStateAgainstTable(currentTargetTable, submode) != RETURN_OK) { + if (checkStateAgainstTable(currentTargetTable, submode) + != RETURN_OK) { triggerEvent(CANT_KEEP_MODE, mode, submode); cantKeepMode(); } @@ -147,7 +150,7 @@ HybridIterator Subsystem::getTable(Mode_t id) { } } -ReturnValue_t Subsystem::handleCommandMessage(CommandMessage* message) { +ReturnValue_t Subsystem::handleCommandMessage(CommandMessage *message) { ReturnValue_t result; switch (message->getCommand()) { case HealthMessage::HEALTH_INFO: { @@ -168,12 +171,13 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage* message) { &sizeRead); if (result == RETURN_OK) { Mode_t fallbackId; - int32_t size = sizeRead; - result = SerializeAdapter::deSerialize(&fallbackId, - &pointer, &size, true); + size_t size = sizeRead; + result = SerializeAdapter::deSerialize(&fallbackId, &pointer, &size, + SerializeIF::Endianness::BIG); if (result == RETURN_OK) { result = SerialArrayListAdapter::deSerialize( - &sequence, &pointer, &size, true); + &sequence, &pointer, &size, + SerializeIF::Endianness::BIG); if (result == RETURN_OK) { result = addSequence(&sequence, ModeSequenceMessage::getSequenceId(message), @@ -193,9 +197,9 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage* message) { ModeSequenceMessage::getStoreAddress(message), &pointer, &sizeRead); if (result == RETURN_OK) { - int32_t size = sizeRead; + size_t size = sizeRead; result = SerialArrayListAdapter::deSerialize(&table, - &pointer, &size, true); + &pointer, &size, SerializeIF::Endianness::BIG); if (result == RETURN_OK) { result = addTable(&table, ModeSequenceMessage::getSequenceId(message)); @@ -339,7 +343,7 @@ void Subsystem::replyToCommand(ReturnValue_t status, uint32_t parameter) { } } -ReturnValue_t Subsystem::addSequence(ArrayList* sequence, +ReturnValue_t Subsystem::addSequence(ArrayList *sequence, Mode_t id, Mode_t fallbackSequence, bool inStore, bool preInit) { ReturnValue_t result; @@ -507,7 +511,7 @@ MessageQueueId_t Subsystem::getSequenceCommandQueue() const { } ReturnValue_t Subsystem::checkModeCommand(Mode_t mode, Submode_t submode, - uint32_t* msToReachTheMode) { + uint32_t *msToReachTheMode) { //Need to accept all submodes to be able to inherit submodes // if (submode != SUBMODE_NONE) { // return INVALID_SUBMODE; @@ -599,15 +603,15 @@ void Subsystem::transitionFailed(ReturnValue_t failureCode, } void Subsystem::sendSerializablesAsCommandMessage(Command_t command, - SerializeIF** elements, uint8_t count) { + SerializeIF **elements, uint8_t count) { ReturnValue_t result; - uint32_t maxSize = 0; + size_t maxSize = 0; for (uint8_t i = 0; i < count; i++) { maxSize += elements[i]->getSerializedSize(); } uint8_t *storeBuffer; store_address_t address; - uint32_t size = 0; + size_t size = 0; result = IPCStore->getFreeElement(&address, maxSize, &storeBuffer); if (result != HasReturnvaluesIF::RETURN_OK) { @@ -615,7 +619,8 @@ void Subsystem::sendSerializablesAsCommandMessage(Command_t command, return; } for (uint8_t i = 0; i < count; i++) { - elements[i]->serialize(&storeBuffer, &size, maxSize, true); + elements[i]->serialize(&storeBuffer, &size, maxSize, + SerializeIF::Endianness::BIG); } CommandMessage reply; ModeSequenceMessage::setModeSequenceMessage(&reply, command, address); diff --git a/subsystem/modes/ModeDefinitions.h b/subsystem/modes/ModeDefinitions.h index 3e749dd8..153710af 100644 --- a/subsystem/modes/ModeDefinitions.h +++ b/subsystem/modes/ModeDefinitions.h @@ -18,65 +18,65 @@ public: uint8_t value3; uint8_t value4; - virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { ReturnValue_t result; result = SerializeAdapter::serialize(&value1, buffer, size, - max_size, bigEndian); + maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } result = SerializeAdapter::serialize(&value2, buffer, size, - max_size, bigEndian); + maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } result = SerializeAdapter::serialize(&value3, buffer, size, - max_size, bigEndian); + maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } result = SerializeAdapter::serialize(&value4, buffer, size, - max_size, bigEndian); + maxSize, streamEndianness); return result; } - virtual uint32_t getSerializedSize() const { + virtual size_t getSerializedSize() const { return sizeof(value1) + sizeof(value2) + sizeof(value3) + sizeof(value4); } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) { ReturnValue_t result; result = SerializeAdapter::deSerialize(&value1, buffer, size, - bigEndian); + streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } result = SerializeAdapter::deSerialize(&value2, buffer, size, - bigEndian); + streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } result = SerializeAdapter::deSerialize(&value3, buffer, size, - bigEndian); + streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } result = SerializeAdapter::deSerialize(&value4, buffer, size, - bigEndian); + streamEndianness); return result; } diff --git a/thermal/ThermalComponent.cpp b/thermal/ThermalComponent.cpp index 93513e16..5dcd0bc6 100644 --- a/thermal/ThermalComponent.cpp +++ b/thermal/ThermalComponent.cpp @@ -46,15 +46,15 @@ ReturnValue_t ThermalComponent::setLimits(const uint8_t* data, uint32_t size) { if (size != 4 * sizeof(parameters.lowerOpLimit)) { return MonitoringIF::INVALID_SIZE; } - int32_t readSize = size; + size_t readSize = size; SerializeAdapter::deSerialize(&nopParameters.lowerNopLimit, &data, - &readSize, true); + &readSize, SerializeIF::Endianness::BIG); SerializeAdapter::deSerialize(¶meters.lowerOpLimit, &data, - &readSize, true); + &readSize, SerializeIF::Endianness::BIG); SerializeAdapter::deSerialize(¶meters.upperOpLimit, &data, - &readSize, true); + &readSize, SerializeIF::Endianness::BIG); SerializeAdapter::deSerialize(&nopParameters.upperNopLimit, &data, - &readSize, true); + &readSize, SerializeIF::Endianness::BIG); return HasReturnvaluesIF::RETURN_OK; } diff --git a/tmstorage/TmStorePackets.h b/tmstorage/TmStorePackets.h index 4e7160fb..16768e68 100644 --- a/tmstorage/TmStorePackets.h +++ b/tmstorage/TmStorePackets.h @@ -32,31 +32,31 @@ public: } uint16_t apid; uint16_t ssc; - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { + ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { ReturnValue_t result = SerializeAdapter::serialize(&apid, - buffer, size, max_size, bigEndian); + buffer, size, maxSize, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } return SerializeAdapter::serialize(&ssc, buffer, size, - max_size, bigEndian); + maxSize, streamEndianness); } - uint32_t getSerializedSize() const { + size_t getSerializedSize() const { return sizeof(apid) + sizeof(ssc); } - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) { ReturnValue_t result = SerializeAdapter::deSerialize(&apid, - buffer, size, bigEndian); + buffer, size, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } return SerializeAdapter::deSerialize(&ssc, buffer, size, - bigEndian); + streamEndianness); } }; @@ -218,33 +218,33 @@ public: } - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { - ReturnValue_t result = SerializeAdapter::serialize(&apid,buffer,size,max_size,bigEndian); + ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { + ReturnValue_t result = SerializeAdapter::serialize(&apid,buffer,size,maxSize,streamEndianness); if(result!=HasReturnvaluesIF::RETURN_OK){ return result; } - result = SerializeAdapter::serialize(&sourceSequenceCount,buffer,size,max_size,bigEndian); + result = SerializeAdapter::serialize(&sourceSequenceCount,buffer,size,maxSize,streamEndianness); if(result!=HasReturnvaluesIF::RETURN_OK){ return result; } - result = SerializeAdapter::serialize(&serviceType,buffer,size,max_size,bigEndian); + result = SerializeAdapter::serialize(&serviceType,buffer,size,maxSize,streamEndianness); if(result!=HasReturnvaluesIF::RETURN_OK){ return result; } - result = SerializeAdapter::serialize(&serviceSubtype,buffer,size,max_size,bigEndian); + result = SerializeAdapter::serialize(&serviceSubtype,buffer,size,maxSize,streamEndianness); if(result!=HasReturnvaluesIF::RETURN_OK){ return result; } - result = SerializeAdapter::serialize(&subCounter,buffer,size,max_size,bigEndian); + result = SerializeAdapter::serialize(&subCounter,buffer,size,maxSize,streamEndianness); if(result!=HasReturnvaluesIF::RETURN_OK){ return result; } SerialBufferAdapter adapter(rawTimestamp,sizeof(rawTimestamp)); - return adapter.serialize(buffer,size,max_size,bigEndian); + return adapter.serialize(buffer,size,maxSize,streamEndianness); } - uint32_t getSerializedSize() const { + size_t getSerializedSize() const { uint32_t size = 0; size += SerializeAdapter::getSerializedSize(&apid); size += SerializeAdapter::getSerializedSize(&sourceSequenceCount); @@ -257,35 +257,35 @@ public: }; - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) { ReturnValue_t result = SerializeAdapter::deSerialize(&apid, buffer, - size, bigEndian); + size, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } result = SerializeAdapter::deSerialize(&sourceSequenceCount, buffer, - size, bigEndian); + size, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } result = SerializeAdapter::deSerialize(&serviceType, buffer, size, - bigEndian); + streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } result = SerializeAdapter::deSerialize(&serviceSubtype, buffer, - size, bigEndian); + size, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } result = SerializeAdapter::deSerialize(&subCounter, buffer, size, - bigEndian); + streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } SerialBufferAdapter adapter(rawTimestamp,sizeof(rawTimestamp)); - return adapter.deSerialize(buffer,size,bigEndian); + return adapter.deSerialize(buffer,size,streamEndianness); } private: diff --git a/tmtcpacket/packetmatcher/ApidMatcher.h b/tmtcpacket/packetmatcher/ApidMatcher.h index d5d96f2d..3080ffef 100644 --- a/tmtcpacket/packetmatcher/ApidMatcher.h +++ b/tmtcpacket/packetmatcher/ApidMatcher.h @@ -22,16 +22,16 @@ public: return false; } } - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { - return SerializeAdapter::serialize(&apid, buffer, size, max_size, bigEndian); + ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { + return SerializeAdapter::serialize(&apid, buffer, size, maxSize, streamEndianness); } - uint32_t getSerializedSize() const { + size_t getSerializedSize() const { return SerializeAdapter::getSerializedSize(&apid); } - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { - return SerializeAdapter::deSerialize(&apid, buffer, size, bigEndian); + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) { + return SerializeAdapter::deSerialize(&apid, buffer, size, streamEndianness); } }; diff --git a/tmtcpacket/packetmatcher/ServiceMatcher.h b/tmtcpacket/packetmatcher/ServiceMatcher.h index b0623780..f6e9e360 100644 --- a/tmtcpacket/packetmatcher/ServiceMatcher.h +++ b/tmtcpacket/packetmatcher/ServiceMatcher.h @@ -22,16 +22,16 @@ public: return false; } } - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { - return SerializeAdapter::serialize(&service, buffer, size, max_size, bigEndian); + ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { + return SerializeAdapter::serialize(&service, buffer, size, maxSize, streamEndianness); } - uint32_t getSerializedSize() const { + size_t getSerializedSize() const { return SerializeAdapter::getSerializedSize(&service); } - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { - return SerializeAdapter::deSerialize(&service, buffer, size, bigEndian); + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) { + return SerializeAdapter::deSerialize(&service, buffer, size, streamEndianness); } }; diff --git a/tmtcpacket/packetmatcher/SubserviceMatcher.h b/tmtcpacket/packetmatcher/SubserviceMatcher.h index 90370af1..2e8b82b2 100644 --- a/tmtcpacket/packetmatcher/SubserviceMatcher.h +++ b/tmtcpacket/packetmatcher/SubserviceMatcher.h @@ -20,16 +20,16 @@ public: return false; } } - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { - return SerializeAdapter::serialize(&subService, buffer, size, max_size, bigEndian); + ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { + return SerializeAdapter::serialize(&subService, buffer, size, maxSize, streamEndianness); } - uint32_t getSerializedSize() const { + size_t getSerializedSize() const { return SerializeAdapter::getSerializedSize(&subService); } - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { - return SerializeAdapter::deSerialize(&subService, buffer, size, bigEndian); + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) { + return SerializeAdapter::deSerialize(&subService, buffer, size, streamEndianness); } private: uint8_t subService; diff --git a/tmtcpacket/pus/TmPacketStored.cpp b/tmtcpacket/pus/TmPacketStored.cpp index f2c1eb28..32f9c431 100644 --- a/tmtcpacket/pus/TmPacketStored.cpp +++ b/tmtcpacket/pus/TmPacketStored.cpp @@ -10,14 +10,14 @@ TmPacketStored::TmPacketStored(store_address_t setAddress) : } TmPacketStored::TmPacketStored(uint16_t apid, uint8_t service, - uint8_t subservice, uint8_t packetSubcounter, const uint8_t* data, - uint32_t size, const uint8_t* headerData, uint32_t headerSize) : + uint8_t subservice, uint8_t packetSubcounter, const uint8_t *data, + uint32_t size, const uint8_t *headerData, uint32_t headerSize) : TmPacketBase(NULL) { storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; if (!checkAndSetStore()) { return; } - uint8_t* pData = NULL; + uint8_t *pData = NULL; ReturnValue_t returnValue = store->getFreeElement(&storeAddress, (TmPacketBase::TM_PACKET_MIN_SIZE + size + headerSize), &pData); @@ -34,21 +34,21 @@ TmPacketStored::TmPacketStored(uint16_t apid, uint8_t service, } TmPacketStored::TmPacketStored(uint16_t apid, uint8_t service, - uint8_t subservice, uint8_t packetSubcounter, SerializeIF* content, - SerializeIF* header) : + uint8_t subservice, uint8_t packetSubcounter, SerializeIF *content, + SerializeIF *header) : TmPacketBase(NULL) { storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; if (!checkAndSetStore()) { return; } - uint32_t sourceDataSize = 0; + size_t sourceDataSize = 0; if (content != NULL) { sourceDataSize += content->getSerializedSize(); } if (header != NULL) { sourceDataSize += header->getSerializedSize(); } - uint8_t* p_data = NULL; + uint8_t *p_data = NULL; ReturnValue_t returnValue = store->getFreeElement(&storeAddress, (TmPacketBase::TM_PACKET_MIN_SIZE + sourceDataSize), &p_data); if (returnValue != store->RETURN_OK) { @@ -56,13 +56,15 @@ TmPacketStored::TmPacketStored(uint16_t apid, uint8_t service, } setData(p_data); initializeTmPacket(apid, service, subservice, packetSubcounter); - uint8_t* putDataHere = getSourceData(); - uint32_t size = 0; + uint8_t *putDataHere = getSourceData(); + size_t size = 0; if (header != NULL) { - header->serialize(&putDataHere, &size, sourceDataSize, true); + header->serialize(&putDataHere, &size, sourceDataSize, + SerializeIF::Endianness::BIG); } if (content != NULL) { - content->serialize(&putDataHere, &size, sourceDataSize, true); + content->serialize(&putDataHere, &size, sourceDataSize, + SerializeIF::Endianness::BIG); } setPacketDataLength( sourceDataSize + sizeof(PUSTmDataFieldHeader) + CRC_SIZE - 1); @@ -80,7 +82,7 @@ void TmPacketStored::deletePacket() { void TmPacketStored::setStoreAddress(store_address_t setAddress) { storeAddress = setAddress; - const uint8_t* temp_data = NULL; + const uint8_t *temp_data = NULL; uint32_t temp_size; if (!checkAndSetStore()) { return; @@ -106,8 +108,8 @@ bool TmPacketStored::checkAndSetStore() { return true; } -StorageManagerIF* TmPacketStored::store = NULL; -InternalErrorReporterIF* TmPacketStored::internalErrorReporter = NULL; +StorageManagerIF *TmPacketStored::store = NULL; +InternalErrorReporterIF *TmPacketStored::internalErrorReporter = NULL; ReturnValue_t TmPacketStored::sendPacket(MessageQueueId_t destination, MessageQueueId_t sentFrom, bool doErrorReporting) { @@ -116,7 +118,8 @@ ReturnValue_t TmPacketStored::sendPacket(MessageQueueId_t destination, return HasReturnvaluesIF::RETURN_FAILED; } TmTcMessage tmMessage(getStoreAddress()); - ReturnValue_t result = MessageQueueSenderIF::sendMessage(destination, &tmMessage, sentFrom); + ReturnValue_t result = MessageQueueSenderIF::sendMessage(destination, + &tmMessage, sentFrom); if (result != HasReturnvaluesIF::RETURN_OK) { deletePacket(); if (doErrorReporting) { diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index 5b9e7b68..aa41f334 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -235,9 +235,9 @@ void CommandingServiceBase::sendTmPacket(uint8_t subservice, object_id_t objectId, const uint8_t *data, uint32_t dataLen) { uint8_t buffer[sizeof(object_id_t)]; uint8_t* pBuffer = buffer; - uint32_t size = 0; + size_t size = 0; SerializeAdapter::serialize(&objectId, &pBuffer, &size, - sizeof(object_id_t), true); + sizeof(object_id_t), SerializeIF::Endianness::BIG); TmPacketStored tmPacketStored(this->apid, this->service, subservice, this->tmPacketCounter, data, dataLen, buffer, size); ReturnValue_t result = tmPacketStored.sendPacket( diff --git a/tmtcservices/PusVerificationReport.cpp b/tmtcservices/PusVerificationReport.cpp index e1dad2be..07631801 100644 --- a/tmtcservices/PusVerificationReport.cpp +++ b/tmtcservices/PusVerificationReport.cpp @@ -33,7 +33,7 @@ PusVerificationMessage::PusVerificationMessage(uint8_t set_report_id, uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, ReturnValue_t set_error_code, uint8_t set_step, uint32_t parameter1, uint32_t parameter2) { - uint8_t* data = this->getBuffer(); + uint8_t *data = this->getBuffer(); data[messageSize] = set_report_id; messageSize += sizeof(set_report_id); data[messageSize] = ackFlags; @@ -109,12 +109,12 @@ PusSuccessReport::PusSuccessReport(uint16_t setPacketId, reportSize(0), pBuffer(reportBuffer) { //Serialization won't fail, because we know the necessary max-size of the buffer. SerializeAdapter::serialize(&setPacketId, &pBuffer, &reportSize, - sizeof(reportBuffer), true); - SerializeAdapter::serialize(&setSequenceControl, &pBuffer, - &reportSize, sizeof(reportBuffer), true); + sizeof(reportBuffer), SerializeIF::Endianness::BIG); + SerializeAdapter::serialize(&setSequenceControl, &pBuffer, &reportSize, + sizeof(reportBuffer), SerializeIF::Endianness::BIG); if (setStep != 0) { SerializeAdapter::serialize(&setStep, &pBuffer, &reportSize, - sizeof(reportBuffer), true); + sizeof(reportBuffer), SerializeIF::Endianness::BIG); } } @@ -136,25 +136,25 @@ PusFailureReport::PusFailureReport(uint16_t setPacketId, reportSize(0), pBuffer(reportBuffer) { //Serialization won't fail, because we know the necessary max-size of the buffer. SerializeAdapter::serialize(&setPacketId, &pBuffer, &reportSize, - sizeof(reportBuffer), true); - SerializeAdapter::serialize(&setSequenceControl, &pBuffer, - &reportSize, sizeof(reportBuffer), true); + sizeof(reportBuffer), SerializeIF::Endianness::BIG); + SerializeAdapter::serialize(&setSequenceControl, &pBuffer, &reportSize, + sizeof(reportBuffer), SerializeIF::Endianness::BIG); if (setStep != 0) { SerializeAdapter::serialize(&setStep, &pBuffer, &reportSize, - sizeof(reportBuffer), true); + sizeof(reportBuffer), SerializeIF::Endianness::BIG); } - SerializeAdapter::serialize(&setErrorCode, &pBuffer, - &reportSize, sizeof(reportBuffer), true); + SerializeAdapter::serialize(&setErrorCode, &pBuffer, &reportSize, + sizeof(reportBuffer), SerializeIF::Endianness::BIG); SerializeAdapter::serialize(¶meter1, &pBuffer, &reportSize, - sizeof(reportBuffer), true); + sizeof(reportBuffer), SerializeIF::Endianness::BIG); SerializeAdapter::serialize(¶meter2, &pBuffer, &reportSize, - sizeof(reportBuffer), true); + sizeof(reportBuffer), SerializeIF::Endianness::BIG); } PusFailureReport::~PusFailureReport() { } -uint32_t PusFailureReport::getSize() { +size_t PusFailureReport::getSize() { return reportSize; } diff --git a/tmtcservices/PusVerificationReport.h b/tmtcservices/PusVerificationReport.h index 7a173be9..ee84f0c1 100644 --- a/tmtcservices/PusVerificationReport.h +++ b/tmtcservices/PusVerificationReport.h @@ -49,7 +49,7 @@ class PusSuccessReport { private: static const uint16_t MAX_SIZE = 7; uint8_t reportBuffer[MAX_SIZE]; - uint32_t reportSize; + size_t reportSize; uint8_t * pBuffer; public: PusSuccessReport(uint16_t setPacketId, uint16_t setSequenceControl, @@ -63,14 +63,14 @@ class PusFailureReport { private: static const uint16_t MAX_SIZE = 16; uint8_t reportBuffer[MAX_SIZE]; - uint32_t reportSize; + size_t reportSize; uint8_t * pBuffer; public: PusFailureReport(uint16_t setPacketId, uint16_t setSequenceControl, ReturnValue_t setErrorCode, uint8_t setStep = 0, uint32_t parameter1 = 0, uint32_t parameter2 = 0); ~PusFailureReport(); - uint32_t getSize(); + size_t getSize(); uint8_t* getReport(); }; From 07247dbf403b625dcc1b5c54241243ad19219288 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 23 Apr 2020 11:50:13 +0200 Subject: [PATCH 037/653] added virtual keyword for init and performOp() --- tmtcservices/TmTcBridge.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tmtcservices/TmTcBridge.h b/tmtcservices/TmTcBridge.h index c6c79d6c..9fb00ef1 100644 --- a/tmtcservices/TmTcBridge.h +++ b/tmtcservices/TmTcBridge.h @@ -52,12 +52,12 @@ public: * Initializes necessary FSFW components for the TMTC Bridge * @return */ - ReturnValue_t initialize() override; + virtual ReturnValue_t initialize() override; /** * @brief Handles TMTC reception */ - ReturnValue_t performOperation(uint8_t operationCode = 0) override; + virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override; /** * Return TMTC Reception Queue From 6be607e4220141111c67a2a611fc1e62517e269c Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 4 May 2020 17:33:56 +0200 Subject: [PATCH 038/653] FIFO protected --- tmtcservices/TmTcBridge.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmtcservices/TmTcBridge.h b/tmtcservices/TmTcBridge.h index 9fb00ef1..15fd42c1 100644 --- a/tmtcservices/TmTcBridge.h +++ b/tmtcservices/TmTcBridge.h @@ -75,6 +75,7 @@ protected: //! Used to specify whether communication link is up bool communicationLinkUp = false; bool tmStored = false; + FIFO fifo; /** * @brief Handle TC reception @@ -141,7 +142,6 @@ protected: void printData(uint8_t * data, size_t dataLen); private: - FIFO fifo; uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE; uint8_t maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED; }; From 684dd67f638040143c425df537d16ab13230b38d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 5 May 2020 19:14:51 +0200 Subject: [PATCH 039/653] seconds_t double now --- timemanager/Clock.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/timemanager/Clock.h b/timemanager/Clock.h index 5f18de3e..2883878f 100644 --- a/timemanager/Clock.h +++ b/timemanager/Clock.h @@ -8,7 +8,7 @@ #include typedef uint32_t millis_t; -typedef float seconds_t; +typedef double seconds_t; class Clock { public: From 25ff8784cf0554e85ed50ff0d073dbff56bf2d51 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 7 May 2020 20:00:42 +0200 Subject: [PATCH 040/653] corrected documentation --- timemanager/Stopwatch.cpp | 6 ------ timemanager/Stopwatch.h | 13 +++---------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/timemanager/Stopwatch.cpp b/timemanager/Stopwatch.cpp index 3f0755fd..771b63dc 100644 --- a/timemanager/Stopwatch.cpp +++ b/timemanager/Stopwatch.cpp @@ -1,9 +1,3 @@ -/** - * @file Stopwatch.cpp - * - * @date 08.04.2020 - */ - #include #include #include diff --git a/timemanager/Stopwatch.h b/timemanager/Stopwatch.h index 786a9d57..19e1f92b 100644 --- a/timemanager/Stopwatch.h +++ b/timemanager/Stopwatch.h @@ -1,9 +1,3 @@ -/** - * @file Stopwatch.h - * - * @date 08.04.2020 - */ - #ifndef FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ #define FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ #include @@ -18,8 +12,7 @@ enum class StopwatchDisplayMode { * @details * This class can be used to measure elapsed times. It also displays elapsed * times automatically on destruction if not explicitely deactivated in the - * constructor. The default time format is the elapsed time in miliseconds - * as a float. + * constructor. The default time format is the elapsed time in miliseconds. */ class Stopwatch { public: @@ -28,8 +21,8 @@ public: * no parameters are required! * @param displayOnDestruction If set to true, displays measured time on * object destruction - * @param displayMode Display format is either MS rounded or MS as double - * format + * @param displayMode Display format is either MS rounded or seconds as + * double format * @param outputPrecision If using double format, specify precision here. */ Stopwatch(bool displayOnDestruction = true, StopwatchDisplayMode displayMode From 33eae034c7c7a9e697505461b8676eeae2a4d733 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 7 May 2020 23:14:29 +0200 Subject: [PATCH 041/653] replace device comIF uint32_t with size_t --- devicehandlers/DeviceCommunicationIF.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/devicehandlers/DeviceCommunicationIF.h b/devicehandlers/DeviceCommunicationIF.h index 1f6d01f0..8301ddcf 100644 --- a/devicehandlers/DeviceCommunicationIF.h +++ b/devicehandlers/DeviceCommunicationIF.h @@ -81,7 +81,7 @@ public: * - Everything else triggers failure event with returnvalue as parameter 1 */ virtual ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t * sendData, - uint32_t sendLen) = 0; + size_t sendLen) = 0; /** * Called by DHB in the GET_WRITE doGetWrite(). @@ -107,7 +107,7 @@ public: * returnvalue as parameter 1 */ virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie, - uint32_t requestLen) = 0; + size_t requestLen) = 0; /** * Called by DHB in the GET_WRITE doGetRead(). @@ -124,7 +124,7 @@ public: * returnvalue as parameter 1 */ virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, - uint32_t *size) = 0; + size_t *size) = 0; }; #endif /* DEVICECOMMUNICATIONIF_H_ */ From 614deea323bd22af7fd937bb40bf1f23dee7ad83 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 7 May 2020 23:38:28 +0200 Subject: [PATCH 042/653] last size_t replacements --- devicehandlers/DeviceCommunicationIF.h | 1 + devicehandlers/DeviceHandlerBase.cpp | 4 ++-- devicehandlers/DeviceHandlerBase.h | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/devicehandlers/DeviceCommunicationIF.h b/devicehandlers/DeviceCommunicationIF.h index 8301ddcf..9ca31a9b 100644 --- a/devicehandlers/DeviceCommunicationIF.h +++ b/devicehandlers/DeviceCommunicationIF.h @@ -3,6 +3,7 @@ #include #include +#include /** * @defgroup interfaces Interfaces * @brief Interfaces for flight software objects diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 3331f5f9..068fdd78 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -570,10 +570,10 @@ void DeviceHandlerBase::doSendRead() { } void DeviceHandlerBase::doGetRead() { - uint32_t receivedDataLen; + size_t receivedDataLen; uint8_t *receivedData; DeviceCommandId_t foundId = 0xFFFFFFFF; - uint32_t foundLen = 0; + size_t foundLen = 0; ReturnValue_t result; if (cookieInfo.state != COOKIE_READ_SENT) { diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index d0c95a5a..379992b1 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -301,8 +301,8 @@ protected: * requested by a command, but should be handled anyway * (@see also fillCommandAndCookieMap() ) */ - virtual ReturnValue_t scanForReply(const uint8_t *start, uint32_t len, - DeviceCommandId_t *foundId, uint32_t *foundLen) = 0; + virtual ReturnValue_t scanForReply(const uint8_t *start, size_t len, + DeviceCommandId_t *foundId, size_t *foundLen) = 0; /** * @brief Interpret a reply from the device. From fadebe2eb4255aa6ff870ed3fa07e70905487138 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 8 May 2020 14:38:10 +0200 Subject: [PATCH 043/653] new initializer list ctor --- datapool/PoolEntry.cpp | 18 ++++++++-- datapool/PoolEntry.h | 79 ++++++++++++++++++++++++------------------ 2 files changed, 62 insertions(+), 35 deletions(-) diff --git a/datapool/PoolEntry.cpp b/datapool/PoolEntry.cpp index de024c81..97c60131 100644 --- a/datapool/PoolEntry.cpp +++ b/datapool/PoolEntry.cpp @@ -2,9 +2,22 @@ #include template -PoolEntry::PoolEntry( T* initValue, uint8_t set_length, uint8_t set_valid ) : length(set_length), valid(set_valid) { +PoolEntry::PoolEntry(std::initializer_list initValue, uint8_t set_length, + uint8_t set_valid ) : length(set_length), valid(set_valid) { this->address = new T[this->length]; - if (initValue != NULL) { + if(initValue.size() == 0) { + memset(this->address, 0, this->getByteSize()); + } + else { + memcpy(this->address, initValue.begin(), this->getByteSize()); + } +} + +template +PoolEntry::PoolEntry( T* initValue, uint8_t set_length, uint8_t set_valid ) : + length(set_length), valid(set_valid) { + this->address = new T[this->length]; + if (initValue != nullptr) { memcpy(this->address, initValue, this->getByteSize() ); } else { memset(this->address, 0, this->getByteSize() ); @@ -57,6 +70,7 @@ Type PoolEntry::getType() { return PodTypeConversion::type; } +template class PoolEntry; template class PoolEntry; template class PoolEntry; template class PoolEntry; diff --git a/datapool/PoolEntry.h b/datapool/PoolEntry.h index ce41a991..5edc0198 100644 --- a/datapool/PoolEntry.h +++ b/datapool/PoolEntry.h @@ -1,81 +1,94 @@ #ifndef POOLENTRY_H_ #define POOLENTRY_H_ - #include #include #include +#include + /** - * \brief This is a small helper class that defines a single data pool entry. + * @brief This is a small helper class that defines a single data pool entry. + * @details + * The helper is used to store all information together with the data as a + * single data pool entry.The content's type is defined by the template argument. + * It is prepared for use with plain old data types, but may be extended to + * complex types if necessary. It can be initialized with a certain value, + * size and validity flag. It holds a pointer to the real data and offers + * methods to access this data and to acquire additional information + * (such as validity and array/byte size). It is NOT intended to be used + * outside the DataPool class. * - * \details The helper is used to store all information together with the data as a single data pool entry. - * The content's type is defined by the template argument. - * It is prepared for use with plain old data types, - * but may be extended to complex types if necessary. - * It can be initialized with a certain value, size and validity flag. - * It holds a pointer to the real data and offers methods to access this data and to acquire - * additional information (such as validity and array/byte size). - * It is NOT intended to be used outside the DataPool class. - * - * \ingroup data_pool + * @ingroup data_pool * */ template class PoolEntry : public PoolEntryIF { public: /** - * \brief In the classe's constructor, space is allocated on the heap and + * @brief In the classe's constructor, space is allocated on the heap and * potential init values are copied to that space. - * \param initValue A pointer to the single value or array that holds the init value. - * With the default value (NULL), the entry is initalized with all 0. - * \param set_length Defines the array length of this entry. - * \param set_valid Sets the initialization flag. It is invalid (0) by default. + * @param initValue Initializer list with values to initialize with + * @param set_length Defines the array length of this entry. + * @param set_valid Sets the initialization flag. + * It is invalid (0) by default. */ - PoolEntry( T* initValue = NULL, uint8_t set_length = 1, uint8_t set_valid = 0 ); + PoolEntry(std::initializer_list initValue = {}, uint8_t set_length = 1, + uint8_t set_valid = 0); /** - * \brief The allocated memory for the variable is freed in the destructor. - * \details As the data pool is global, this dtor is only called on program exit. - * PoolEntries shall never be copied, as a copy might delete the variable on the heap. + * @brief In the classe's constructor, space is allocated on the heap and + * potential init values are copied to that space. + * @param initValue A pointer to the single value or array that holds + * the init value. With the default value (nullptr), the entry is + * initalized with all 0. + * @param set_length Defines the array length of this entry. + * @param set_valid Sets the initialization flag. It is invalid (0) by default. + */ + PoolEntry(T* initValue = nullptr, uint8_t set_length = 1, uint8_t set_valid = 0); + + /** + * @brief The allocated memory for the variable is freed in the destructor. + * @details As the data pool is global, this dtor is only called on program exit. + * PoolEntries shall never be copied, as a copy might delete the variable on the heap. */ ~PoolEntry(); /** - * \brief This is the address pointing to the allocated memory. + * @brief This is the address pointing to the allocated memory. */ T* address; /** - * \brief This attribute stores the length information. + * @brief This attribute stores the length information. */ uint8_t length; /** - * \brief Here, the validity information for a variable is stored. + * @brief Here, the validity information for a variable is stored. * Every entry (single variable or vector) has one valid flag. */ uint8_t valid; /** - * \brief getSize returns the array size of the entry. - * \details A single parameter has size 1. + * @brief getSize returns the array size of the entry. + * @details A single parameter has size 1. */ uint8_t getSize(); /** - * \brief This operation returns the size in bytes. - * \details The size is calculated by sizeof(type) * array_size. + * @brief This operation returns the size in bytes. + * @details The size is calculated by sizeof(type) * array_size. */ uint16_t getByteSize(); /** - * \brief This operation returns a the address pointer casted to void*. + * @brief This operation returns a the address pointer casted to void*. */ void* getRawData(); /** - * \brief This method allows to set the valid information of the pool entry. + * @brief This method allows to set the valid information of the pool entry. */ void setValid( uint8_t isValid ); /** - * \brief This method allows to get the valid information of the pool entry. + * @brief This method allows to get the valid information of the pool entry. */ uint8_t getValid(); /** - * \brief This is a debug method that prints all values and the valid information to the screen. - * It prints all array entries in a row. + * @brief This is a debug method that prints all values and the valid + * information to the screen. It prints all array entries in a row. */ void print(); From a159e60a9055e51b6c38a739b1f489e378a30857 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 11 May 2020 16:53:16 +0200 Subject: [PATCH 044/653] removed bool specialization --- datapool/PoolEntry.cpp | 1 - datapool/PoolEntry.h | 7 +++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/datapool/PoolEntry.cpp b/datapool/PoolEntry.cpp index 97c60131..1d8d2486 100644 --- a/datapool/PoolEntry.cpp +++ b/datapool/PoolEntry.cpp @@ -70,7 +70,6 @@ Type PoolEntry::getType() { return PodTypeConversion::type; } -template class PoolEntry; template class PoolEntry; template class PoolEntry; template class PoolEntry; diff --git a/datapool/PoolEntry.h b/datapool/PoolEntry.h index 5edc0198..4487db72 100644 --- a/datapool/PoolEntry.h +++ b/datapool/PoolEntry.h @@ -2,10 +2,10 @@ #define POOLENTRY_H_ #include -#include +#include #include #include - +#include /** * @brief This is a small helper class that defines a single data pool entry. * @details @@ -24,6 +24,9 @@ template class PoolEntry : public PoolEntryIF { public: + static_assert(not std::is_same::value, + "Do not use boolean for the PoolEntry type, use uint8_t instead!" + "Warum? Darum :-)"); /** * @brief In the classe's constructor, space is allocated on the heap and * potential init values are copied to that space. From 1fb87db82e5e5cac6e1933f2fed5cf7066a0822e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 15 May 2020 19:44:14 +0200 Subject: [PATCH 045/653] bugfix and additional functions --- tmtcpacket/SpacePacketBase.cpp | 3 ++- tmtcpacket/pus/TcPacketBase.cpp | 22 +++++++++++++++++----- tmtcpacket/pus/TcPacketBase.h | 20 +++++++++++++++++--- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/tmtcpacket/SpacePacketBase.cpp b/tmtcpacket/SpacePacketBase.cpp index 13c062d8..a06c3a33 100644 --- a/tmtcpacket/SpacePacketBase.cpp +++ b/tmtcpacket/SpacePacketBase.cpp @@ -14,7 +14,8 @@ uint8_t SpacePacketBase::getPacketVersionNumber( void ) { return (this->data->header.packet_id_h & 0b11100000) >> 5; } -void SpacePacketBase::initSpacePacketHeader(bool isTelecommand, bool hasSecondaryHeader, uint16_t apid, uint16_t sequenceCount) { +void SpacePacketBase::initSpacePacketHeader(bool isTelecommand, + bool hasSecondaryHeader, uint16_t apid, uint16_t sequenceCount) { //reset header to zero: memset(data,0, sizeof(this->data->header) ); //Set TC/TM bit. diff --git a/tmtcpacket/pus/TcPacketBase.cpp b/tmtcpacket/pus/TcPacketBase.cpp index 0f3bd52e..b98cf136 100644 --- a/tmtcpacket/pus/TcPacketBase.cpp +++ b/tmtcpacket/pus/TcPacketBase.cpp @@ -28,7 +28,7 @@ const uint8_t* TcPacketBase::getApplicationData() const { return &tcData->data; } -uint16_t TcPacketBase::getApplicationDataSize() { +size_t TcPacketBase::getApplicationDataSize() { return getPacketDataLength() - sizeof(tcData->data_field) - CRC_SIZE + 1; } @@ -46,9 +46,16 @@ void TcPacketBase::setErrorControl() { (&tcData->data)[size + 1] = (crc) & 0X00FF; // CRCL } -void TcPacketBase::setData(const uint8_t* p_Data) { - SpacePacketBase::setData(p_Data); - tcData = (TcPacketPointer*) p_Data; +void TcPacketBase::setData(const uint8_t* pData) { + SpacePacketBase::setData(pData); + tcData = (TcPacketPointer*) pData; +} + +void TcPacketBase::setApplicationData(const uint8_t * pData, size_t dataLen) { + SpacePacketBase::setData(pData); + tcData = (TcPacketPointer*) pData; + SpacePacketBase::setPacketDataLength(dataLen + + sizeof(PUSTcDataFieldHeader) + TcPacketBase::CRC_SIZE-1); } uint8_t TcPacketBase::getSecondaryHeaderFlag() { @@ -72,7 +79,7 @@ void TcPacketBase::initializeTcPacket(uint16_t apid, uint16_t sequenceCount, uint8_t ack, uint8_t service, uint8_t subservice) { initSpacePacketHeader(true, true, apid, sequenceCount); memset(&tcData->data_field, 0, sizeof(tcData->data_field)); - setPacketDataLength(sizeof(tcData->data_field) + CRC_SIZE); + setPacketDataLength(sizeof(PUSTcDataFieldHeader) + CRC_SIZE - 1); //Data Field Header: //Set CCSDS_secondary_header_flag to 0, version number to 001 and ack to 0000 tcData->data_field.version_type_ack = 0b00010000; @@ -80,3 +87,8 @@ void TcPacketBase::initializeTcPacket(uint16_t apid, uint16_t sequenceCount, tcData->data_field.service_type = service; tcData->data_field.service_subtype = subservice; } + +size_t TcPacketBase::calculateFullPacketLength(size_t appDataLen) { + return sizeof(CCSDSPrimaryHeader) + sizeof(PUSTcDataFieldHeader) + + appDataLen + TcPacketBase::CRC_SIZE; +} diff --git a/tmtcpacket/pus/TcPacketBase.h b/tmtcpacket/pus/TcPacketBase.h index e6e6bdad..69c64b87 100644 --- a/tmtcpacket/pus/TcPacketBase.h +++ b/tmtcpacket/pus/TcPacketBase.h @@ -2,6 +2,7 @@ #define TCPACKETBASE_H_ #include +#include /** * This struct defines a byte-wise structured PUS TC Data Field Header. @@ -99,7 +100,8 @@ public: * @param service PUS Service * @param subservice PUS Subservice */ - void initializeTcPacket(uint16_t apid, uint16_t sequenceCount, uint8_t ack, uint8_t service, uint8_t subservice); + void initializeTcPacket(uint16_t apid, uint16_t sequenceCount, uint8_t ack, + uint8_t service, uint8_t subservice); /** * This command returns the CCSDS Secondary Header Flag. * It shall always be zero for PUS Packets. This is the @@ -151,7 +153,7 @@ public: * @return The size of the PUS Application Data (without Error Control * field) */ - uint16_t getApplicationDataSize(); + size_t getApplicationDataSize(); /** * This getter returns the Error Control Field of the packet. * @@ -175,12 +177,24 @@ public: * * @param p_data A pointer to another PUS Telecommand Packet. */ - void setData( const uint8_t* p_data ); + void setData( const uint8_t* pData ); + /** + * Set application data and corresponding length field. + * @param pData + * @param dataLen + */ + void setApplicationData(const uint8_t * pData, size_t dataLen); /** * This is a debugging helper method that prints the whole packet content * to the screen. */ void print(); + /** + * Calculate full packet length from application data length. + * @param appDataLen + * @return + */ + static size_t calculateFullPacketLength(size_t appDataLen); }; From eb5832180b18b5c789ba66c309e5aa5d3771dbc0 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 15 May 2020 19:51:39 +0200 Subject: [PATCH 046/653] size_t uint16_t corrections --- tmtcpacket/SpacePacketBase.cpp | 2 +- tmtcpacket/SpacePacketBase.h | 5 +++-- tmtcpacket/pus/TcPacketBase.cpp | 2 +- tmtcpacket/pus/TcPacketBase.h | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tmtcpacket/SpacePacketBase.cpp b/tmtcpacket/SpacePacketBase.cpp index a06c3a33..b9ae0684 100644 --- a/tmtcpacket/SpacePacketBase.cpp +++ b/tmtcpacket/SpacePacketBase.cpp @@ -82,7 +82,7 @@ void SpacePacketBase::setPacketDataLength( uint16_t new_length) { this->data->header.packet_length_l = ( new_length & 0x00FF ); } -uint32_t SpacePacketBase::getFullSize() { +size_t SpacePacketBase::getFullSize() { //+1 is done because size in packet data length field is: size of data field -1 return this->getPacketDataLength() + sizeof(this->data->header) + 1; } diff --git a/tmtcpacket/SpacePacketBase.h b/tmtcpacket/SpacePacketBase.h index cc68f714..57a5df9c 100644 --- a/tmtcpacket/SpacePacketBase.h +++ b/tmtcpacket/SpacePacketBase.h @@ -2,9 +2,10 @@ #define SPACEPACKETBASE_H_ #include +#include /** - * \defgroup tmtcpackets Space Packets + * @defgroup tmtcpackets Space Packets * This is the group, where all classes associated with Telecommand and * Telemetry packets belong to. * The class hierarchy resembles the dependency between the different standards @@ -167,7 +168,7 @@ public: * This method returns the full raw packet size. * @return The full size of the packet in bytes. */ - uint32_t getFullSize(); + size_t getFullSize(); uint32_t getApidAndSequenceCount() const; diff --git a/tmtcpacket/pus/TcPacketBase.cpp b/tmtcpacket/pus/TcPacketBase.cpp index b98cf136..4ef50c0d 100644 --- a/tmtcpacket/pus/TcPacketBase.cpp +++ b/tmtcpacket/pus/TcPacketBase.cpp @@ -51,7 +51,7 @@ void TcPacketBase::setData(const uint8_t* pData) { tcData = (TcPacketPointer*) pData; } -void TcPacketBase::setApplicationData(const uint8_t * pData, size_t dataLen) { +void TcPacketBase::setApplicationData(const uint8_t * pData, uint16_t dataLen) { SpacePacketBase::setData(pData); tcData = (TcPacketPointer*) pData; SpacePacketBase::setPacketDataLength(dataLen + diff --git a/tmtcpacket/pus/TcPacketBase.h b/tmtcpacket/pus/TcPacketBase.h index 69c64b87..c8342896 100644 --- a/tmtcpacket/pus/TcPacketBase.h +++ b/tmtcpacket/pus/TcPacketBase.h @@ -183,7 +183,7 @@ public: * @param pData * @param dataLen */ - void setApplicationData(const uint8_t * pData, size_t dataLen); + void setApplicationData(const uint8_t * pData, uint16_t dataLen); /** * This is a debugging helper method that prints the whole packet content * to the screen. From 1c967d473933a3262ac9f74a0bdc1914d54b6aeb Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 15 May 2020 19:56:21 +0200 Subject: [PATCH 047/653] app data size uint16_t --- tmtcpacket/pus/TcPacketBase.cpp | 2 +- tmtcpacket/pus/TcPacketBase.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tmtcpacket/pus/TcPacketBase.cpp b/tmtcpacket/pus/TcPacketBase.cpp index 4ef50c0d..f8dba79f 100644 --- a/tmtcpacket/pus/TcPacketBase.cpp +++ b/tmtcpacket/pus/TcPacketBase.cpp @@ -28,7 +28,7 @@ const uint8_t* TcPacketBase::getApplicationData() const { return &tcData->data; } -size_t TcPacketBase::getApplicationDataSize() { +uint16_t TcPacketBase::getApplicationDataSize() { return getPacketDataLength() - sizeof(tcData->data_field) - CRC_SIZE + 1; } diff --git a/tmtcpacket/pus/TcPacketBase.h b/tmtcpacket/pus/TcPacketBase.h index c8342896..136aaa0b 100644 --- a/tmtcpacket/pus/TcPacketBase.h +++ b/tmtcpacket/pus/TcPacketBase.h @@ -153,7 +153,7 @@ public: * @return The size of the PUS Application Data (without Error Control * field) */ - size_t getApplicationDataSize(); + uint16_t getApplicationDataSize(); /** * This getter returns the Error Control Field of the packet. * From 4819bad402e7a6b1c596aeff89c630e60bfeeaf1 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 15 May 2020 20:01:11 +0200 Subject: [PATCH 048/653] addtional comment --- tmtcpacket/pus/TcPacketBase.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tmtcpacket/pus/TcPacketBase.cpp b/tmtcpacket/pus/TcPacketBase.cpp index f8dba79f..0972ffff 100644 --- a/tmtcpacket/pus/TcPacketBase.cpp +++ b/tmtcpacket/pus/TcPacketBase.cpp @@ -52,10 +52,10 @@ void TcPacketBase::setData(const uint8_t* pData) { } void TcPacketBase::setApplicationData(const uint8_t * pData, uint16_t dataLen) { - SpacePacketBase::setData(pData); - tcData = (TcPacketPointer*) pData; + setData(pData); + // packet data length is actual size of data field minus 1 SpacePacketBase::setPacketDataLength(dataLen + - sizeof(PUSTcDataFieldHeader) + TcPacketBase::CRC_SIZE-1); + sizeof(PUSTcDataFieldHeader) + TcPacketBase::CRC_SIZE - 1); } uint8_t TcPacketBase::getSecondaryHeaderFlag() { From b8e7b12a63b35262cf5616a0afe4b7abc05b4ac6 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 17 May 2020 13:10:09 +0200 Subject: [PATCH 049/653] commented whole SWITCH IO BOARD block --- devicehandlers/DeviceHandlerBase.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 068fdd78..84dd0811 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -1049,19 +1049,19 @@ ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage( } replyReturnvalueToCommand(RETURN_OK); return RETURN_OK; - case DeviceHandlerMessage::CMD_SWITCH_IOBOARD: +// case DeviceHandlerMessage::CMD_SWITCH_IOBOARD: // if (mode != MODE_OFF) { // replyReturnvalueToCommand(WRONG_MODE_FOR_COMMAND); // } else { -//// result = switchCookieChannel( -//// DeviceHandlerMessage::getIoBoardObjectId(message)); +// result = switchCookieChannel( +// DeviceHandlerMessage::getIoBoardObjectId(message)); // if (result == RETURN_OK) { // replyReturnvalueToCommand(RETURN_OK); // } else { // replyReturnvalueToCommand(CANT_SWITCH_IO_ADDRESS); // } // } - return RETURN_OK; +// return RETURN_OK; case DeviceHandlerMessage::CMD_RAW: if ((mode != MODE_RAW)) { DeviceHandlerMessage::clear(message); From fb0834ffe14b44a88fa32a25b3366def4dc25a3e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 17 May 2020 15:28:00 +0200 Subject: [PATCH 050/653] added cookie caching and deletion --- devicehandlers/DeviceHandlerBase.cpp | 6 ++++-- devicehandlers/DeviceHandlerBase.h | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 84dd0811..b12d797a 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -23,8 +23,9 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, size_t cmdQueueSize) : SystemObject(setObjectId), mode(MODE_OFF), submode(SUBMODE_NONE), wiretappingMode(OFF), storedRawData(StorageManagerIF::INVALID_ADDRESS), - deviceCommunicationId(deviceCommunication), deviceThermalStatePoolId( - thermalStatePoolId),deviceThermalRequestPoolId(thermalRequestPoolId), + deviceCommunicationId(deviceCommunication), comCookie(comCookie), + deviceThermalStatePoolId(thermalStatePoolId), + deviceThermalRequestPoolId(thermalRequestPoolId), healthHelper(this,setObjectId), modeHelper(this), parameterHelper(this), childTransitionFailure(RETURN_OK), fdirInstance(fdirInstance), hkSwitcher(this), defaultFDIRUsed(fdirInstance == nullptr), @@ -44,6 +45,7 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, DeviceHandlerBase::~DeviceHandlerBase() { //communicationInterface->close(cookie); + delete comCookie; if (defaultFDIRUsed) { delete fdirInstance; } diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 379992b1..3d13f1e3 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -606,12 +606,12 @@ protected: /** * Communication object used for device communication */ - DeviceCommunicationIF *communicationInterface = nullptr; + DeviceCommunicationIF * communicationInterface = nullptr; /** * Cookie used for communication */ - CookieIF * comCookie = nullptr; + CookieIF * comCookie; struct DeviceCommandInfo { bool isExecuting; //!< Indicates if the command is already executing. From 7ceb6f3c96914bd1ebea5532f21bee6dd17b3f20 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 17 May 2020 15:43:45 +0200 Subject: [PATCH 051/653] override for executeAction() --- devicehandlers/DeviceHandlerBase.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 3d13f1e3..38af3020 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -482,7 +482,8 @@ public: virtual void setParentQueue(MessageQueueId_t parentQueueId); ReturnValue_t executeAction(ActionId_t actionId, - MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size); + MessageQueueId_t commandedBy, const uint8_t* data, + uint32_t size) override; Mode_t getTransitionSourceMode() const; Submode_t getTransitionSourceSubMode() const; virtual void getMode(Mode_t *mode, Submode_t *submode); From f4ad38f07ffd873b70076bfac26d4ece6baeaefc Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 17 May 2020 15:47:17 +0200 Subject: [PATCH 052/653] replyMap insertion improvements --- devicehandlers/DeviceHandlerBase.cpp | 11 ++++------- devicehandlers/DeviceHandlerBase.h | 2 ++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index b12d797a..f58fab18 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -354,8 +354,8 @@ ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId, info.delayCycles = 0; info.replyLen = replyLen; info.command = deviceCommandMap.end(); - std::pair result = deviceReplyMap.emplace(replyId, info); - if (result.second) { + auto resultPair = deviceReplyMap.emplace(replyId, info); + if (resultPair.second) { return RETURN_OK; } else { return RETURN_FAILED; @@ -367,11 +367,8 @@ ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceComm info.expectedReplies = 0; info.isExecuting = false; info.sendReplyTo = NO_COMMANDER; - std::pair::iterator, bool> returnValue; - returnValue = deviceCommandMap.insert( - std::pair(deviceCommand, - info)); - if (returnValue.second) { + auto resultPair = deviceCommandMap.emplace(deviceCommand, info); + if (resultPair.second) { return RETURN_OK; } else { return RETURN_FAILED; diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 38af3020..56f9be1d 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -481,9 +481,11 @@ public: */ virtual void setParentQueue(MessageQueueId_t parentQueueId); + /** @brief Implementation required for HasActionIF */ ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size) override; + Mode_t getTransitionSourceMode() const; Submode_t getTransitionSourceSubMode() const; virtual void getMode(Mode_t *mode, Submode_t *submode); From deb8ce3744c9c2962c19310f5092bf547a016d8a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 17 May 2020 15:53:29 +0200 Subject: [PATCH 053/653] merged upstream master --- devicehandlers/DeviceHandlerBase.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 0fd2a601..fa06a93a 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -44,7 +44,6 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, } DeviceHandlerBase::~DeviceHandlerBase() { - //communicationInterface->close(cookie); delete comCookie; if (defaultFDIRUsed) { delete fdirInstance; From 80c6eff8a6fd543b5151716a21e392639367a246 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 17 May 2020 17:46:27 +0200 Subject: [PATCH 054/653] added error output for passed nullptr cookie --- devicehandlers/DeviceHandlerBase.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index fa06a93a..ac9d15c1 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -37,6 +37,12 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, CommandMessage::MAX_MESSAGE_SIZE); cookieInfo.state = COOKIE_UNUSED; insertInCommandMap(RAW_COMMAND_ID); + if (comCookie == nullptr) { + sif::error << "DeviceHandlerBase: ObjectID 0x" << std::hex << + this->getObjectId() << std::dec << ": Do not pass nullptr as a" + " cookie, consider passing a dummy cookie instead!" << + std::endl; + } if (this->fdirInstance == nullptr) { this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, defaultFDIRParentId); From 0bf8e97830f3c6ec2de91935091389890bec44ac Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 17 May 2020 17:49:32 +0200 Subject: [PATCH 055/653] better error output for invalid passed cookie --- devicehandlers/DeviceHandlerBase.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index ac9d15c1..f52ddbad 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -12,6 +12,8 @@ #include #include +#include + object_id_t DeviceHandlerBase::powerSwitcherId = 0; object_id_t DeviceHandlerBase::rawDataReceiverId = 0; object_id_t DeviceHandlerBase::defaultFDIRParentId = 0; @@ -39,9 +41,9 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, insertInCommandMap(RAW_COMMAND_ID); if (comCookie == nullptr) { sif::error << "DeviceHandlerBase: ObjectID 0x" << std::hex << - this->getObjectId() << std::dec << ": Do not pass nullptr as a" - " cookie, consider passing a dummy cookie instead!" << - std::endl; + std::setw(8) << std::setfill('0') << this->getObjectId() << + std::dec << ": Do not pass nullptr as a cookie, consider " + "passing a dummy cookie instead!" << std::endl; } if (this->fdirInstance == nullptr) { this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, From df7be467eb1885c35527aabbe9c47678457dc41f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 17 May 2020 17:54:21 +0200 Subject: [PATCH 056/653] nullptr replacements --- devicehandlers/DeviceHandlerBase.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index f52ddbad..338ed9b2 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -653,8 +653,8 @@ ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, uint8_t * *data, uint32_t * len) { uint32_t lenTmp; - if (IPCStore == NULL) { - *data = NULL; + if (IPCStore == nullptr) { + *data = nullptr; *len = 0; return RETURN_FAILED; } @@ -665,7 +665,7 @@ ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, } else { triggerEvent(StorageManagerIF::GET_DATA_FAILED, result, storageAddress.raw); - *data = NULL; + *data = nullptr; *len = 0; return result; } From 7bc7e06277b95a3ee39ecc6339daa359b1cdfb4b Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 18 May 2020 16:41:37 +0200 Subject: [PATCH 057/653] added reordering of ctor arguments --- tmtcpacket/pus/TcPacketStored.cpp | 18 +++++++++--------- tmtcpacket/pus/TcPacketStored.h | 4 +++- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/tmtcpacket/pus/TcPacketStored.cpp b/tmtcpacket/pus/TcPacketStored.cpp index 81eb7f99..57b90bcc 100644 --- a/tmtcpacket/pus/TcPacketStored.cpp +++ b/tmtcpacket/pus/TcPacketStored.cpp @@ -1,22 +1,22 @@ #include #include #include -#include +#include TcPacketStored::TcPacketStored(store_address_t setAddress) : - TcPacketBase(NULL), storeAddress(setAddress) { + TcPacketBase(nullptr), storeAddress(setAddress) { this->setStoreAddress(this->storeAddress); } -TcPacketStored::TcPacketStored(uint16_t apid, uint8_t ack, uint8_t service, - uint8_t subservice, uint8_t sequence_count, const uint8_t* data, - uint32_t size) : - TcPacketBase(NULL) { +TcPacketStored::TcPacketStored(uint8_t service, uint8_t subservice, + uint16_t apid, uint8_t sequence_count, const uint8_t* data, + size_t size, uint8_t ack ) : + TcPacketBase(nullptr) { this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; if (!this->checkAndSetStore()) { return; } - uint8_t* p_data = NULL; + uint8_t* p_data = nullptr; ReturnValue_t returnValue = this->store->getFreeElement(&this->storeAddress, (TC_PACKET_MIN_SIZE + size), &p_data); if (returnValue != this->store->RETURN_OK) { @@ -59,7 +59,7 @@ bool TcPacketStored::checkAndSetStore() { void TcPacketStored::setStoreAddress(store_address_t setAddress) { this->storeAddress = setAddress; const uint8_t* temp_data = NULL; - uint32_t temp_size; + size_t temp_size; ReturnValue_t status = StorageManagerIF::RETURN_FAILED; if (this->checkAndSetStore()) { status = this->store->getData(this->storeAddress, &temp_data, @@ -79,7 +79,7 @@ store_address_t TcPacketStored::getStoreAddress() { bool TcPacketStored::isSizeCorrect() { const uint8_t* temp_data = NULL; - uint32_t temp_size; + size_t temp_size; ReturnValue_t status = this->store->getData(this->storeAddress, &temp_data, &temp_size); if (status == StorageManagerIF::RETURN_OK) { diff --git a/tmtcpacket/pus/TcPacketStored.h b/tmtcpacket/pus/TcPacketStored.h index c57f0e0f..a9c49c2e 100644 --- a/tmtcpacket/pus/TcPacketStored.h +++ b/tmtcpacket/pus/TcPacketStored.h @@ -64,7 +64,9 @@ public: * @param data The data to be copied to the Application Data Field. * @param size The amount of data to be copied. */ - TcPacketStored( uint16_t apid, uint8_t ack, uint8_t service, uint8_t subservice, uint8_t sequence_count = 0, const uint8_t* data = NULL, uint32_t size = 0 ); + TcPacketStored( uint8_t service, uint8_t subservice, uint16_t apid, + uint8_t sequence_count = 0, const uint8_t* data = nullptr, + size_t size = 0, uint8_t ack = TcPacketBase::ACK_ALL ); /** * Another constructor to create a TcPacket from a raw packet stream. * Takes the data and adds it unchecked to the TcStore. From 483a47d353219a4a6af1fd36c08ddd55a2bcf3d4 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 19 May 2020 18:55:13 +0200 Subject: [PATCH 058/653] some renamings --- tmtcpacket/pus/TcPacketBase.cpp | 30 +++++++++++++++--------------- tmtcpacket/pus/TcPacketBase.h | 4 ++-- tmtcpacket/pus/TcPacketStored.cpp | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tmtcpacket/pus/TcPacketBase.cpp b/tmtcpacket/pus/TcPacketBase.cpp index 0972ffff..32caf5bb 100644 --- a/tmtcpacket/pus/TcPacketBase.cpp +++ b/tmtcpacket/pus/TcPacketBase.cpp @@ -13,28 +13,28 @@ TcPacketBase::~TcPacketBase() { } uint8_t TcPacketBase::getService() { - return tcData->data_field.service_type; + return tcData->dataField.service_type; } uint8_t TcPacketBase::getSubService() { - return tcData->data_field.service_subtype; + return tcData->dataField.service_subtype; } uint8_t TcPacketBase::getAcknowledgeFlags() { - return tcData->data_field.version_type_ack & 0b00001111; + return tcData->dataField.version_type_ack & 0b00001111; } const uint8_t* TcPacketBase::getApplicationData() const { - return &tcData->data; + return &tcData->appData; } uint16_t TcPacketBase::getApplicationDataSize() { - return getPacketDataLength() - sizeof(tcData->data_field) - CRC_SIZE + 1; + return getPacketDataLength() - sizeof(tcData->dataField) - CRC_SIZE + 1; } uint16_t TcPacketBase::getErrorControl() { uint16_t size = getApplicationDataSize() + CRC_SIZE; - uint8_t* p_to_buffer = &tcData->data; + uint8_t* p_to_buffer = &tcData->appData; return (p_to_buffer[size - 2] << 8) + p_to_buffer[size - 1]; } @@ -42,8 +42,8 @@ void TcPacketBase::setErrorControl() { uint32_t full_size = getFullSize(); uint16_t crc = CRC::crc16ccitt(getWholeData(), full_size - CRC_SIZE); uint32_t size = getApplicationDataSize(); - (&tcData->data)[size] = (crc & 0XFF00) >> 8; // CRCH - (&tcData->data)[size + 1] = (crc) & 0X00FF; // CRCL + (&tcData->appData)[size] = (crc & 0XFF00) >> 8; // CRCH + (&tcData->appData)[size + 1] = (crc) & 0X00FF; // CRCL } void TcPacketBase::setData(const uint8_t* pData) { @@ -59,11 +59,11 @@ void TcPacketBase::setApplicationData(const uint8_t * pData, uint16_t dataLen) { } uint8_t TcPacketBase::getSecondaryHeaderFlag() { - return (tcData->data_field.version_type_ack & 0b10000000) >> 7; + return (tcData->dataField.version_type_ack & 0b10000000) >> 7; } uint8_t TcPacketBase::getPusVersionNumber() { - return (tcData->data_field.version_type_ack & 0b01110000) >> 4; + return (tcData->dataField.version_type_ack & 0b01110000) >> 4; } void TcPacketBase::print() { @@ -78,14 +78,14 @@ void TcPacketBase::print() { void TcPacketBase::initializeTcPacket(uint16_t apid, uint16_t sequenceCount, uint8_t ack, uint8_t service, uint8_t subservice) { initSpacePacketHeader(true, true, apid, sequenceCount); - memset(&tcData->data_field, 0, sizeof(tcData->data_field)); + memset(&tcData->dataField, 0, sizeof(tcData->dataField)); setPacketDataLength(sizeof(PUSTcDataFieldHeader) + CRC_SIZE - 1); //Data Field Header: //Set CCSDS_secondary_header_flag to 0, version number to 001 and ack to 0000 - tcData->data_field.version_type_ack = 0b00010000; - tcData->data_field.version_type_ack |= (ack & 0x0F); - tcData->data_field.service_type = service; - tcData->data_field.service_subtype = subservice; + tcData->dataField.version_type_ack = 0b00010000; + tcData->dataField.version_type_ack |= (ack & 0x0F); + tcData->dataField.service_type = service; + tcData->dataField.service_subtype = subservice; } size_t TcPacketBase::calculateFullPacketLength(size_t appDataLen) { diff --git a/tmtcpacket/pus/TcPacketBase.h b/tmtcpacket/pus/TcPacketBase.h index 136aaa0b..9b858bd9 100644 --- a/tmtcpacket/pus/TcPacketBase.h +++ b/tmtcpacket/pus/TcPacketBase.h @@ -24,8 +24,8 @@ struct PUSTcDataFieldHeader { */ struct TcPacketPointer { CCSDSPrimaryHeader primary; - PUSTcDataFieldHeader data_field; - uint8_t data; + PUSTcDataFieldHeader dataField; + uint8_t appData; }; /** diff --git a/tmtcpacket/pus/TcPacketStored.cpp b/tmtcpacket/pus/TcPacketStored.cpp index 57b90bcc..47cf2ecd 100644 --- a/tmtcpacket/pus/TcPacketStored.cpp +++ b/tmtcpacket/pus/TcPacketStored.cpp @@ -24,7 +24,7 @@ TcPacketStored::TcPacketStored(uint8_t service, uint8_t subservice, } this->setData(p_data); initializeTcPacket(apid, sequence_count, ack, service, subservice); - memcpy(&tcData->data, data, size); + memcpy(&tcData->appData, data, size); this->setPacketDataLength( size + sizeof(PUSTcDataFieldHeader) + CRC_SIZE - 1); this->setErrorControl(); From 7bc29fc2d5c90e3f2ce9888e39cb4fcf7f380771 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 19 May 2020 19:00:33 +0200 Subject: [PATCH 059/653] souce data setter function --- tmtcpacket/pus/TmPacketBase.cpp | 5 +++++ tmtcpacket/pus/TmPacketBase.h | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/tmtcpacket/pus/TmPacketBase.cpp b/tmtcpacket/pus/TmPacketBase.cpp index a7bda5af..a2c27ce1 100644 --- a/tmtcpacket/pus/TmPacketBase.cpp +++ b/tmtcpacket/pus/TmPacketBase.cpp @@ -102,6 +102,11 @@ void TmPacketBase::initializeTmPacket(uint16_t apid, uint8_t service, uint8_t su } } +void TmPacketBase::setSourceData(uint8_t* sourceData, size_t sourceSize) { + memcpy(getSourceData(), sourceData, sourceSize); + setSourceDataSize(sourceSize); +} + void TmPacketBase::setSourceDataSize(uint16_t size) { setPacketDataLength(size + sizeof(PUSTmDataFieldHeader) + CRC_SIZE - 1); } diff --git a/tmtcpacket/pus/TmPacketBase.h b/tmtcpacket/pus/TmPacketBase.h index d03beba5..583a5495 100644 --- a/tmtcpacket/pus/TmPacketBase.h +++ b/tmtcpacket/pus/TmPacketBase.h @@ -125,6 +125,13 @@ public: * current content of the packet. */ void setErrorControl(); + /** + * This sets the source data. It copies the provided data to + * the internal TmPacketPointer. + * @param sourceData + * @param sourceSize + */ + void setSourceData(uint8_t* sourceData, size_t sourceSize); /** * With this method, the packet data pointer can be redirected to another * location. From 730c7151202160afceac06792d151cc10a698ee4 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 19 May 2020 19:01:25 +0200 Subject: [PATCH 060/653] doc improved --- tmtcpacket/pus/TmPacketBase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmtcpacket/pus/TmPacketBase.h b/tmtcpacket/pus/TmPacketBase.h index 583a5495..6f3c4b59 100644 --- a/tmtcpacket/pus/TmPacketBase.h +++ b/tmtcpacket/pus/TmPacketBase.h @@ -127,7 +127,7 @@ public: void setErrorControl(); /** * This sets the source data. It copies the provided data to - * the internal TmPacketPointer. + * the internal TmPacketPointer source data location. * @param sourceData * @param sourceSize */ From 331b36fe18024698912910d13bf2a3d6c3580889 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 19 May 2020 19:05:17 +0200 Subject: [PATCH 061/653] fixed setAppData function --- tmtcpacket/pus/TcPacketBase.cpp | 7 +++---- tmtcpacket/pus/TcPacketBase.h | 15 +++++++++------ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/tmtcpacket/pus/TcPacketBase.cpp b/tmtcpacket/pus/TcPacketBase.cpp index 32caf5bb..733c36df 100644 --- a/tmtcpacket/pus/TcPacketBase.cpp +++ b/tmtcpacket/pus/TcPacketBase.cpp @@ -51,11 +51,10 @@ void TcPacketBase::setData(const uint8_t* pData) { tcData = (TcPacketPointer*) pData; } -void TcPacketBase::setApplicationData(const uint8_t * pData, uint16_t dataLen) { - setData(pData); - // packet data length is actual size of data field minus 1 +void TcPacketBase::setAppData(uint8_t * appData, uint16_t dataLen) { + memcpy(&tcData->appData, appData, dataLen); SpacePacketBase::setPacketDataLength(dataLen + - sizeof(PUSTcDataFieldHeader) + TcPacketBase::CRC_SIZE - 1); + sizeof(PUSTcDataFieldHeader) + TcPacketBase::CRC_SIZE - 1); } uint8_t TcPacketBase::getSecondaryHeaderFlag() { diff --git a/tmtcpacket/pus/TcPacketBase.h b/tmtcpacket/pus/TcPacketBase.h index 9b858bd9..73076176 100644 --- a/tmtcpacket/pus/TcPacketBase.h +++ b/tmtcpacket/pus/TcPacketBase.h @@ -168,6 +168,14 @@ public: * current content of the packet. */ void setErrorControl(); + + /** + * Copies the supplied data to the internal TC application data field. + * @param pData + * @param dataLen + */ + void setAppData(uint8_t * appData, uint16_t dataLen); + /** * With this method, the packet data pointer can be redirected to another * location. @@ -178,12 +186,7 @@ public: * @param p_data A pointer to another PUS Telecommand Packet. */ void setData( const uint8_t* pData ); - /** - * Set application data and corresponding length field. - * @param pData - * @param dataLen - */ - void setApplicationData(const uint8_t * pData, uint16_t dataLen); + /** * This is a debugging helper method that prints the whole packet content * to the screen. From ca10020f190783821077ee281d7f1c56284fa6ab Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 19 May 2020 20:29:37 +0200 Subject: [PATCH 062/653] added getter function for tc packet stored --- tmtcpacket/pus/TcPacketStored.cpp | 12 ++++++++++++ tmtcpacket/pus/TcPacketStored.h | 13 +++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/tmtcpacket/pus/TcPacketStored.cpp b/tmtcpacket/pus/TcPacketStored.cpp index 47cf2ecd..64aa74dc 100644 --- a/tmtcpacket/pus/TcPacketStored.cpp +++ b/tmtcpacket/pus/TcPacketStored.cpp @@ -1,6 +1,7 @@ #include #include #include + #include TcPacketStored::TcPacketStored(store_address_t setAddress) : @@ -20,6 +21,8 @@ TcPacketStored::TcPacketStored(uint8_t service, uint8_t subservice, ReturnValue_t returnValue = this->store->getFreeElement(&this->storeAddress, (TC_PACKET_MIN_SIZE + size), &p_data); if (returnValue != this->store->RETURN_OK) { + sif::warning << "TcPacketStored: Could not get free element from store!" + << std::endl; return; } this->setData(p_data); @@ -30,6 +33,15 @@ TcPacketStored::TcPacketStored(uint8_t service, uint8_t subservice, this->setErrorControl(); } +ReturnValue_t TcPacketStored::getData(const uint8_t ** dataPtr, + size_t* dataSize) { + auto result = this->store->getData(storeAddress, dataPtr, dataSize); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "TcPacketStored: Could not get data!" << std::endl; + } + return result; +} + TcPacketStored::TcPacketStored() : TcPacketBase(NULL) { this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; diff --git a/tmtcpacket/pus/TcPacketStored.h b/tmtcpacket/pus/TcPacketStored.h index a9c49c2e..4ce95ddd 100644 --- a/tmtcpacket/pus/TcPacketStored.h +++ b/tmtcpacket/pus/TcPacketStored.h @@ -74,10 +74,19 @@ public: * @param Size size of the packet. */ TcPacketStored( const uint8_t* data, uint32_t size); + + /** + * Getter function for the raw data. + * @param dataPtr [out] Pointer to the data pointer to set + * @param dataSize [out] Address of size to set. + * @return -@c RETURN_OK if data was retrieved successfully. + */ + ReturnValue_t getData(const uint8_t ** dataPtr, + size_t* dataSize); /** * This is a getter for the current store address of the packet. - * @return The current store address. The (raw) value is \c StorageManagerIF::INVALID_ADDRESS if - * the packet is not linked. + * @return The current store address. The (raw) value is + * @c StorageManagerIF::INVALID_ADDRESS if the packet is not linked. */ store_address_t getStoreAddress(); /** From 7eb250a90ab432b8a5e5d10f78ec7598f13cdd45 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 25 May 2020 15:06:54 +0200 Subject: [PATCH 063/653] include testing --- osal/FreeRTOS/Clock.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osal/FreeRTOS/Clock.cpp b/osal/FreeRTOS/Clock.cpp index 5e597f25..a672076a 100644 --- a/osal/FreeRTOS/Clock.cpp +++ b/osal/FreeRTOS/Clock.cpp @@ -4,8 +4,7 @@ #include "Timekeeper.h" extern "C" { -#include -#include +#include } From 35b9346c2bface422ad7943d66689a8c7da21ed0 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 25 May 2020 15:25:17 +0200 Subject: [PATCH 064/653] include improvements for clock, sif fixes --- osal/FreeRTOS/Clock.cpp | 1 + timemanager/Stopwatch.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/osal/FreeRTOS/Clock.cpp b/osal/FreeRTOS/Clock.cpp index a672076a..82c9e170 100644 --- a/osal/FreeRTOS/Clock.cpp +++ b/osal/FreeRTOS/Clock.cpp @@ -5,6 +5,7 @@ extern "C" { #include +#include } diff --git a/timemanager/Stopwatch.cpp b/timemanager/Stopwatch.cpp index 771b63dc..2c85376d 100644 --- a/timemanager/Stopwatch.cpp +++ b/timemanager/Stopwatch.cpp @@ -25,11 +25,11 @@ seconds_t Stopwatch::stopSeconds() { void Stopwatch::display() { if(displayMode == StopwatchDisplayMode::MILLIS) { - info << "Stopwatch: Operation took " << (elapsedTime.tv_sec * 1000 + + sif::info << "Stopwatch: Operation took " << (elapsedTime.tv_sec * 1000 + elapsedTime.tv_usec / 1000) << " milliseconds" << std::endl; } else if(displayMode == StopwatchDisplayMode::SECONDS) { - info <<"Stopwatch: Operation took " << std::setprecision(3) + sif::info <<"Stopwatch: Operation took " << std::setprecision(3) << std::fixed << timevalOperations::toDouble(elapsedTime) << " seconds" << std::endl; } From 19b4332801baa3aa427e330cc712eaa8910decca Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 25 May 2020 23:16:46 +0200 Subject: [PATCH 065/653] some little tweaks --- devicehandlers/DeviceHandlerIF.h | 128 ++++++++++++++++++++----------- 1 file changed, 85 insertions(+), 43 deletions(-) diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index 04e94613..aec0e796 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -2,11 +2,10 @@ #define DEVICEHANDLERIF_H_ #include -#include -#include #include #include - +#include +#include /** * @brief This is the Interface used to communicate with a device handler. @@ -29,19 +28,57 @@ public: // 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. - static const Mode_t MODE_RAW = 3; //!< The device is powered on and ready to perform operations. In this mode, raw commands can be sent. The device handler will send all replies received from the command back to the commanding object. - 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; //!< It is possible to set the mode to _MODE_TO_ON to use the to on transition if available. + //! 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. + static const Mode_t MODE_NORMAL = 2; + //! The device is powered on and ready to perform operations. In this mode, + //! raw commands can be sent. The device handler will send all replies + //! received from the command back to the commanding object. + static const Mode_t MODE_RAW = 3; + //! 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_ERROR_ON = 4; + //! 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_START_UP = TRANSITION_MODE_CHILD_ACTION_MASK | 5; + //! 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_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6; + //! 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_ON = TRANSITION_MODE_CHILD_ACTION_MASK | HasModesIF::MODE_ON; + //! It is possible to set the mode to _MODE_TO_RAW to use the to raw + //! transition if available. static const Mode_t _MODE_TO_RAW = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_RAW; + //! It is possible to set the mode to _MODE_TO_NORMAL to use the to normal + //! transition if available. 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 - static const Mode_t _MODE_POWER_ON = TRANSITION_MODE_BASE_ACTION_MASK | 2; //!< This is a transitional state which can not be commanded. The device will be switched on in this state. After the command to set the switch on has been sent, the mode changes to @c MODE_WAIT_ON - static const Mode_t _MODE_WAIT_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 3; //!< This is a transitional state which can not be commanded. The switch has been commanded off and the handler waits for it to be off. When the switch is off, the mode changes to @c MODE_OFF. - static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4; //!< This is a transitional state which can not be commanded. The switch has been commanded on and the handler waits for it to be on. When the switch is on, the mode changes to @c MODE_TO_ON. - static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5; //!< This is a transitional state which can not be commanded. The switch has been commanded off and is off now. This state is only to do an RMAP cycle once more where the doSendRead() function will set the mode to MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board + //! 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 + 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 + //! will be switched on in this state. After the command to set the switch + //! on has been sent, the mode changes to @c MODE_WAIT_ON. + static const Mode_t _MODE_POWER_ON = TRANSITION_MODE_BASE_ACTION_MASK | 2; + //! This is a transitional state which can not be commanded. The switch has + //! been commanded off and the handler waits for it to be off. + //! When the switch is off, the mode changes to @c MODE_OFF. + static const Mode_t _MODE_WAIT_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 3; + //! This is a transitional state which can not be commanded. The switch + //! has been commanded on and the handler waits for it to be on. + //! When the switch is on, the mode changes to @c MODE_TO_ON. + static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4; + //! This is a transitional state which can not be commanded. The switch has + //! been commanded off and is off now. This state is only to do an RMAP + //! cycle once more where the doSendRead() function will set the mode to + //! MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board. + static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5; static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CDH; static const Event DEVICE_BUILDING_COMMAND_FAILED = MAKE_EVENT(0, SEVERITY::LOW); @@ -57,37 +94,47 @@ public: static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, SEVERITY::HIGH); static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF; - // Standard error codes when handling or building commands. - 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); - static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3); - static const ReturnValue_t CANT_SWITCH_IO_ADDRESS = MAKE_RETURN_CODE(0xA4); - static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA5); - static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA6); - 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 error codes used in scan for reply - //static const ReturnValue_t TOO_SHORT = MAKE_RETURN_CODE(0xB1); - static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB2); - static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB3); - static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB4); - static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB5); + // Standard codes used when building commands. + static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(0xA0); //!< Return this if no command sending in required + // Mostly used for internal handling. + static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA2); //!< If the command size is 0. Checked in DHB + static const ReturnValue_t NO_REPLY_EXPECTED = MAKE_RETURN_CODE(0xA3); //!< Used to indicate that this is a command-only command. + static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA4); //!< Command ID not in commandMap. Checked in DHB + static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA5); //!< Command was already executed. Checked in DHB + static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA6); + static const ReturnValue_t CANT_SWITCH_ADDRESS = MAKE_RETURN_CODE(0xA7); + static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA8); + static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA9); + static const ReturnValue_t BUSY = MAKE_RETURN_CODE(0xAA); + static const ReturnValue_t NON_OP_TEMPERATURE = MAKE_RETURN_CODE(0xAB); + static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xAC); - // Standard error codes used in interpret device reply + // Standard codes used in scanForReply + static const ReturnValue_t APERIODIC_REPLY = MAKE_RETURN_CODE(0xB1); //!< This is used to specify for replies from a device which are not replies to requests + static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB2); + static const ReturnValue_t IGNORE_REPLY_DATA = MAKE_RETURN_CODE(0xB3); //!< Ignore parts of the received packet + static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE(0xB4); //!< Ignore full received packet + static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB5); + static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB6); + static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB7); + + // Standard codes used in interpretDeviceReply static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC1); //the device reported, that it did not execute the command static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC2); static const ReturnValue_t UNKNOW_DEVICE_REPLY = MAKE_RETURN_CODE(0xC3); //the deviceCommandId reported by scanforReply is unknown static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC4); //syntax etc is correct but still not ok, eg parameters where none are expected - // Standard error codes used in buildCommandFromCommand - static const ReturnValue_t INVALID_COMMAND_PARAMETER = MAKE_RETURN_CODE( - 0xD0); - static const ReturnValue_t INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS = - MAKE_RETURN_CODE(0xD1); + // Standard codes used in buildCommandFromCommand + static const ReturnValue_t INVALID_COMMAND_PARAMETER = MAKE_RETURN_CODE(0xD0); + static const ReturnValue_t INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS = MAKE_RETURN_CODE(0xD1); + + // Standard codes used in getSwitches + static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(0xE1); //!< Return in getSwitches() to specify there are no switches + + // static const ReturnValue_t ONE_SWITCH = MAKE_RETURN_CODE(8); + // static const ReturnValue_t TWO_SWITCHES = MAKE_RETURN_CODE(9); + // static const ReturnValue_t COMMAND_MAP_ERROR = MAKE_RETURN_CODE(11); /** * Communication action that will be executed. @@ -109,11 +156,6 @@ public: /** * This MessageQueue is used to command the device handler. - * - * To command a device handler, a DeviceHandlerCommandMessage can be - * sent to this Queue. The handler replies with a - * DeviceHandlerCommandMessage containing the DeviceHandlerCommand_t reply. - * * @return the id of the MessageQueue */ virtual MessageQueueId_t getCommandQueue() const = 0; From 98449ddc7fbb7a10a4052d3393ec721adbd81d26 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 25 May 2020 23:17:15 +0200 Subject: [PATCH 066/653] comment removed --- devicehandlers/DeviceHandlerIF.h | 1 - 1 file changed, 1 deletion(-) diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index aec0e796..e2a5138d 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -97,7 +97,6 @@ public: // Standard codes used when building commands. static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(0xA0); //!< Return this if no command sending in required - // Mostly used for internal handling. static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA2); //!< If the command size is 0. Checked in DHB static const ReturnValue_t NO_REPLY_EXPECTED = MAKE_RETURN_CODE(0xA3); //!< Used to indicate that this is a command-only command. static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA4); //!< Command ID not in commandMap. Checked in DHB From 112779d91ffbcca1937e813d76f5381d46703aaf Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 25 May 2020 23:31:13 +0200 Subject: [PATCH 067/653] cleaned up returnvlaues --- devicehandlers/DeviceHandlerBase.h | 16 ++++++------ devicehandlers/DeviceHandlerIF.h | 41 +++++++++++------------------- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 56f9be1d..99b53b57 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -505,28 +505,28 @@ public: protected: /** - * The Returnvalues id of this class, required by HasReturnvaluesIF + * The Returnvalues ID of this class, required by HasReturnvaluesIF */ static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE; - /** - * These returnvalues can be returned from abstract functions + /* These returnvalues can be returned from abstract functions * to alter the behaviour of DHB.For error values, refer to - * DeviceHandlerIF.h returnvalues. - */ + * DeviceHandlerIF.h returnvalues. */ static const ReturnValue_t INVALID_CHANNEL = MAKE_RETURN_CODE(4); + // Returnvalues for scanForReply() 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); //!< Ignore parts of the received packet static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE(7); //!< Ignore full received packet -// static const ReturnValue_t ONE_SWITCH = MAKE_RETURN_CODE(8); -// static const ReturnValue_t TWO_SWITCHES = MAKE_RETURN_CODE(9); + // Returnvalues for command building + static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(0xA0); //!< Return this if no command sending in required static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(10); static const ReturnValue_t COMMAND_MAP_ERROR = MAKE_RETURN_CODE(11); static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(12); - //Mode handling error Codes + // (Robin): Maybe this would be better in DeviceHandlerIF? + // Mode handling error Codes static const ReturnValue_t CHILD_TIMEOUT = MAKE_RETURN_CODE(0xE1); static const ReturnValue_t SWITCH_FAILED = MAKE_RETURN_CODE(0xE2); diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index e2a5138d..2cb1ec3b 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -96,27 +96,23 @@ public: static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF; // Standard codes used when building commands. - static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(0xA0); //!< Return this if no command sending in required - static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA2); //!< If the command size is 0. Checked in DHB - static const ReturnValue_t NO_REPLY_EXPECTED = MAKE_RETURN_CODE(0xA3); //!< Used to indicate that this is a command-only command. - static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA4); //!< Command ID not in commandMap. Checked in DHB - static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA5); //!< Command was already executed. Checked in DHB - static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA6); - static const ReturnValue_t CANT_SWITCH_ADDRESS = MAKE_RETURN_CODE(0xA7); - static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA8); - static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA9); - static const ReturnValue_t BUSY = MAKE_RETURN_CODE(0xAA); - static const ReturnValue_t NON_OP_TEMPERATURE = MAKE_RETURN_CODE(0xAB); - static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xAC); + static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If the command size is 0. Checked in DHB + static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1); //!< Command ID not in commandMap. Checked in DHB + static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA2); //!< Command was already executed. Checked in DHB + static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3); + static const ReturnValue_t CANT_SWITCH_ADDRESS = MAKE_RETURN_CODE(0xA4); + static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA5); + static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA6); + 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 scanForReply - static const ReturnValue_t APERIODIC_REPLY = MAKE_RETURN_CODE(0xB1); //!< This is used to specify for replies from a device which are not replies to requests - static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB2); - static const ReturnValue_t IGNORE_REPLY_DATA = MAKE_RETURN_CODE(0xB3); //!< Ignore parts of the received packet - static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE(0xB4); //!< Ignore full received packet - static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB5); - static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB6); - static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB7); + static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB2); + static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB3); + static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB4); + static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB5); // Standard codes used in interpretDeviceReply static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC1); //the device reported, that it did not execute the command @@ -128,13 +124,6 @@ public: static const ReturnValue_t INVALID_COMMAND_PARAMETER = MAKE_RETURN_CODE(0xD0); static const ReturnValue_t INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS = MAKE_RETURN_CODE(0xD1); - // Standard codes used in getSwitches - static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(0xE1); //!< Return in getSwitches() to specify there are no switches - - // static const ReturnValue_t ONE_SWITCH = MAKE_RETURN_CODE(8); - // static const ReturnValue_t TWO_SWITCHES = MAKE_RETURN_CODE(9); - // static const ReturnValue_t COMMAND_MAP_ERROR = MAKE_RETURN_CODE(11); - /** * Communication action that will be executed. * From 5de68fcc6e5433d4bf6fb6af87680f5d7c659459 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 25 May 2020 23:36:47 +0200 Subject: [PATCH 068/653] some returnvalue comments --- devicehandlers/DeviceHandlerBase.h | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 99b53b57..bcfcde97 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -512,23 +512,25 @@ protected: /* These returnvalues can be returned from abstract functions * to alter the behaviour of DHB.For error values, refer to * DeviceHandlerIF.h returnvalues. */ - static const ReturnValue_t INVALID_CHANNEL = MAKE_RETURN_CODE(4); + // (Robin): maybe this would be better in DeviceHandlerIF? + static const ReturnValue_t INVALID_CHANNEL = MAKE_RETURN_CODE(0xA0); // Returnvalues for scanForReply() - 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); //!< Ignore parts of the received packet - static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE(7); //!< Ignore full received packet + static const ReturnValue_t APERIODIC_REPLY = MAKE_RETURN_CODE(0xB0); //!< 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(0xB1); //!< Ignore parts of the received packet + static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE(0xB2); //!< Ignore full received packet // Returnvalues for command building - static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(0xA0); //!< Return this if no command sending in required - static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(10); - static const ReturnValue_t COMMAND_MAP_ERROR = MAKE_RETURN_CODE(11); - static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(12); + static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(0xC0); //!< Return this if no command sending in required + static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(0xC1); + // (Robin): Maybe this would be better in DeviceHandlerIF? + static const ReturnValue_t COMMAND_MAP_ERROR = MAKE_RETURN_CODE(0xC2); + static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(0xC3); // (Robin): Maybe this would be better in DeviceHandlerIF? // Mode handling error Codes - static const ReturnValue_t CHILD_TIMEOUT = MAKE_RETURN_CODE(0xE1); - static const ReturnValue_t SWITCH_FAILED = MAKE_RETURN_CODE(0xE2); + static const ReturnValue_t CHILD_TIMEOUT = MAKE_RETURN_CODE(0xD0); + static const ReturnValue_t SWITCH_FAILED = MAKE_RETURN_CODE(0xD1); static const DeviceCommandId_t RAW_COMMAND_ID = -1; static const DeviceCommandId_t NO_COMMAND_ID = -2; From dd5b301980550442ef702662f27cc602aad07017 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 25 May 2020 23:38:11 +0200 Subject: [PATCH 069/653] improved returnvalues --- devicehandlers/DeviceHandlerIF.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index 2cb1ec3b..666d9efc 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -109,16 +109,16 @@ public: static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xAA); // Standard codes used in scanForReply - static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB2); - static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB3); - static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB4); - static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB5); + static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB0); + static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB1); + static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB2); + static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB3); // Standard codes used in interpretDeviceReply - static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC1); //the device reported, that it did not execute the command - static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC2); - static const ReturnValue_t UNKNOW_DEVICE_REPLY = MAKE_RETURN_CODE(0xC3); //the deviceCommandId reported by scanforReply is unknown - static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC4); //syntax etc is correct but still not ok, eg parameters where none are expected + static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC0); //the device reported, that it did not execute the command + static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC1); + static const ReturnValue_t UNKNOW_DEVICE_REPLY = MAKE_RETURN_CODE(0xC2); //the deviceCommandId reported by scanforReply is unknown + static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC3); //syntax etc is correct but still not ok, eg parameters where none are expected // Standard codes used in buildCommandFromCommand static const ReturnValue_t INVALID_COMMAND_PARAMETER = MAKE_RETURN_CODE(0xD0); From 9951b59627b55093cd50334946d7473d9aabe114 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 25 May 2020 23:45:32 +0200 Subject: [PATCH 070/653] DHB retval fixes --- devicehandlers/DeviceHandlerBase.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index bcfcde97..421e0005 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -522,15 +522,16 @@ protected: // Returnvalues for command building static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(0xC0); //!< Return this if no command sending in required - static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(0xC1); // (Robin): Maybe this would be better in DeviceHandlerIF? static const ReturnValue_t COMMAND_MAP_ERROR = MAKE_RETURN_CODE(0xC2); - static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(0xC3); + + // Returnvalues for getSwitches() + static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(0xD0); // (Robin): Maybe this would be better in DeviceHandlerIF? // Mode handling error Codes - static const ReturnValue_t CHILD_TIMEOUT = MAKE_RETURN_CODE(0xD0); - static const ReturnValue_t SWITCH_FAILED = MAKE_RETURN_CODE(0xD1); + static const ReturnValue_t CHILD_TIMEOUT = MAKE_RETURN_CODE(0xE0); + static const ReturnValue_t SWITCH_FAILED = MAKE_RETURN_CODE(0xE1); static const DeviceCommandId_t RAW_COMMAND_ID = -1; static const DeviceCommandId_t NO_COMMAND_ID = -2; From ca74e0c0f2d6e82fcb7eb3dc2848f157dec1709f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 26 May 2020 16:07:32 +0200 Subject: [PATCH 071/653] removed comments --- devicehandlers/DeviceHandlerBase.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 421e0005..b959c9de 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -509,26 +509,16 @@ protected: */ static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE; - /* These returnvalues can be returned from abstract functions - * to alter the behaviour of DHB.For error values, refer to - * DeviceHandlerIF.h returnvalues. */ - // (Robin): maybe this would be better in DeviceHandlerIF? static const ReturnValue_t INVALID_CHANNEL = MAKE_RETURN_CODE(0xA0); - // Returnvalues for scanForReply() static const ReturnValue_t APERIODIC_REPLY = MAKE_RETURN_CODE(0xB0); //!< 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(0xB1); //!< Ignore parts of the received packet static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE(0xB2); //!< Ignore full received packet - // Returnvalues for command building static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(0xC0); //!< Return this if no command sending in required - // (Robin): Maybe this would be better in DeviceHandlerIF? static const ReturnValue_t COMMAND_MAP_ERROR = MAKE_RETURN_CODE(0xC2); - // Returnvalues for getSwitches() static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(0xD0); - - // (Robin): Maybe this would be better in DeviceHandlerIF? // Mode handling error Codes static const ReturnValue_t CHILD_TIMEOUT = MAKE_RETURN_CODE(0xE0); static const ReturnValue_t SWITCH_FAILED = MAKE_RETURN_CODE(0xE1); From f388bd374c8db334b5d7b0b9207a360d712d5fde Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 13:29:29 +0200 Subject: [PATCH 072/653] added new factory and interface --- tasks/SemaphoreFactory.h | 49 ++++++++++++++++++++++++++++++++ tasks/SemaphoreIF.h | 61 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 tasks/SemaphoreFactory.h create mode 100644 tasks/SemaphoreIF.h diff --git a/tasks/SemaphoreFactory.h b/tasks/SemaphoreFactory.h new file mode 100644 index 00000000..7f8edaf1 --- /dev/null +++ b/tasks/SemaphoreFactory.h @@ -0,0 +1,49 @@ +#ifndef FRAMEWORK_TASKS_SEMAPHOREFACTORY_H_ +#define FRAMEWORK_TASKS_SEMAPHOREFACTORY_H_ +#include + +/** + * Creates Semaphore. + * This class is a "singleton" interface, i.e. it provides an + * interface, but also is the base class for a singleton. + */ +class SemaphoreFactory { +public: + virtual ~SemaphoreFactory(); + /** + * Returns the single instance of SemaphoreFactory. + * The implementation of #instance is found in its subclasses. + * Thus, we choose link-time variability of the instance. + */ + static SemaphoreFactory* instance(); + + /** + * Create a binary semaphore. + * Creator function for a binary semaphore which may only be acquired once + * @param argument Can be used to pass implementation specific information. + * @return Pointer to newly created semaphore class instance. + */ + SemaphoreIF* createBinarySemaphore(uint32_t arguments = 0); + /** + * Create a counting semaphore. + * Creator functons for a counting semaphore which may be acquired multiple + * times. + * @param count Semaphore can be taken count times. + * @param initCount Initial count value. + * @param argument Can be used to pass implementation specific information. + * @return + */ + SemaphoreIF* createCountingSemaphore(const uint8_t maxCount, + uint8_t initCount, uint32_t arguments = 0); + + void deleteSemaphore(SemaphoreIF* semaphore); + +private: + /** + * External instantiation is not allowed. + */ + SemaphoreFactory(); + static SemaphoreFactory* factoryInstance; +}; + +#endif /* FRAMEWORK_TASKS_SEMAPHOREFACTORY_H_ */ diff --git a/tasks/SemaphoreIF.h b/tasks/SemaphoreIF.h new file mode 100644 index 00000000..a7c5a97b --- /dev/null +++ b/tasks/SemaphoreIF.h @@ -0,0 +1,61 @@ +#ifndef FRAMEWORK_TASKS_SEMAPHOREIF_H_ +#define FRAMEWORK_TASKS_SEMAPHOREIF_H_ +#include +#include +#include + +/** + * @brief Generic interface for semaphores, which can be used to achieve + * task synchronization. This is a generic interface which can be + * used for both binary semaphores and counting semaphores. + * @details + * A semaphore is a synchronization primitive. + * See: https://en.wikipedia.org/wiki/Semaphore_(programming) + * A semaphore can be used to achieve task synchonization and track the + * availability of resources by using either the binary or the counting + * semaphore types. + * + * If mutual exlcusion of a resource is desired, a mutex should be used, + * which is a special form of a semaphore and has an own interface. + */ +class SemaphoreIF { +public: + virtual~ SemaphoreIF() {}; + //! Needs to be defined in implementation. No blocking time + static const uint32_t NO_TIMEOUT; + //! Needs to be defined in implementation. Blocks indefinitely. + static const uint32_t MAX_TIMEOUT; + static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; + //! Semaphore timeout + static constexpr ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(1); + //! The current semaphore can not be given, because it is not owned + static constexpr ReturnValue_t SEMAPHORE_NOT_OWNED = MAKE_RETURN_CODE(2); + static constexpr ReturnValue_t SEMAPHORE_INVALID = MAKE_RETURN_CODE(3); + + /** + * Generic call to acquire a semaphore. + * If there are no more semaphores to be taken (for a counting semaphore, + * a semaphore may be taken more than once), the taks will block + * for a maximum of timeoutMs while trying to acquire the semaphore. + * This can be used to achieve task synchrnization. + * @param timeoutMs + * @return - c RETURN_OK for successfull acquisition + */ + virtual ReturnValue_t acquire(uint32_t timeoutMs) = 0; + + /** + * Corrensponding call to release a semaphore. + * @return -@c RETURN_OK for successfull release + */ + virtual ReturnValue_t release() = 0; + + /** + * If the semaphore is a counting semaphore then the semaphores current + * count value is returned. If the semaphore is a binary semaphore then 1 + * is returned if the semaphore is available, and 0 is returned if the + * semaphore is not available. + */ + virtual uint8_t getSemaphoreCounter() const = 0; +}; + +#endif /* FRAMEWORK_TASKS_SEMAPHOREIF_H_ */ From d909fcb6a17448a3f2ccd3c7c9512a666a429e33 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 13:31:19 +0200 Subject: [PATCH 073/653] added semaphore implementations --- osal/FreeRTOS/BinSemaphUsingTask.cpp | 91 ++++++++++++++++++ osal/FreeRTOS/BinSemaphUsingTask.h | 75 +++++++++++++++ osal/FreeRTOS/BinarySemaphore.cpp | 103 ++++++++++++++++++++ osal/FreeRTOS/BinarySemaphore.h | 107 +++++++++++++++++++++ osal/FreeRTOS/CountingSemaphUsingTask.cpp | 110 ++++++++++++++++++++++ osal/FreeRTOS/CountingSemaphUsingTask.h | 100 ++++++++++++++++++++ osal/FreeRTOS/CountingSemaphore.cpp | 43 +++++++++ osal/FreeRTOS/CountingSemaphore.h | 34 +++++++ 8 files changed, 663 insertions(+) create mode 100644 osal/FreeRTOS/BinSemaphUsingTask.cpp create mode 100644 osal/FreeRTOS/BinSemaphUsingTask.h create mode 100644 osal/FreeRTOS/BinarySemaphore.cpp create mode 100644 osal/FreeRTOS/BinarySemaphore.h create mode 100644 osal/FreeRTOS/CountingSemaphUsingTask.cpp create mode 100644 osal/FreeRTOS/CountingSemaphUsingTask.h create mode 100644 osal/FreeRTOS/CountingSemaphore.cpp create mode 100644 osal/FreeRTOS/CountingSemaphore.h diff --git a/osal/FreeRTOS/BinSemaphUsingTask.cpp b/osal/FreeRTOS/BinSemaphUsingTask.cpp new file mode 100644 index 00000000..8f5fd4d8 --- /dev/null +++ b/osal/FreeRTOS/BinSemaphUsingTask.cpp @@ -0,0 +1,91 @@ +#include +#include +#include + +BinarySemaphoreUsingTask::BinarySemaphoreUsingTask() { + handle = TaskManagement::getCurrentTaskHandle(); + if(handle == nullptr) { + sif::error << "Could not retrieve task handle. Please ensure the" + "constructor was called inside a task." << std::endl; + } + xTaskNotifyGive(handle); +} + +BinarySemaphoreUsingTask::~BinarySemaphoreUsingTask() { + // Clear notification value on destruction. + xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr); +} + +ReturnValue_t BinarySemaphoreUsingTask::acquire(uint32_t timeoutMs) { + TickType_t timeout = SemaphoreIF::NO_TIMEOUT; + if(timeoutMs == SemaphoreIF::MAX_TIMEOUT) { + timeout = SemaphoreIF::MAX_TIMEOUT; + } + else if(timeoutMs > SemaphoreIF::NO_TIMEOUT){ + timeout = pdMS_TO_TICKS(timeoutMs); + } + return acquireWithTickTimeout(timeout); +} + +ReturnValue_t BinarySemaphoreUsingTask::acquireWithTickTimeout( + TickType_t timeoutTicks) { + BaseType_t returncode = ulTaskNotifyTake(pdTRUE, timeoutTicks); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SemaphoreIF::SEMAPHORE_TIMEOUT; + } +} + +ReturnValue_t BinarySemaphoreUsingTask::release() { + return release(this->handle); +} + +ReturnValue_t BinarySemaphoreUsingTask::release( + TaskHandle_t taskHandle) { + if(getSemaphoreCounter(taskHandle) == 1) { + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } + BaseType_t returncode = xTaskNotifyGive(taskHandle); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + // This should never happen. + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +TaskHandle_t BinarySemaphoreUsingTask::getTaskHandle() { + return handle; +} + +uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter() const { + return getSemaphoreCounter(this->handle); +} + +uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter( + TaskHandle_t taskHandle) { + uint32_t notificationValue; + xTaskNotifyAndQuery(taskHandle, 0, eNoAction, ¬ificationValue); + return notificationValue; +} + +// Be careful with the stack size here. This is called from an ISR! +ReturnValue_t BinarySemaphoreUsingTask::releaseFromISR( + TaskHandle_t taskHandle, BaseType_t * higherPriorityTaskWoken) { + if(getSemaphoreCounterFromISR(taskHandle, higherPriorityTaskWoken) == 1) { + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } + vTaskNotifyGiveFromISR(taskHandle, higherPriorityTaskWoken); + return HasReturnvaluesIF::RETURN_OK; +} + +uint8_t BinarySemaphoreUsingTask::getSemaphoreCounterFromISR( + TaskHandle_t taskHandle, BaseType_t* higherPriorityTaskWoken) { + uint32_t notificationValue = 0; + xTaskNotifyAndQueryFromISR(taskHandle, 0, eNoAction, ¬ificationValue, + higherPriorityTaskWoken); + return notificationValue; +} diff --git a/osal/FreeRTOS/BinSemaphUsingTask.h b/osal/FreeRTOS/BinSemaphUsingTask.h new file mode 100644 index 00000000..48c1cd12 --- /dev/null +++ b/osal/FreeRTOS/BinSemaphUsingTask.h @@ -0,0 +1,75 @@ +#ifndef FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ +#define FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ + +#include +#include + +#include +#include + +/** + * @brief Binary Semaphore implementation using the task notification value. + * The notification value should therefore not be used + * for other purposes. + * @details + * Additional information: https://www.freertos.org/RTOS-task-notifications.html + * and general semaphore documentation. + */ +class BinarySemaphoreUsingTask: public SemaphoreIF, + public HasReturnvaluesIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; + + //! @brief Default ctor + BinarySemaphoreUsingTask(); + //! @brief Default dtor + virtual~ BinarySemaphoreUsingTask(); + + ReturnValue_t acquire(uint32_t timeoutMs = + SemaphoreIF::NO_TIMEOUT) override; + ReturnValue_t release() override; + uint8_t getSemaphoreCounter() const override; + static uint8_t getSemaphoreCounter(TaskHandle_t taskHandle); + static uint8_t getSemaphoreCounterFromISR(TaskHandle_t taskHandle, + BaseType_t* higherPriorityTaskWoken); + + /** + * Same as acquire() with timeout in FreeRTOS ticks. + * @param timeoutTicks + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + ReturnValue_t acquireWithTickTimeout(TickType_t timeoutTicks = + SemaphoreIF::NO_TIMEOUT); + + /** + * Get handle to the task related to the semaphore. + * @return + */ + TaskHandle_t getTaskHandle(); + + /** + * Wrapper function to give back semaphore from handle + * @param semaphore + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + static ReturnValue_t release(TaskHandle_t taskToNotify); + + /** + * Wrapper function to give back semaphore from handle when called from an ISR + * @param semaphore + * @param higherPriorityTaskWoken This will be set to pdPASS if a task with + * a higher priority was unblocked. A context switch should be requested + * from an ISR if this is the case (see TaskManagement functions) + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify, + BaseType_t * higherPriorityTaskWoken); + +protected: + TaskHandle_t handle; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ */ diff --git a/osal/FreeRTOS/BinarySemaphore.cpp b/osal/FreeRTOS/BinarySemaphore.cpp new file mode 100644 index 00000000..b6687bb7 --- /dev/null +++ b/osal/FreeRTOS/BinarySemaphore.cpp @@ -0,0 +1,103 @@ +#include +#include +#include + +BinarySemaphore::BinarySemaphore() { + handle = xSemaphoreCreateBinary(); + if(handle == nullptr) { + sif::error << "Semaphore: Binary semaph creation failure" << std::endl; + } + // Initiated semaphore must be given before it can be taken. + xSemaphoreGive(handle); +} + +BinarySemaphore::~BinarySemaphore() { + vSemaphoreDelete(handle); +} + +BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { + handle = xSemaphoreCreateBinary(); + if(handle == nullptr) { + sif::error << "Binary semaphore creation failure" << std::endl; + } + xSemaphoreGive(handle); +} + +BinarySemaphore& BinarySemaphore::operator =( + BinarySemaphore&& s) { + if(&s != this) { + handle = xSemaphoreCreateBinary(); + if(handle == nullptr) { + sif::error << "Binary semaphore creation failure" << std::endl; + } + xSemaphoreGive(handle); + } + return *this; +} + +ReturnValue_t BinarySemaphore::acquire(uint32_t timeoutMs) { + TickType_t timeout = SemaphoreIF::NO_TIMEOUT; + if(timeoutMs == SemaphoreIF::MAX_TIMEOUT) { + timeout = SemaphoreIF::MAX_TIMEOUT; + } + else if(timeoutMs > SemaphoreIF::NO_TIMEOUT){ + timeout = pdMS_TO_TICKS(timeoutMs); + } + return acquireWithTickTimeout(timeout); +} + +ReturnValue_t BinarySemaphore::acquireWithTickTimeout(TickType_t timeoutTicks) { + if(handle == nullptr) { + return SemaphoreIF::SEMAPHORE_INVALID; + } + + BaseType_t returncode = xSemaphoreTake(handle, timeoutTicks); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SemaphoreIF::SEMAPHORE_TIMEOUT; + } +} + +ReturnValue_t BinarySemaphore::release() { + return release(handle); +} + +ReturnValue_t BinarySemaphore::release(SemaphoreHandle_t semaphore) { + if (semaphore == nullptr) { + return SemaphoreIF::SEMAPHORE_INVALID; + } + BaseType_t returncode = xSemaphoreGive(semaphore); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } +} + +uint8_t BinarySemaphore::getSemaphoreCounter() const { + return uxSemaphoreGetCount(handle); +} + +SemaphoreHandle_t BinarySemaphore::getSemaphore() { + return handle; +} + + +// Be careful with the stack size here. This is called from an ISR! +ReturnValue_t BinarySemaphore::releaseFromISR( + SemaphoreHandle_t semaphore, BaseType_t * higherPriorityTaskWoken) { + if (semaphore == nullptr) { + return SemaphoreIF::SEMAPHORE_INVALID; + } + BaseType_t returncode = xSemaphoreGiveFromISR(semaphore, + higherPriorityTaskWoken); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } +} diff --git a/osal/FreeRTOS/BinarySemaphore.h b/osal/FreeRTOS/BinarySemaphore.h new file mode 100644 index 00000000..0938dee6 --- /dev/null +++ b/osal/FreeRTOS/BinarySemaphore.h @@ -0,0 +1,107 @@ +#ifndef FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ +#define FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ + +#include +#include + +#include +#include + +/** + * @brief OS Tool to achieve synchronization of between tasks or between + * task and ISR. The default semaphore implementation creates a + * binary semaphore, which can only be taken once. + * @details + * Documentation: https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html + * + * Please note that if the semaphore implementation is only related to + * the synchronization of one task, the new task notifications can be used, + * also see the BinSemaphUsingTask and CountingSemaphUsingTask classes. + * These use the task notification value instead of a queue and are + * faster and more efficient. + * + * @author R. Mueller + * @ingroup osal + */ +class BinarySemaphore: public SemaphoreIF, + public HasReturnvaluesIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; + + //! @brief Default ctor + BinarySemaphore(); + //! @brief Copy ctor, deleted explicitely. + BinarySemaphore(const BinarySemaphore&) = delete; + //! @brief Copy assignment, deleted explicitely. + BinarySemaphore& operator=(const BinarySemaphore&) = delete; + //! @brief Move ctor + BinarySemaphore (BinarySemaphore &&); + //! @brief Move assignment + BinarySemaphore & operator=(BinarySemaphore &&); + //! @brief Destructor + virtual ~BinarySemaphore(); + + uint8_t getSemaphoreCounter() const override; + + /** + * Take the binary semaphore. + * If the semaphore has already been taken, the task will be blocked + * for a maximum of #timeoutMs or until the semaphore is given back, + * for example by an ISR or another task. + * @param timeoutMs + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout + */ + ReturnValue_t acquire(uint32_t timeoutMs = + SemaphoreIF::NO_TIMEOUT) override; + + /** + * Same as lockBinarySemaphore() with timeout in FreeRTOS ticks. + * @param timeoutTicks + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout + */ + ReturnValue_t acquireWithTickTimeout(TickType_t timeoutTicks = + BinarySemaphore::NO_TIMEOUT); + + /** + * Release the binary semaphore. + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is + * already available. + */ + ReturnValue_t release() override; + + /** + * Get Handle to the semaphore. + * @return + */ + SemaphoreHandle_t getSemaphore(); + + /** + * Wrapper function to give back semaphore from handle + * @param semaphore + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is + * already available. + */ + static ReturnValue_t release(SemaphoreHandle_t semaphore); + + /** + * Wrapper function to give back semaphore from handle when called from an ISR + * @param semaphore + * @param higherPriorityTaskWoken This will be set to pdPASS if a task with + * a higher priority was unblocked. A context switch from an ISR should + * then be requested (see TaskManagement functions) + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is + * already available. + */ + static ReturnValue_t releaseFromISR(SemaphoreHandle_t semaphore, + BaseType_t * higherPriorityTaskWoken); + +protected: + SemaphoreHandle_t handle; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */ diff --git a/osal/FreeRTOS/CountingSemaphUsingTask.cpp b/osal/FreeRTOS/CountingSemaphUsingTask.cpp new file mode 100644 index 00000000..d0f63f3f --- /dev/null +++ b/osal/FreeRTOS/CountingSemaphUsingTask.cpp @@ -0,0 +1,110 @@ +#include +#include +#include + +CountingSemaphoreUsingTask::CountingSemaphoreUsingTask(const uint8_t maxCount, + uint8_t initCount): maxCount(maxCount) { + if(initCount > maxCount) { + sif::error << "CountingSemaphoreUsingTask: Max count bigger than " + "intial cout. Setting initial count to max count." << std::endl; + initCount = maxCount; + } + + handle = TaskManagement::getCurrentTaskHandle(); + if(handle == nullptr) { + sif::error << "CountingSemaphoreUsingTask: Could not retrieve task " + "handle. Please ensure the constructor was called inside a " + "task." << std::endl; + } + + uint32_t oldNotificationValue; + xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, + &oldNotificationValue); + if(oldNotificationValue != 0) { + sif::warning << "CountinSemaphoreUsingTask: Semaphore initiated but " + "current notification value is not 0. Please ensure the " + "notification value is not used for other purposes!" << std::endl; + } + for(int i = 0; i < initCount; i++) { + xTaskNotifyGive(handle); + } +} + +CountingSemaphoreUsingTask::~CountingSemaphoreUsingTask() { + // Clear notification value on destruction. + // If this is not desired, don't call the destructor + // (or implement a boolean which disables the reset) + xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr); +} + +ReturnValue_t CountingSemaphoreUsingTask::acquire(uint32_t timeoutMs) { + TickType_t timeout = SemaphoreIF::NO_TIMEOUT; + if(timeoutMs == SemaphoreIF::MAX_TIMEOUT) { + timeout = SemaphoreIF::MAX_TIMEOUT; + } + else if(timeoutMs > SemaphoreIF::NO_TIMEOUT){ + timeout = pdMS_TO_TICKS(timeoutMs); + } + return acquireWithTickTimeout(timeout); + +} + +ReturnValue_t CountingSemaphoreUsingTask::acquireWithTickTimeout( + TickType_t timeoutTicks) { + // Decrement notfication value without resetting it. + BaseType_t oldCount = ulTaskNotifyTake(pdFALSE, timeoutTicks); + if (getSemaphoreCounter() == oldCount - 1) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SemaphoreIF::SEMAPHORE_TIMEOUT; + } +} + +ReturnValue_t CountingSemaphoreUsingTask::release() { + if(getSemaphoreCounter() == maxCount) { + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } + return release(handle); +} + +ReturnValue_t CountingSemaphoreUsingTask::release( + TaskHandle_t taskToNotify) { + BaseType_t returncode = xTaskNotifyGive(taskToNotify); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + // This should never happen. + return HasReturnvaluesIF::RETURN_FAILED; + } +} + + +uint8_t CountingSemaphoreUsingTask::getSemaphoreCounter() const { + uint32_t notificationValue = 0; + xTaskNotifyAndQuery(handle, 0, eNoAction, ¬ificationValue); + return notificationValue; +} + +TaskHandle_t CountingSemaphoreUsingTask::getTaskHandle() { + return handle; +} + +ReturnValue_t CountingSemaphoreUsingTask::releaseFromISR( + TaskHandle_t taskToNotify, BaseType_t* higherPriorityTaskWoken) { + vTaskNotifyGiveFromISR(taskToNotify, higherPriorityTaskWoken); + return HasReturnvaluesIF::RETURN_OK; +} + +uint8_t CountingSemaphoreUsingTask::getSemaphoreCounterFromISR( + TaskHandle_t task, BaseType_t* higherPriorityTaskWoken) { + uint32_t notificationValue; + xTaskNotifyAndQueryFromISR(task, 0, eNoAction, ¬ificationValue, + higherPriorityTaskWoken); + return notificationValue; +} + +uint8_t CountingSemaphoreUsingTask::getMaxCount() const { + return maxCount; +} diff --git a/osal/FreeRTOS/CountingSemaphUsingTask.h b/osal/FreeRTOS/CountingSemaphUsingTask.h new file mode 100644 index 00000000..797e864b --- /dev/null +++ b/osal/FreeRTOS/CountingSemaphUsingTask.h @@ -0,0 +1,100 @@ +#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ +#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ + +#include +#include + +extern "C" { +#include +#include +} + +/** + * @brief Couting Semaphore implementation which uses the notification value + * of the task. The notification value should therefore not be used + * for other purposes. + * @details + * Additional information: https://www.freertos.org/RTOS-task-notifications.html + * and general semaphore documentation. + */ +class CountingSemaphoreUsingTask: public SemaphoreIF { +public: + CountingSemaphoreUsingTask(const uint8_t maxCount, uint8_t initCount); + virtual ~CountingSemaphoreUsingTask(); + + /** + * Acquire the counting semaphore. + * If no semaphores are available, the task will be blocked + * for a maximum of #timeoutMs or until one is given back, + * for example by an ISR or another task. + * @param timeoutMs + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout + */ + ReturnValue_t acquire(uint32_t timeoutMs = SemaphoreIF::NO_TIMEOUT) override; + + /** + * Release a semaphore, increasing the number of available counting + * semaphores up to the #maxCount value. + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are + * already available. + */ + ReturnValue_t release() override; + + uint8_t getSemaphoreCounter() const override; + /** + * Get the semaphore counter from an ISR. + * @param task + * @param higherPriorityTaskWoken This will be set to pdPASS if a task with + * a higher priority was unblocked. A context switch should be requested + * from an ISR if this is the case (see TaskManagement functions) + * @return + */ + static uint8_t getSemaphoreCounterFromISR(TaskHandle_t task, + BaseType_t* higherPriorityTaskWoken); + + /** + * Acquire with a timeout value in ticks + * @param timeoutTicks + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout + */ + ReturnValue_t acquireWithTickTimeout( + TickType_t timeoutTicks = SemaphoreIF::NO_TIMEOUT); + + /** + * Get handle to the task related to the semaphore. + * @return + */ + TaskHandle_t getTaskHandle(); + + /** + * Release semaphore of task by supplying task handle + * @param taskToNotify + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are + * already available. + */ + static ReturnValue_t release(TaskHandle_t taskToNotify); + /** + * Release seamphore of a task from an ISR. + * @param taskToNotify + * @param higherPriorityTaskWoken This will be set to pdPASS if a task with + * a higher priority was unblocked. A context switch should be requested + * from an ISR if this is the case (see TaskManagement functions) + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are + * already available. + */ + static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify, + BaseType_t* higherPriorityTaskWoken); + + uint8_t getMaxCount() const; + +private: + TaskHandle_t handle; + const uint8_t maxCount; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ */ diff --git a/osal/FreeRTOS/CountingSemaphore.cpp b/osal/FreeRTOS/CountingSemaphore.cpp new file mode 100644 index 00000000..957f6a31 --- /dev/null +++ b/osal/FreeRTOS/CountingSemaphore.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include + +// Make sure #define configUSE_COUNTING_SEMAPHORES 1 is set in +// free FreeRTOSConfig.h file. +CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount): + maxCount(maxCount), initCount(initCount) { + if(initCount > maxCount) { + sif::error << "CountingSemaphoreUsingTask: Max count bigger than " + "intial cout. Setting initial count to max count." << std::endl; + initCount = maxCount; + } + + handle = xSemaphoreCreateCounting(maxCount, initCount); + if(handle == nullptr) { + sif::error << "CountingSemaphore: Creation failure" << std::endl; + } +} + +CountingSemaphore::CountingSemaphore(CountingSemaphore&& other): + maxCount(other.maxCount), initCount(other.initCount) { + handle = xSemaphoreCreateCounting(other.maxCount, other.initCount); + if(handle == nullptr) { + sif::error << "CountingSemaphore: Creation failure" << std::endl; + } +} + +CountingSemaphore& CountingSemaphore::operator =( + CountingSemaphore&& other) { + handle = xSemaphoreCreateCounting(other.maxCount, other.initCount); + if(handle == nullptr) { + sif::error << "CountingSemaphore: Creation failure" << std::endl; + } + return * this; +} + + +uint8_t CountingSemaphore::getMaxCount() const { + return maxCount; +} diff --git a/osal/FreeRTOS/CountingSemaphore.h b/osal/FreeRTOS/CountingSemaphore.h new file mode 100644 index 00000000..dca3ab0e --- /dev/null +++ b/osal/FreeRTOS/CountingSemaphore.h @@ -0,0 +1,34 @@ +#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ +#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ +#include + +/** + * @brief Counting semaphores, which can be acquire more than once. + * @details + * See: https://www.freertos.org/CreateCounting.html + * API of counting semaphores is almost identical to binary semaphores, + * so we just inherit from binary semaphore and provide the respective + * constructors. + */ +class CountingSemaphore: public BinarySemaphore { +public: + CountingSemaphore(const uint8_t maxCount, uint8_t initCount); + //! @brief Copy ctor, disabled + CountingSemaphore(const CountingSemaphore&) = delete; + //! @brief Copy assignment, disabled + CountingSemaphore& operator=(const CountingSemaphore&) = delete; + //! @brief Move ctor + CountingSemaphore (CountingSemaphore &&); + //! @brief Move assignment + CountingSemaphore & operator=(CountingSemaphore &&); + + /* Same API as binary semaphore otherwise. acquire() can be called + * until there are not semaphores left and release() can be called + * until maxCount is reached. */ + uint8_t getMaxCount() const; +private: + const uint8_t maxCount; + uint8_t initCount = 0; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */ From f829d063cee5383abfdc9dc951a4f82cbea7d36f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 13:31:55 +0200 Subject: [PATCH 074/653] added task management functions required for freeRTOS --- osal/FreeRTOS/TaskManagement.cpp | 23 ++++++++++++ osal/FreeRTOS/TaskManagement.h | 63 ++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 osal/FreeRTOS/TaskManagement.cpp create mode 100644 osal/FreeRTOS/TaskManagement.h diff --git a/osal/FreeRTOS/TaskManagement.cpp b/osal/FreeRTOS/TaskManagement.cpp new file mode 100644 index 00000000..7871ab2e --- /dev/null +++ b/osal/FreeRTOS/TaskManagement.cpp @@ -0,0 +1,23 @@ +#include + +void TaskManagement::requestContextSwitchFromTask() { + vTaskDelay(0); +} + +void TaskManagement::requestContextSwitch( + CallContext callContext = CallContext::TASK) { + if(callContext == CallContext::ISR) { + // This function depends on the partmacro.h definition for the specific device + requestContextSwitchFromISR(); + } else { + requestContextSwitchFromTask(); + } +} + +TaskHandle_t TaskManagement::getCurrentTaskHandle() { + return xTaskGetCurrentTaskHandle(); +} + +configSTACK_DEPTH_TYPE TaskManagement::getTaskStackHighWatermark() { + return uxTaskGetStackHighWaterMark(TaskManagement::getCurrentTaskHandle()); +} diff --git a/osal/FreeRTOS/TaskManagement.h b/osal/FreeRTOS/TaskManagement.h new file mode 100644 index 00000000..39c24377 --- /dev/null +++ b/osal/FreeRTOS/TaskManagement.h @@ -0,0 +1,63 @@ +#ifndef FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ +#define FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ + +#include + +extern "C" { +#include +#include +} +#include + +/** + * Architecture dependant portmacro.h function call. + * Should be implemented in bsp. + */ +extern "C" void requestContextSwitchFromISR(); + +/*! + * Used by functions to tell if they are being called from + * within an ISR or from a regular task. This is required because FreeRTOS + * has different functions for handling semaphores and messages from within + * an ISR and task. + */ +enum class CallContext { + TASK = 0x00,//!< task_context + ISR = 0xFF //!< isr_context +}; + + +class TaskManagement { +public: + /** + * @brief In this function, a function dependant on the portmacro.h header + * function calls to request a context switch can be specified. + * This can be used if sending to the queue from an ISR caused a task + * to unblock and a context switch is required. + */ + static void requestContextSwitch(CallContext callContext); + + /** + * If task preemption in FreeRTOS is disabled, a context switch + * can be requested manually by calling this function. + */ + static void requestContextSwitchFromTask(void); + + /** + * @return The current task handle + */ + static TaskHandle_t getCurrentTaskHandle(); + + /** + * Get returns the minimum amount of remaining stack space in words + * that was a available to the task since the task started executing. + * Please note that the actual value in bytes depends + * on the stack depth type. + * E.g. on a 32 bit machine, a value of 200 means 800 bytes. + * @return Smallest value of stack remaining since the task was started in + * words. + */ + static configSTACK_DEPTH_TYPE getTaskStackHighWatermark(); +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */ From adb80a68fc0fb8fd7a206ad842565083df18a59d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 13:32:38 +0200 Subject: [PATCH 075/653] addd freertos semaphore factory --- osal/FreeRTOS/SemaphoreFactory.cpp | 61 ++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 osal/FreeRTOS/SemaphoreFactory.cpp diff --git a/osal/FreeRTOS/SemaphoreFactory.cpp b/osal/FreeRTOS/SemaphoreFactory.cpp new file mode 100644 index 00000000..05a898cd --- /dev/null +++ b/osal/FreeRTOS/SemaphoreFactory.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include + +SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; +const uint32_t SemaphoreIF::NO_TIMEOUT = 0; +const uint32_t SemaphoreIF::MAX_TIMEOUT = portMAX_DELAY; + +static const uint32_t USE_REGULAR_SEMAPHORES = 0; +static const uint32_t USE_TASK_NOTIFICATIONS = 1; + +SemaphoreFactory::SemaphoreFactory() { +} + +SemaphoreFactory::~SemaphoreFactory() { + delete factoryInstance; +} + +SemaphoreFactory* SemaphoreFactory::instance() { + if (factoryInstance == nullptr){ + factoryInstance = new SemaphoreFactory(); + } + return SemaphoreFactory::factoryInstance; +} + +SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t argument) { + if(argument == USE_REGULAR_SEMAPHORES) { + return new BinarySemaphore(); + } + else if(argument == USE_TASK_NOTIFICATIONS) { + return new BinarySemaphoreUsingTask(); + } + else { + sif::warning << "SemaphoreFactory: Invalid argument, return regular" + "binary semaphore" << std::endl; + return new BinarySemaphore(); + } +} + +SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t maxCount, + uint8_t initCount, uint32_t argument) { + if(argument == USE_REGULAR_SEMAPHORES) { + return new CountingSemaphore(maxCount, initCount); + } + else if(argument == USE_TASK_NOTIFICATIONS) { + return new CountingSemaphoreUsingTask(maxCount, initCount); + } + else { + sif::warning << "SemaphoreFactory: Invalid argument, return regular" + "binary semaphore" << std::endl; + return new CountingSemaphore(maxCount, initCount); + } + +} + +void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { + delete semaphore; +} From b4c6a04d4a9969727f2602fee1fb1fff8c4bc832 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 13:33:44 +0200 Subject: [PATCH 076/653] added linux implementations --- osal/linux/BinarySemaphore.cpp | 148 +++++++++++++++++++++++++++++++ osal/linux/BinarySemaphore.h | 81 +++++++++++++++++ osal/linux/CountingSemaphore.cpp | 54 +++++++++++ osal/linux/CountingSemaphore.h | 37 ++++++++ osal/linux/SemaphoreFactory.cpp | 36 ++++++++ 5 files changed, 356 insertions(+) create mode 100644 osal/linux/BinarySemaphore.cpp create mode 100644 osal/linux/BinarySemaphore.h create mode 100644 osal/linux/CountingSemaphore.cpp create mode 100644 osal/linux/CountingSemaphore.h create mode 100644 osal/linux/SemaphoreFactory.cpp diff --git a/osal/linux/BinarySemaphore.cpp b/osal/linux/BinarySemaphore.cpp new file mode 100644 index 00000000..7c76a5c4 --- /dev/null +++ b/osal/linux/BinarySemaphore.cpp @@ -0,0 +1,148 @@ +#include +#include + +extern "C" { +#include +#include +} + +BinarySemaphore::BinarySemaphore() { + // Using unnamed semaphores for now + initSemaphore(); +} + +BinarySemaphore::~BinarySemaphore() { + sem_destroy(&handle); +} + +BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { + initSemaphore(); +} + +BinarySemaphore& BinarySemaphore::operator =( + BinarySemaphore&& s) { + initSemaphore(); + return * this; +} + +ReturnValue_t BinarySemaphore::acquire(uint32_t timeoutMs) { + int result = 0; + if(timeoutMs == SemaphoreIF::NO_TIMEOUT) { + result = sem_trywait(&handle); + } + else if(timeoutMs == SemaphoreIF::MAX_TIMEOUT) { + result = sem_wait(&handle); + } + else if(timeoutMs > SemaphoreIF::NO_TIMEOUT){ + timespec timeOut; + clock_gettime(CLOCK_REALTIME, &timeOut); + uint64_t nseconds = timeOut.tv_sec * 1000000000 + timeOut.tv_nsec; + nseconds += timeoutMs * 1000000; + timeOut.tv_sec = nseconds / 1000000000; + timeOut.tv_nsec = nseconds - timeOut.tv_sec * 1000000000; + result = sem_timedwait(&handle, &timeOut); + if(result != 0 and errno == EINVAL) { + sif::debug << "BinarySemaphore::acquire: Invalid time value possible" + << std::endl; + } + } + if(result == 0) { + return HasReturnvaluesIF::RETURN_OK; + } + + switch(errno) { + case(EAGAIN): + // Operation could not be performed without blocking (for sem_trywait) + case(ETIMEDOUT): + // Semaphore is 0 + return SemaphoreIF::SEMAPHORE_TIMEOUT; + case(EINVAL): + // Semaphore invalid + return SemaphoreIF::SEMAPHORE_INVALID; + case(EINTR): + // Call was interrupted by signal handler + sif::debug << "BinarySemaphore::acquire: Signal handler interrupted." + "Code " << strerror(errno) << std::endl; + /* No break */ + default: + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +ReturnValue_t BinarySemaphore::release() { + return BinarySemaphore::release(&this->handle); +} + +ReturnValue_t BinarySemaphore::release(sem_t *handle) { + ReturnValue_t countResult = checkCount(handle, 1); + if(countResult != HasReturnvaluesIF::RETURN_OK) { + return countResult; + } + + int result = sem_post(handle); + if(result == 0) { + return HasReturnvaluesIF::RETURN_OK; + } + + switch(errno) { + case(EINVAL): + // Semaphore invalid + return SemaphoreIF::SEMAPHORE_INVALID; + case(EOVERFLOW): + // SEM_MAX_VALUE overflow. This should never happen + default: + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +uint8_t BinarySemaphore::getSemaphoreCounter() const { + // And another ugly cast :-D + return getSemaphoreCounter(const_cast(&this->handle)); +} + +uint8_t BinarySemaphore::getSemaphoreCounter(sem_t *handle) { + int value = 0; + int result = sem_getvalue(handle, &value); + if (result == 0) { + return value; + } + else if(result != 0 and errno == EINVAL) { + // Could be called from interrupt, use lightweight printf + printf("BinarySemaphore::getSemaphoreCounter: Invalid semaphore\n"); + return 0; + } + else { + // This should never happen. + return 0; + } +} + +void BinarySemaphore::initSemaphore(uint8_t initCount) { + auto result = sem_init(&handle, true, initCount); + if(result == -1) { + switch(errno) { + case(EINVAL): + // Value exceeds SEM_VALUE_MAX + case(ENOSYS): + // System does not support process-shared semaphores + sif::error << "BinarySemaphore: Init failed with" << strerror(errno) + << std::endl; + } + } +} + +ReturnValue_t BinarySemaphore::checkCount(sem_t* handle, uint8_t maxCount) { + int value = getSemaphoreCounter(handle); + if(value >= maxCount) { + if(maxCount == 1 and value > 1) { + // Binary Semaphore special case. + // This is a config error use lightweight printf is this is called + // from an interrupt + printf("BinarySemaphore::release: Value of binary semaphore greater" + " than 1!\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/osal/linux/BinarySemaphore.h b/osal/linux/BinarySemaphore.h new file mode 100644 index 00000000..7836cd41 --- /dev/null +++ b/osal/linux/BinarySemaphore.h @@ -0,0 +1,81 @@ +#ifndef FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_ +#define FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_ + +#include +#include + +extern "C" { +#include +} + +/** + * @brief OS Tool to achieve synchronization of between tasks or between + * task and ISR. The default semaphore implementation creates a + * binary semaphore, which can only be taken once. + * @details + * See: http://www.man7.org/linux/man-pages/man7/sem_overview.7.html + * @author R. Mueller + * @ingroup osal + */ +class BinarySemaphore: public SemaphoreIF, + public HasReturnvaluesIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; + + //! @brief Default ctor + BinarySemaphore(); + //! @brief Copy ctor, deleted explicitely. + BinarySemaphore(const BinarySemaphore&) = delete; + //! @brief Copy assignment, deleted explicitely. + BinarySemaphore& operator=(const BinarySemaphore&) = delete; + //! @brief Move ctor + BinarySemaphore (BinarySemaphore &&); + //! @brief Move assignment + BinarySemaphore & operator=(BinarySemaphore &&); + //! @brief Destructor + virtual ~BinarySemaphore(); + + void initSemaphore(uint8_t initCount = 1); + + uint8_t getSemaphoreCounter() const override; + static uint8_t getSemaphoreCounter(sem_t* handle); + + /** + * Take the binary semaphore. + * If the semaphore has already been taken, the task will be blocked + * for a maximum of #timeoutMs or until the semaphore is given back, + * for example by an ISR or another task. + * @param timeoutMs + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout + */ + ReturnValue_t acquire(uint32_t timeoutMs = + SemaphoreIF::NO_TIMEOUT) override; + + /** + * Release the binary semaphore. + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is + * already available. + */ + virtual ReturnValue_t release() override; + /** + * This static function can be used to release a semaphore by providing + * its handle. + * @param handle + * @return + */ + static ReturnValue_t release(sem_t* handle); + + /** Checks the validity of the semaphore count against a specified + * known maxCount + * @param handle + * @param maxCount + * @return + */ + static ReturnValue_t checkCount(sem_t* handle, uint8_t maxCount); +protected: + sem_t handle; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */ diff --git a/osal/linux/CountingSemaphore.cpp b/osal/linux/CountingSemaphore.cpp new file mode 100644 index 00000000..dfc4d801 --- /dev/null +++ b/osal/linux/CountingSemaphore.cpp @@ -0,0 +1,54 @@ +#include +#include + +CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount): + maxCount(maxCount), initCount(initCount) { + if(initCount > maxCount) { + sif::error << "CountingSemaphoreUsingTask: Max count bigger than " + "intial cout. Setting initial count to max count." << std::endl; + initCount = maxCount; + } + + initSemaphore(initCount); +} + +CountingSemaphore::CountingSemaphore(CountingSemaphore&& other): + maxCount(other.maxCount), initCount(other.initCount) { + initSemaphore(initCount); +} + +CountingSemaphore& CountingSemaphore::operator =( + CountingSemaphore&& other) { + initSemaphore(other.initCount); + return * this; +} + +ReturnValue_t CountingSemaphore::release() { + ReturnValue_t result = checkCount(&handle, maxCount); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return CountingSemaphore::release(&this->handle); +} + +ReturnValue_t CountingSemaphore::release(sem_t* handle) { + int result = sem_post(handle); + if(result == 0) { + return HasReturnvaluesIF::RETURN_OK; + } + + switch(errno) { + case(EINVAL): + // Semaphore invalid + return SemaphoreIF::SEMAPHORE_INVALID; + case(EOVERFLOW): + // SEM_MAX_VALUE overflow. This should never happen + default: + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +uint8_t CountingSemaphore::getMaxCount() const { + return maxCount; +} + diff --git a/osal/linux/CountingSemaphore.h b/osal/linux/CountingSemaphore.h new file mode 100644 index 00000000..ba606595 --- /dev/null +++ b/osal/linux/CountingSemaphore.h @@ -0,0 +1,37 @@ +#ifndef FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_ +#define FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_ +#include + +/** + * @brief Counting semaphores, which can be acquired more than once. + * @details + * See: https://www.freertos.org/CreateCounting.html + * API of counting semaphores is almost identical to binary semaphores, + * so we just inherit from binary semaphore and provide the respective + * constructors. + */ +class CountingSemaphore: public BinarySemaphore { +public: + CountingSemaphore(const uint8_t maxCount, uint8_t initCount); + //! @brief Copy ctor, disabled + CountingSemaphore(const CountingSemaphore&) = delete; + //! @brief Copy assignment, disabled + CountingSemaphore& operator=(const CountingSemaphore&) = delete; + //! @brief Move ctor + CountingSemaphore (CountingSemaphore &&); + //! @brief Move assignment + CountingSemaphore & operator=(CountingSemaphore &&); + + ReturnValue_t release() override; + static ReturnValue_t release(sem_t* sem); + /* Same API as binary semaphore otherwise. acquire() can be called + * until there are not semaphores left and release() can be called + * until maxCount is reached. */ + + uint8_t getMaxCount() const; +private: + const uint8_t maxCount; + uint8_t initCount = 0; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */ diff --git a/osal/linux/SemaphoreFactory.cpp b/osal/linux/SemaphoreFactory.cpp new file mode 100644 index 00000000..5aec84ea --- /dev/null +++ b/osal/linux/SemaphoreFactory.cpp @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +const uint32_t SemaphoreIF::NO_TIMEOUT = 0; +const uint32_t SemaphoreIF::MAX_TIMEOUT = 0xFFFFFFFF; + +SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; + +SemaphoreFactory::SemaphoreFactory() { +} + +SemaphoreFactory::~SemaphoreFactory() { + delete factoryInstance; +} + +SemaphoreFactory* SemaphoreFactory::instance() { + if (factoryInstance == nullptr){ + factoryInstance = new SemaphoreFactory(); + } + return SemaphoreFactory::factoryInstance; +} + +SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t arguments) { + return new BinarySemaphore(); +} + +SemaphoreIF* SemaphoreFactory::createCountingSemaphore(const uint8_t maxCount, + uint8_t initCount, uint32_t arguments) { + return new CountingSemaphore(maxCount, initCount); +} + +void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { + delete semaphore; +} From 6c9f157d2c657874990c579bea920bc2c0a6c3e5 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 13:34:17 +0200 Subject: [PATCH 077/653] added fw class ids --- returnvalues/FwClassIds.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/returnvalues/FwClassIds.h b/returnvalues/FwClassIds.h index d21861c0..120d8b8c 100644 --- a/returnvalues/FwClassIds.h +++ b/returnvalues/FwClassIds.h @@ -24,6 +24,7 @@ enum { MEMORY_HELPER, //MH SERIALIZE_IF, //SE FIXED_MAP, //FM + FIXED_MULTIMAP, //FMM HAS_HEALTH_IF, //HHI FIFO_CLASS, //FF MESSAGE_PROXY, //MQP @@ -59,6 +60,7 @@ enum { SGP4PROPAGATOR_CLASS, //SGP4 53 MUTEX_IF, //MUX 54 MESSAGE_QUEUE_IF,//MQI 55 + SEMAPHORE_IF, //SPH 56 FW_CLASS_ID_COUNT //is actually count + 1 ! }; From 73183b39efaa3de9e7a295100dace8fb82aa069f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 13:37:13 +0200 Subject: [PATCH 078/653] added new casts otherwise i cant compile with new freertos version --- osal/FreeRTOS/MessageQueue.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osal/FreeRTOS/MessageQueue.cpp b/osal/FreeRTOS/MessageQueue.cpp index e5da0442..18e7aa3d 100644 --- a/osal/FreeRTOS/MessageQueue.cpp +++ b/osal/FreeRTOS/MessageQueue.cpp @@ -97,7 +97,8 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, bool ignoreFault) { message->setSender(sentFrom); - BaseType_t result = xQueueSendToBack(reinterpret_cast(sendTo),reinterpret_cast(message->getBuffer()), 0); + BaseType_t result = xQueueSendToBack(reinterpret_cast(sendTo), + reinterpret_cast(message->getBuffer()), 0); if (result != pdPASS) { if (!ignoreFault) { InternalErrorReporterIF* internalErrorReporter = objectManager->get( From 8f563b7b21af065208e34b1705533bfc700cd9e5 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 14:02:14 +0200 Subject: [PATCH 079/653] added retvals for mutex --- osal/FreeRTOS/Mutex.cpp | 18 ++++++++---------- osal/FreeRTOS/Mutex.h | 25 +++++++++++++++---------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/osal/FreeRTOS/Mutex.cpp b/osal/FreeRTOS/Mutex.cpp index 7c511091..e304d60e 100644 --- a/osal/FreeRTOS/Mutex.cpp +++ b/osal/FreeRTOS/Mutex.cpp @@ -1,4 +1,4 @@ -#include "Mutex.h" +#include #include @@ -6,7 +6,9 @@ const uint32_t MutexIF::NO_TIMEOUT = 0; Mutex::Mutex() { handle = xSemaphoreCreateMutex(); - //TODO print error + if(handle == NULL) { + sif::error << "Mutex creation failure" << std::endl; + } } Mutex::~Mutex() { @@ -18,8 +20,7 @@ Mutex::~Mutex() { ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { if (handle == 0) { - //TODO Does not exist - return HasReturnvaluesIF::RETURN_FAILED; + return MutexIF::MUTEX_NOT_FOUND; } TickType_t timeout = portMAX_DELAY; if (timeoutMs != NO_TIMEOUT) { @@ -30,21 +31,18 @@ ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { if (returncode == pdPASS) { return HasReturnvaluesIF::RETURN_OK; } else { - //TODO could not be acquired/timeout - return HasReturnvaluesIF::RETURN_FAILED; + return MutexIF::MUTEX_TIMEOUT; } } ReturnValue_t Mutex::unlockMutex() { if (handle == 0) { - //TODO Does not exist - return HasReturnvaluesIF::RETURN_FAILED; + return MutexIF::MUTEX_NOT_FOUND; } BaseType_t returncode = xSemaphoreGive(handle); if (returncode == pdPASS) { return HasReturnvaluesIF::RETURN_OK; } else { - //TODO is not owner - return HasReturnvaluesIF::RETURN_FAILED; + return MutexIF::CURR_THREAD_DOES_NOT_OWN_MUTEX; } } diff --git a/osal/FreeRTOS/Mutex.h b/osal/FreeRTOS/Mutex.h index 91f29585..e04cd20d 100644 --- a/osal/FreeRTOS/Mutex.h +++ b/osal/FreeRTOS/Mutex.h @@ -1,22 +1,27 @@ -#ifndef OS_RTEMS_MUTEX_H_ -#define OS_RTEMS_MUTEX_H_ +#ifndef FRAMEWORK_FREERTOS_MUTEX_H_ +#define FRAMEWORK_FREERTOS_MUTEX_H_ #include +#include +#include -#include -#include "semphr.h" - - - +/** + * @brief OS component to implement MUTual EXclusion + * + * @details + * Mutexes are binary semaphores which include a priority inheritance mechanism. + * Documentation: https://www.freertos.org/Real-time-embedded-RTOS-mutexes.html + * @ingroup osal + */ class Mutex : public MutexIF { public: Mutex(); ~Mutex(); - ReturnValue_t lockMutex(uint32_t timeoutMs); - ReturnValue_t unlockMutex(); + ReturnValue_t lockMutex(uint32_t timeoutMs) override; + ReturnValue_t unlockMutex() override; private: SemaphoreHandle_t handle; }; -#endif /* OS_RTEMS_MUTEX_H_ */ +#endif /* FRAMEWORK_FREERTOS_MUTEX_H_ */ From 2eba8655641e0ef51d085f4da52b3a5ecee4b478 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 14:03:39 +0200 Subject: [PATCH 080/653] some minor form corrections --- ipc/MutexHelper.h | 4 ++-- ipc/MutexIF.h | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ipc/MutexHelper.h b/ipc/MutexHelper.h index f76ccec4..671cd5a6 100644 --- a/ipc/MutexHelper.h +++ b/ipc/MutexHelper.h @@ -10,11 +10,11 @@ public: internalMutex(mutex) { ReturnValue_t status = mutex->lockMutex(timeoutMs); if(status != HasReturnvaluesIF::RETURN_OK){ - sif::error << "MutexHelper: Lock of Mutex failed " << status << std::endl; + sif::error << "MutexHelper: Lock of Mutex failed " << + status << std::endl; } } - ~MutexHelper() { internalMutex->unlockMutex(); } diff --git a/ipc/MutexIF.h b/ipc/MutexIF.h index 35786d6a..a4aff1cd 100644 --- a/ipc/MutexIF.h +++ b/ipc/MutexIF.h @@ -3,6 +3,13 @@ #include +/** + * @brief Common interface for OS Mutex objects which provide MUTual EXclusion. + * + * @details https://en.wikipedia.org/wiki/Lock_(computer_science) + * @ingroup osal + * @ingroup interface + */ class MutexIF { public: static const uint32_t NO_TIMEOUT; //!< Needs to be defined in implementation. From 896e7f15dc9e4e4ababcf1283e5c6be460780d8a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 14:16:44 +0200 Subject: [PATCH 081/653] addd new timeout value --- ipc/MutexIF.h | 2 +- osal/FreeRTOS/Mutex.cpp | 18 +++++++++++------- osal/FreeRTOS/Mutex.h | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/ipc/MutexIF.h b/ipc/MutexIF.h index a4aff1cd..dcb1cf33 100644 --- a/ipc/MutexIF.h +++ b/ipc/MutexIF.h @@ -13,7 +13,7 @@ class MutexIF { public: static const uint32_t NO_TIMEOUT; //!< Needs to be defined in implementation. - + static const uint32_t MAX_TIMEOUT; static const uint8_t INTERFACE_ID = CLASS_ID::MUTEX_IF; /** * The system lacked the necessary resources (other than memory) to initialize another mutex. diff --git a/osal/FreeRTOS/Mutex.cpp b/osal/FreeRTOS/Mutex.cpp index e304d60e..cc2f865f 100644 --- a/osal/FreeRTOS/Mutex.cpp +++ b/osal/FreeRTOS/Mutex.cpp @@ -3,27 +3,31 @@ #include const uint32_t MutexIF::NO_TIMEOUT = 0; +const uint32_t MutexIF::MAX_TIMEOUT = portMAX_DELAY; Mutex::Mutex() { handle = xSemaphoreCreateMutex(); - if(handle == NULL) { - sif::error << "Mutex creation failure" << std::endl; + if(handle == nullptr) { + sif::error << "Mutex: Creation failure" << std::endl; } } Mutex::~Mutex() { - if (handle != 0) { + if (handle != nullptr) { vSemaphoreDelete(handle); } } ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { - if (handle == 0) { + if (handle == nullptr) { return MutexIF::MUTEX_NOT_FOUND; } - TickType_t timeout = portMAX_DELAY; - if (timeoutMs != NO_TIMEOUT) { + TickType_t timeout = MutexIF::NO_TIMEOUT; + if(timeoutMs == MutexIF::MAX_TIMEOUT) { + timeout = MutexIF::MAX_TIMEOUT; + } + else if(timeoutMs > MutexIF::NO_TIMEOUT){ timeout = pdMS_TO_TICKS(timeoutMs); } @@ -36,7 +40,7 @@ ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { } ReturnValue_t Mutex::unlockMutex() { - if (handle == 0) { + if (handle == nullptr) { return MutexIF::MUTEX_NOT_FOUND; } BaseType_t returncode = xSemaphoreGive(handle); diff --git a/osal/FreeRTOS/Mutex.h b/osal/FreeRTOS/Mutex.h index e04cd20d..90e82467 100644 --- a/osal/FreeRTOS/Mutex.h +++ b/osal/FreeRTOS/Mutex.h @@ -18,7 +18,7 @@ class Mutex : public MutexIF { public: Mutex(); ~Mutex(); - ReturnValue_t lockMutex(uint32_t timeoutMs) override; + ReturnValue_t lockMutex(uint32_t timeoutMs = MutexIF::MAX_TIMEOUT) override; ReturnValue_t unlockMutex() override; private: SemaphoreHandle_t handle; From 8af5a32f1d3f3376cb229b85a3d742b51bec0ef3 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 16:37:46 +0200 Subject: [PATCH 082/653] new store accessor classes implementation of local pool and pool manager extracted into tpp file. store_address_t definition extracted in separate file to avoid circular includes by using forward declarations --- storagemanager/LocalPool.h | 389 ++++++----------------------- storagemanager/LocalPool.tpp | 300 ++++++++++++++++++++++ storagemanager/PoolManager.h | 96 ++----- storagemanager/PoolManager.tpp | 47 ++++ storagemanager/StorageAccessor.cpp | 155 ++++++++++++ storagemanager/StorageAccessor.h | 151 +++++++++++ storagemanager/StorageManagerIF.h | 118 ++++----- storagemanager/storeAddress.h | 54 ++++ 8 files changed, 868 insertions(+), 442 deletions(-) create mode 100644 storagemanager/LocalPool.tpp create mode 100644 storagemanager/PoolManager.tpp create mode 100644 storagemanager/StorageAccessor.cpp create mode 100644 storagemanager/StorageAccessor.h create mode 100644 storagemanager/storeAddress.h diff --git a/storagemanager/LocalPool.h b/storagemanager/LocalPool.h index 5104be2e..c155f918 100644 --- a/storagemanager/LocalPool.h +++ b/storagemanager/LocalPool.h @@ -1,26 +1,18 @@ #ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ #define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ -/** - * @file LocalPool - * - * @date 02.02.2012 - * @author Bastian Baetz - * - * @brief This file contains the definition of the LocalPool class. - */ - #include #include #include #include #include -#include +#include +#include /** * @brief The LocalPool class provides an intermediate data storage with * a fixed pool size policy. - * \details The class implements the StorageManagerIF interface. While the + * @details The class implements the StorageManagerIF interface. While the * total number of pools is fixed, the element sizes in one pool and * the number of pool elements per pool are set on construction. * The full amount of memory is allocated on construction. @@ -39,7 +31,71 @@ public: * @brief This definition generally sets the number of different sized pools. * @details This must be less than the maximum number of pools (currently 0xff). */ -// static const uint32_t NUMBER_OF_POOLS; + // static const uint32_t NUMBER_OF_POOLS; + /** + * @brief This is the default constructor for a pool manager instance. + * @details By passing two arrays of size NUMBER_OF_POOLS, the constructor + * allocates memory (with \c new) for store and size_list. These + * regions are all set to zero on start up. + * @param setObjectId The object identifier to be set. This allows for + * multiple instances of LocalPool in the system. + * @param element_sizes An array of size NUMBER_OF_POOLS in which the size + * of a single element in each pool is determined. + * The sizes must be provided in ascending order. + * + * @param n_elements An array of size NUMBER_OF_POOLS in which the + * number of elements for each pool is determined. + * The position of these values correspond to those in + * element_sizes. + * @param registered Register the pool in object manager or not. Default is false (local pool). + * @param spillsToHigherPools + * A variable to determine whether higher n pools are used if the store is full. + */ + LocalPool(object_id_t setObjectId, + const uint16_t element_sizes[NUMBER_OF_POOLS], + const uint16_t n_elements[NUMBER_OF_POOLS], + bool registered = false, + bool spillsToHigherPools = false); + /** + * @brief In the LocalPool's destructor all allocated memory is freed. + */ + virtual ~LocalPool(void); + + /** + * Documentation: See StorageManagerIF.h + */ + ReturnValue_t addData(store_address_t* storageId, const uint8_t * data, + size_t size, bool ignoreFault = false) override; + ReturnValue_t getFreeElement(store_address_t* storageId,const size_t size, + uint8_t** p_data, bool ignoreFault = false) override; + + ConstAccessorPair getData(store_address_t packet_id) override; + ReturnValue_t getData(store_address_t packet_id, ConstStorageAccessor&) override; + ReturnValue_t getData(store_address_t packet_id, const uint8_t** packet_ptr, + size_t * size) override; + + AccessorPair modifyData(store_address_t packet_id) override; + ReturnValue_t modifyData(store_address_t packet_id, StorageAccessor&) override; + ReturnValue_t modifyData(store_address_t packet_id, uint8_t** packet_ptr, + size_t * size) override; + + virtual ReturnValue_t deleteData(store_address_t) override; + virtual ReturnValue_t deleteData(uint8_t* ptr, size_t size, + store_address_t* storeId = NULL) override; + void clearStore() override; + ReturnValue_t initialize() override; +protected: + /** + * With this helper method, a free element of \c size is reserved. + * @param size The minimum packet size that shall be reserved. + * @param[out] address Storage ID of the reserved data. + * @return - #RETURN_OK on success, + * - the return codes of #getPoolIndex or #findEmpty otherwise. + */ + virtual ReturnValue_t reserveSpace(const uint32_t size, + store_address_t* address, bool ignoreFault); + + InternalErrorReporterIF *internalErrorReporter; private: /** * Indicates that this element is free. @@ -78,7 +134,7 @@ private: * @param data The data to be stored. * @param size The size of the data to be stored. */ - void write(store_address_t packet_id, const uint8_t* data, uint32_t size); + void write(store_address_t packet_id, const uint8_t* data, size_t size); /** * @brief A helper method to read the element size of a certain pool. * @param pool_index The pool in which to look. @@ -101,7 +157,8 @@ private: * @return - #RETURN_OK on success, * - #DATA_TOO_LARGE otherwise. */ - ReturnValue_t getPoolIndex(uint32_t packet_size, uint16_t* poolIndex, uint16_t startAtIndex = 0); + ReturnValue_t getPoolIndex(size_t packet_size, uint16_t* poolIndex, + uint16_t startAtIndex = 0); /** * @brief This helper method calculates the true array position in store * of a given packet id. @@ -121,310 +178,8 @@ private: * - #DATA_STORAGE_FULL if the store is full */ ReturnValue_t findEmpty(uint16_t pool_index, uint16_t* element); -protected: - /** - * With this helper method, a free element of \c size is reserved. - * @param size The minimum packet size that shall be reserved. - * @param[out] address Storage ID of the reserved data. - * @return - #RETURN_OK on success, - * - the return codes of #getPoolIndex or #findEmpty otherwise. - */ - virtual ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault); - - InternalErrorReporterIF *internalErrorReporter; -public: - /** - * @brief This is the default constructor for a pool manager instance. - * @details By passing two arrays of size NUMBER_OF_POOLS, the constructor - * allocates memory (with \c new) for store and size_list. These - * regions are all set to zero on start up. - * @param setObjectId The object identifier to be set. This allows for - * multiple instances of LocalPool in the system. - * @param element_sizes An array of size NUMBER_OF_POOLS in which the size - * of a single element in each pool is determined. - * The sizes must be provided in ascending order. - * - * @param n_elements An array of size NUMBER_OF_POOLS in which the - * number of elements for each pool is determined. - * The position of these values correspond to those in - * element_sizes. - * @param registered Register the pool in object manager or not. Default is false (local pool). - */ - LocalPool(object_id_t setObjectId, - const uint16_t element_sizes[NUMBER_OF_POOLS], - const uint16_t n_elements[NUMBER_OF_POOLS], - bool registered = false, - bool spillsToHigherPools = false); - /** - * @brief In the LocalPool's destructor all allocated memory is freed. - */ - virtual ~LocalPool(void); - ReturnValue_t addData(store_address_t* storageId, const uint8_t * data, - uint32_t size, bool ignoreFault = false); - - /** - * With this helper method, a free element of \c size is reserved. - * - * @param size The minimum packet size that shall be reserved. - * @return Returns the storage identifier within the storage or - * StorageManagerIF::INVALID_ADDRESS (in raw). - */ - ReturnValue_t getFreeElement(store_address_t* storageId, - const uint32_t size, uint8_t** p_data, bool ignoreFault = false); - ReturnValue_t getData(store_address_t packet_id, const uint8_t** packet_ptr, - uint32_t* size); - ReturnValue_t modifyData(store_address_t packet_id, uint8_t** packet_ptr, - uint32_t* size); - virtual ReturnValue_t deleteData(store_address_t); - virtual ReturnValue_t deleteData(uint8_t* ptr, uint32_t size, - store_address_t* storeId = NULL); - void clearStore(); - ReturnValue_t initialize(); }; -template -inline ReturnValue_t LocalPool::findEmpty(uint16_t pool_index, - uint16_t* element) { - ReturnValue_t status = DATA_STORAGE_FULL; - for (uint16_t foundElement = 0; foundElement < n_elements[pool_index]; - foundElement++) { - if (size_list[pool_index][foundElement] == STORAGE_FREE) { - *element = foundElement; - status = RETURN_OK; - break; - } - } - return status; -} - -template -inline void LocalPool::write(store_address_t packet_id, - const uint8_t* data, uint32_t size) { - uint8_t* ptr; - uint32_t packet_position = getRawPosition(packet_id); - - //check size? -> Not necessary, because size is checked before calling this function. - ptr = &store[packet_id.pool_index][packet_position]; - memcpy(ptr, data, size); - size_list[packet_id.pool_index][packet_id.packet_index] = size; -} - -//Returns page size of 0 in case store_index is illegal -template -inline uint32_t LocalPool::getPageSize(uint16_t pool_index) { - if (pool_index < NUMBER_OF_POOLS) { - return element_sizes[pool_index]; - } else { - return 0; - } -} - -template -inline ReturnValue_t LocalPool::getPoolIndex( - uint32_t packet_size, uint16_t* poolIndex, uint16_t startAtIndex) { - for (uint16_t n = startAtIndex; n < NUMBER_OF_POOLS; n++) { -// debug << "LocalPool " << getObjectId() << "::getPoolIndex: Pool: " << n << ", Element Size: " << element_sizes[n] << std::endl; - if (element_sizes[n] >= packet_size) { - *poolIndex = n; - return RETURN_OK; - } - } - return DATA_TOO_LARGE; -} - -template -inline uint32_t LocalPool::getRawPosition( - store_address_t packet_id) { - return packet_id.packet_index * element_sizes[packet_id.pool_index]; -} - -template -inline ReturnValue_t LocalPool::reserveSpace( - const uint32_t size, store_address_t* address, bool ignoreFault) { - ReturnValue_t status = getPoolIndex(size, &address->pool_index); - if (status != RETURN_OK) { - sif::error << "LocalPool( " << std::hex << getObjectId() << std::dec - << " )::reserveSpace: Packet too large." << std::endl; - return status; - } - status = findEmpty(address->pool_index, &address->packet_index); - while (status != RETURN_OK && spillsToHigherPools) { - status = getPoolIndex(size, &address->pool_index, address->pool_index + 1); - if (status != RETURN_OK) { - //We don't find any fitting pool anymore. - break; - } - status = findEmpty(address->pool_index, &address->packet_index); - } - if (status == RETURN_OK) { -// if (getObjectId() == objects::IPC_STORE && address->pool_index >= 3) { -// debug << "Reserve: Pool: " << std::dec << address->pool_index << " Index: " << address->packet_index << std::endl; -// } - - size_list[address->pool_index][address->packet_index] = size; - } else { - if (!ignoreFault) { - internalErrorReporter->storeFull(); - } -// error << "LocalPool( " << std::hex << getObjectId() << std::dec -// << " )::reserveSpace: Packet store is full." << std::endl; - } - return status; -} - -template -inline LocalPool::LocalPool(object_id_t setObjectId, - const uint16_t element_sizes[NUMBER_OF_POOLS], - const uint16_t n_elements[NUMBER_OF_POOLS], bool registered, bool spillsToHigherPools) : - SystemObject(setObjectId, registered), spillsToHigherPools(spillsToHigherPools), internalErrorReporter(NULL) { - for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { - this->element_sizes[n] = element_sizes[n]; - this->n_elements[n] = n_elements[n]; - store[n] = new uint8_t[n_elements[n] * element_sizes[n]]; - size_list[n] = new uint32_t[n_elements[n]]; - memset(store[n], 0x00, (n_elements[n] * element_sizes[n])); - memset(size_list[n], STORAGE_FREE, (n_elements[n] * sizeof(**size_list))); //TODO checkme - } -} - -template -inline LocalPool::~LocalPool(void) { - for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { - delete[] store[n]; - delete[] size_list[n]; - } -} - -template -inline ReturnValue_t LocalPool::addData( - store_address_t* storageId, const uint8_t* data, uint32_t size, bool ignoreFault) { - ReturnValue_t status = reserveSpace(size, storageId, ignoreFault); - if (status == RETURN_OK) { - write(*storageId, data, size); - } - return status; -} - -template -inline ReturnValue_t LocalPool::getFreeElement( - store_address_t* storageId, const uint32_t size, uint8_t** p_data, bool ignoreFault) { - ReturnValue_t status = reserveSpace(size, storageId, ignoreFault); - if (status == RETURN_OK) { - *p_data = &store[storageId->pool_index][getRawPosition(*storageId)]; - } else { - *p_data = NULL; - } - return status; -} - -template -inline ReturnValue_t LocalPool::getData( - store_address_t packet_id, const uint8_t** packet_ptr, uint32_t* size) { - uint8_t* tempData = NULL; - ReturnValue_t status = modifyData(packet_id, &tempData, size); - *packet_ptr = tempData; - return status; -} - -template -inline ReturnValue_t LocalPool::modifyData(store_address_t packet_id, - uint8_t** packet_ptr, uint32_t* size) { - ReturnValue_t status = RETURN_FAILED; - if (packet_id.pool_index >= NUMBER_OF_POOLS) { - return ILLEGAL_STORAGE_ID; - } - if ((packet_id.packet_index >= n_elements[packet_id.pool_index])) { - return ILLEGAL_STORAGE_ID; - } - if (size_list[packet_id.pool_index][packet_id.packet_index] - != STORAGE_FREE) { - uint32_t packet_position = getRawPosition(packet_id); - *packet_ptr = &store[packet_id.pool_index][packet_position]; - *size = size_list[packet_id.pool_index][packet_id.packet_index]; - status = RETURN_OK; - } else { - status = DATA_DOES_NOT_EXIST; - } - return status; -} - -template -inline ReturnValue_t LocalPool::deleteData( - store_address_t packet_id) { - -// if (getObjectId() == objects::IPC_STORE && packet_id.pool_index >= 3) { -// debug << "Delete: Pool: " << std::dec << packet_id.pool_index << " Index: " << packet_id.packet_index << std::endl; -// } - ReturnValue_t status = RETURN_OK; - uint32_t page_size = getPageSize(packet_id.pool_index); - if ((page_size != 0) - && (packet_id.packet_index < n_elements[packet_id.pool_index])) { - uint16_t packet_position = getRawPosition(packet_id); - uint8_t* ptr = &store[packet_id.pool_index][packet_position]; - memset(ptr, 0, page_size); - //Set free list - size_list[packet_id.pool_index][packet_id.packet_index] = STORAGE_FREE; - } else { - //pool_index or packet_index is too large - sif::error << "LocalPool:deleteData failed." << std::endl; - status = ILLEGAL_STORAGE_ID; - } - return status; -} - -template -inline void LocalPool::clearStore() { - for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { - memset(size_list[n], STORAGE_FREE, (n_elements[n] * sizeof(**size_list)));//TODO checkme - } -} - -template -inline ReturnValue_t LocalPool::deleteData(uint8_t* ptr, - uint32_t size, store_address_t* storeId) { - store_address_t localId; - ReturnValue_t result = ILLEGAL_ADDRESS; - for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { - //Not sure if new allocates all stores in order. so better be careful. - if ((store[n] <= ptr) && (&store[n][n_elements[n]*element_sizes[n]]) > ptr) { - localId.pool_index = n; - uint32_t deltaAddress = ptr - store[n]; - //Getting any data from the right "block" is ok. This is necessary, as IF's sometimes don't point to the first element of an object. - localId.packet_index = deltaAddress / element_sizes[n]; - result = deleteData(localId); -// if (deltaAddress % element_sizes[n] != 0) { -// error << "Pool::deleteData: address not aligned!" << std::endl; -// } - break; - } - } - if (storeId != NULL) { - *storeId = localId; - } - return result; -} - -template -inline ReturnValue_t LocalPool::initialize() { - ReturnValue_t result = SystemObject::initialize(); - if (result != RETURN_OK) { - return result; - } - internalErrorReporter = objectManager->get(objects::INTERNAL_ERROR_REPORTER); - if (internalErrorReporter == NULL){ - return RETURN_FAILED; - } - - //Check if any pool size is large than the maximum allowed. - for (uint8_t count = 0; count < NUMBER_OF_POOLS; count++) { - if (element_sizes[count] >= STORAGE_FREE) { - sif::error - << "LocalPool::initialize: Pool is too large! Max. allowed size is: " - << (STORAGE_FREE - 1) << std::endl; - return RETURN_FAILED; - } - } - return RETURN_OK; -} +#include #endif /* FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ */ diff --git a/storagemanager/LocalPool.tpp b/storagemanager/LocalPool.tpp new file mode 100644 index 00000000..32724bd8 --- /dev/null +++ b/storagemanager/LocalPool.tpp @@ -0,0 +1,300 @@ +#ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ +#define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ + +template +inline LocalPool::LocalPool(object_id_t setObjectId, + const uint16_t element_sizes[NUMBER_OF_POOLS], + const uint16_t n_elements[NUMBER_OF_POOLS], bool registered, + bool spillsToHigherPools) : + SystemObject(setObjectId, registered), internalErrorReporter(nullptr), + spillsToHigherPools(spillsToHigherPools) +{ + for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { + this->element_sizes[n] = element_sizes[n]; + this->n_elements[n] = n_elements[n]; + store[n] = new uint8_t[n_elements[n] * element_sizes[n]]; + size_list[n] = new uint32_t[n_elements[n]]; + memset(store[n], 0x00, (n_elements[n] * element_sizes[n])); + //TODO checkme + memset(size_list[n], STORAGE_FREE, (n_elements[n] * sizeof(**size_list))); + } +} + + +template +inline ReturnValue_t LocalPool::findEmpty(uint16_t pool_index, + uint16_t* element) { + ReturnValue_t status = DATA_STORAGE_FULL; + for (uint16_t foundElement = 0; foundElement < n_elements[pool_index]; + foundElement++) { + if (size_list[pool_index][foundElement] == STORAGE_FREE) { + *element = foundElement; + status = RETURN_OK; + break; + } + } + return status; +} + +template +inline void LocalPool::write(store_address_t packet_id, + const uint8_t* data, size_t size) { + uint8_t* ptr; + uint32_t packet_position = getRawPosition(packet_id); + + //check size? -> Not necessary, because size is checked before calling this function. + ptr = &store[packet_id.pool_index][packet_position]; + memcpy(ptr, data, size); + size_list[packet_id.pool_index][packet_id.packet_index] = size; +} + +//Returns page size of 0 in case store_index is illegal +template +inline uint32_t LocalPool::getPageSize(uint16_t pool_index) { + if (pool_index < NUMBER_OF_POOLS) { + return element_sizes[pool_index]; + } else { + return 0; + } +} + +template +inline ReturnValue_t LocalPool::getPoolIndex( + size_t packet_size, uint16_t* poolIndex, uint16_t startAtIndex) { + for (uint16_t n = startAtIndex; n < NUMBER_OF_POOLS; n++) { + //debug << "LocalPool " << getObjectId() << "::getPoolIndex: Pool: " << + // n << ", Element Size: " << element_sizes[n] << std::endl; + if (element_sizes[n] >= packet_size) { + *poolIndex = n; + return RETURN_OK; + } + } + return DATA_TOO_LARGE; +} + +template +inline uint32_t LocalPool::getRawPosition( + store_address_t packet_id) { + return packet_id.packet_index * element_sizes[packet_id.pool_index]; +} + +template +inline ReturnValue_t LocalPool::reserveSpace( + const uint32_t size, store_address_t* address, bool ignoreFault) { + ReturnValue_t status = getPoolIndex(size, &address->pool_index); + if (status != RETURN_OK) { + sif::error << "LocalPool( " << std::hex << getObjectId() << std::dec + << " )::reserveSpace: Packet too large." << std::endl; + return status; + } + status = findEmpty(address->pool_index, &address->packet_index); + while (status != RETURN_OK && spillsToHigherPools) { + status = getPoolIndex(size, &address->pool_index, address->pool_index + 1); + if (status != RETURN_OK) { + //We don't find any fitting pool anymore. + break; + } + status = findEmpty(address->pool_index, &address->packet_index); + } + if (status == RETURN_OK) { + // if (getObjectId() == objects::IPC_STORE && address->pool_index >= 3) { + // debug << "Reserve: Pool: " << std::dec << address->pool_index << + // " Index: " << address->packet_index << std::endl; + // } + + size_list[address->pool_index][address->packet_index] = size; + } else { + if (!ignoreFault and internalErrorReporter != nullptr) { + internalErrorReporter->storeFull(); + } + // error << "LocalPool( " << std::hex << getObjectId() << std::dec + // << " )::reserveSpace: Packet store is full." << std::endl; + } + return status; +} + +template +inline LocalPool::~LocalPool(void) { + for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { + delete[] store[n]; + delete[] size_list[n]; + } +} + +template inline +ReturnValue_t LocalPool::addData(store_address_t* storageId, + const uint8_t* data, size_t size, bool ignoreFault) { + ReturnValue_t status = reserveSpace(size, storageId, ignoreFault); + if (status == RETURN_OK) { + write(*storageId, data, size); + } + return status; +} + +template +inline ReturnValue_t LocalPool::getFreeElement( + store_address_t* storageId, const size_t size, + uint8_t** p_data, bool ignoreFault) { + ReturnValue_t status = reserveSpace(size, storageId, ignoreFault); + if (status == RETURN_OK) { + *p_data = &store[storageId->pool_index][getRawPosition(*storageId)]; + } else { + *p_data = NULL; + } + return status; +} + +template +inline ConstAccessorPair LocalPool::getData( + store_address_t storeId) { + uint8_t* tempData = nullptr; + ConstStorageAccessor constAccessor(storeId, this); + ReturnValue_t status = modifyData(storeId, &tempData, &constAccessor.size_); + constAccessor.constDataPointer = tempData; + return ConstAccessorPair(status, std::move(constAccessor)); +} + +template +inline ReturnValue_t LocalPool::getData(store_address_t storeId, + ConstStorageAccessor& storeAccessor) { + uint8_t* tempData = nullptr; + ReturnValue_t status = modifyData(storeId, &tempData, &storeAccessor.size_); + storeAccessor.assignStore(this); + storeAccessor.constDataPointer = tempData; + return status; +} + +template +inline ReturnValue_t LocalPool::getData( + store_address_t packet_id, const uint8_t** packet_ptr, size_t* size) { + uint8_t* tempData = NULL; + ReturnValue_t status = modifyData(packet_id, &tempData, size); + *packet_ptr = tempData; + return status; +} + +template +inline AccessorPair LocalPool::modifyData( + store_address_t storeId) { + StorageAccessor accessor(storeId, this); + ReturnValue_t status = modifyData(storeId, &accessor.dataPointer, + &accessor.size_); + accessor.assignConstPointer(); + return AccessorPair(status, std::move(accessor)); +} + +template +inline ReturnValue_t LocalPool::modifyData( + store_address_t storeId, StorageAccessor& storeAccessor) { + storeAccessor.assignStore(this); + ReturnValue_t status = modifyData(storeId, &storeAccessor.dataPointer, + &storeAccessor.size_); + storeAccessor.assignConstPointer(); + return status; +} + +template +inline ReturnValue_t LocalPool::modifyData( + store_address_t packet_id, uint8_t** packet_ptr, size_t* size) { + ReturnValue_t status = RETURN_FAILED; + if (packet_id.pool_index >= NUMBER_OF_POOLS) { + return ILLEGAL_STORAGE_ID; + } + if ((packet_id.packet_index >= n_elements[packet_id.pool_index])) { + return ILLEGAL_STORAGE_ID; + } + if (size_list[packet_id.pool_index][packet_id.packet_index] + != STORAGE_FREE) { + uint32_t packet_position = getRawPosition(packet_id); + *packet_ptr = &store[packet_id.pool_index][packet_position]; + *size = size_list[packet_id.pool_index][packet_id.packet_index]; + status = RETURN_OK; + } else { + status = DATA_DOES_NOT_EXIST; + } + return status; +} + +template +inline ReturnValue_t LocalPool::deleteData( + store_address_t packet_id) { + //if (getObjectId() == objects::IPC_STORE && packet_id.pool_index >= 3) { + // debug << "Delete: Pool: " << std::dec << packet_id.pool_index << " Index: " + // << packet_id.packet_index << std::endl; + //} + ReturnValue_t status = RETURN_OK; + uint32_t page_size = getPageSize(packet_id.pool_index); + if ((page_size != 0) + && (packet_id.packet_index < n_elements[packet_id.pool_index])) { + uint16_t packet_position = getRawPosition(packet_id); + uint8_t* ptr = &store[packet_id.pool_index][packet_position]; + memset(ptr, 0, page_size); + //Set free list + size_list[packet_id.pool_index][packet_id.packet_index] = STORAGE_FREE; + } else { + //pool_index or packet_index is too large + sif::error << "LocalPool:deleteData failed." << std::endl; + status = ILLEGAL_STORAGE_ID; + } + return status; +} + +template +inline void LocalPool::clearStore() { + for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { + //TODO checkme + memset(size_list[n], STORAGE_FREE, (n_elements[n] * sizeof(**size_list))); + } +} + +template +inline ReturnValue_t LocalPool::deleteData(uint8_t* ptr, + size_t size, store_address_t* storeId) { + store_address_t localId; + ReturnValue_t result = ILLEGAL_ADDRESS; + for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { + //Not sure if new allocates all stores in order. so better be careful. + if ((store[n] <= ptr) && (&store[n][n_elements[n]*element_sizes[n]]) > ptr) { + localId.pool_index = n; + uint32_t deltaAddress = ptr - store[n]; + // Getting any data from the right "block" is ok. + // This is necessary, as IF's sometimes don't point to the first + // element of an object. + localId.packet_index = deltaAddress / element_sizes[n]; + result = deleteData(localId); + //if (deltaAddress % element_sizes[n] != 0) { + // error << "Pool::deleteData: address not aligned!" << std::endl; + //} + break; + } + } + if (storeId != NULL) { + *storeId = localId; + } + return result; +} + +template +inline ReturnValue_t LocalPool::initialize() { + ReturnValue_t result = SystemObject::initialize(); + if (result != RETURN_OK) { + return result; + } + internalErrorReporter = objectManager->get( + objects::INTERNAL_ERROR_REPORTER); + if (internalErrorReporter == nullptr){ + return ObjectManagerIF::INTERNAL_ERR_REPORTER_UNINIT; + } + + //Check if any pool size is large than the maximum allowed. + for (uint8_t count = 0; count < NUMBER_OF_POOLS; count++) { + if (element_sizes[count] >= STORAGE_FREE) { + sif::error << "LocalPool::initialize: Pool is too large! " + "Max. allowed size is: " << (STORAGE_FREE - 1) << std::endl; + return StorageManagerIF::POOL_TOO_LARGE; + } + } + return RETURN_OK; +} + +#endif diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index 68a7addc..6e353de2 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -1,86 +1,44 @@ -/** - * @file PoolManager - * - * @date 02.02.2012 - * @author Bastian Baetz - * - * @brief This file contains the definition of the PoolManager class. - */ - -#ifndef POOLMANAGER_H_ -#define POOLMANAGER_H_ - +#ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_ +#define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_ #include #include +#include /** * @brief The PoolManager class provides an intermediate data storage with * a fixed pool size policy for inter-process communication. - * \details Uses local pool, but is thread-safe. + * @details Uses local pool calls but is thread safe by protecting the call + * with a lock. */ - -template +template class PoolManager : public LocalPool { +public: + PoolManager(object_id_t setObjectId, + const uint16_t element_sizes[NUMBER_OF_POOLS], + const uint16_t n_elements[NUMBER_OF_POOLS]); + + //! @brief In the PoolManager's destructor all allocated memory is freed. + virtual ~PoolManager(); + + //! @brief LocalPool overrides for thread-safety. Decorator function which + //! wraps LocalPool calls with a mutex protection. + ReturnValue_t deleteData(store_address_t) override; + ReturnValue_t deleteData(uint8_t* buffer, size_t size, + store_address_t* storeId = nullptr) override; protected: - /** - * Overwritten for thread safety. - * Locks during execution. - */ - virtual ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault); + ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address, + bool ignoreFault) override; /** - * \brief The mutex is created in the constructor and makes access mutual exclusive. - * \details Locking and unlocking is done during searching for free slots and deleting existing slots. + * @brief The mutex is created in the constructor and makes + * access mutual exclusive. + * @details Locking and unlocking is done during searching for free slots + * and deleting existing slots. */ - MutexIF* mutex; -public: - PoolManager( object_id_t setObjectId, const uint16_t element_sizes[NUMBER_OF_POOLS], const uint16_t n_elements[NUMBER_OF_POOLS] ); - /** - * @brief In the PoolManager's destructor all allocated memory is freed. - */ - virtual ~PoolManager( void ); - /** - * Overwritten for thread safety. - */ - virtual ReturnValue_t deleteData(store_address_t); - virtual ReturnValue_t deleteData(uint8_t* buffer, uint32_t size, store_address_t* storeId = NULL); + MutexIF* mutex; }; -template -inline ReturnValue_t PoolManager::reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault) { - MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); - ReturnValue_t status = LocalPool::reserveSpace(size,address,ignoreFault); - return status; -} - -template -inline PoolManager::PoolManager(object_id_t setObjectId, - const uint16_t element_sizes[NUMBER_OF_POOLS], - const uint16_t n_elements[NUMBER_OF_POOLS]) : LocalPool(setObjectId, element_sizes, n_elements, true) { - mutex = MutexFactory::instance()->createMutex(); -} - -template -inline PoolManager::~PoolManager(void) { - MutexFactory::instance()->deleteMutex(mutex); -} - -template -inline ReturnValue_t PoolManager::deleteData( - store_address_t packet_id) { - // debug << "PoolManager( " << translateObject(getObjectId()) << " )::deleteData from store " << packet_id.pool_index << ". id is " << packet_id.packet_index << std::endl; - MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); - ReturnValue_t status = LocalPool::deleteData(packet_id); - return status; -} - -template -inline ReturnValue_t PoolManager::deleteData(uint8_t* buffer, uint32_t size, - store_address_t* storeId) { - MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); - ReturnValue_t status = LocalPool::deleteData(buffer, size, storeId); - return status; -} +#include "PoolManager.tpp" #endif /* POOLMANAGER_H_ */ diff --git a/storagemanager/PoolManager.tpp b/storagemanager/PoolManager.tpp new file mode 100644 index 00000000..854e22da --- /dev/null +++ b/storagemanager/PoolManager.tpp @@ -0,0 +1,47 @@ +#ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ +#define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ + +template +inline PoolManager::PoolManager(object_id_t setObjectId, + const uint16_t element_sizes[NUMBER_OF_POOLS], + const uint16_t n_elements[NUMBER_OF_POOLS]) : + LocalPool(setObjectId, element_sizes, n_elements, true) { + mutex = MutexFactory::instance()->createMutex(); +} + +template +inline PoolManager::~PoolManager(void) { + MutexFactory::instance()->deleteMutex(mutex); +} + +template +inline ReturnValue_t PoolManager::reserveSpace( + const uint32_t size, store_address_t* address, bool ignoreFault) { + MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); + ReturnValue_t status = LocalPool::reserveSpace(size, + address,ignoreFault); + return status; +} + +template +inline ReturnValue_t PoolManager::deleteData( + store_address_t packet_id) { + // debug << "PoolManager( " << translateObject(getObjectId()) << + // " )::deleteData from store " << packet_id.pool_index << + // ". id is "<< packet_id.packet_index << std::endl; + MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); + ReturnValue_t status = LocalPool::deleteData(packet_id); + return status; +} + +template +inline ReturnValue_t PoolManager::deleteData(uint8_t* buffer, + size_t size, store_address_t* storeId) { + MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); + ReturnValue_t status = LocalPool::deleteData(buffer, + size, storeId); + return status; +} + +#endif + diff --git a/storagemanager/StorageAccessor.cpp b/storagemanager/StorageAccessor.cpp new file mode 100644 index 00000000..c0c8126b --- /dev/null +++ b/storagemanager/StorageAccessor.cpp @@ -0,0 +1,155 @@ +#include +#include + +ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): + storeId(storeId) {} + +ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId, + StorageManagerIF* store): + storeId(storeId), store(store) { + internalState = AccessState::ASSIGNED; +} + +ConstStorageAccessor::~ConstStorageAccessor() { + if(deleteData and store != nullptr) { + sif::debug << "deleting store data" << std::endl; + store->deleteData(storeId); + } +} + +ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other): + constDataPointer(other.constDataPointer), storeId(other.storeId), + size_(other.size_), store(other.store), deleteData(other.deleteData), + internalState(other.internalState) { + // This prevent premature deletion + other.store = nullptr; +} + +ConstStorageAccessor& ConstStorageAccessor::operator=( + ConstStorageAccessor&& other) { + constDataPointer = other.constDataPointer; + storeId = other.storeId; + store = other.store; + size_ = other.size_; + deleteData = other.deleteData; + this->store = other.store; + // This prevents premature deletion + other.store = nullptr; + return *this; +} + +const uint8_t* ConstStorageAccessor::data() const { + return constDataPointer; +} + +size_t ConstStorageAccessor::size() const { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + } + return size_; +} + +ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t *pointer, + size_t maxSize) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(size_ > maxSize) { + sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(constDataPointer, constDataPointer + size_, pointer); + return HasReturnvaluesIF::RETURN_OK; +} + +void ConstStorageAccessor::release() { + deleteData = false; +} + +store_address_t ConstStorageAccessor::getId() const { + return storeId; +} + +void ConstStorageAccessor::print() const { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return; + } + sif::info << "StorageAccessor: Printing data: ["; + for(uint16_t iPool = 0; iPool < size_; iPool++) { + sif::info << std::hex << (int)constDataPointer[iPool]; + if(iPool < size_ - 1){ + sif::info << " , "; + } + } + sif::info << " ] " << std::endl; +} + +void ConstStorageAccessor::assignStore(StorageManagerIF* store) { + internalState = AccessState::ASSIGNED; + this->store = store; +} + + +StorageAccessor::StorageAccessor(store_address_t storeId): + ConstStorageAccessor(storeId) { +} + +StorageAccessor::StorageAccessor(store_address_t storeId, + StorageManagerIF* store): + ConstStorageAccessor(storeId, store) { +} + +StorageAccessor& StorageAccessor::operator =( + StorageAccessor&& other) { + // Call the parent move assignment and also assign own member. + dataPointer = other.dataPointer; + StorageAccessor::operator=(std::move(other)); + return * this; +} + +// Call the parent move ctor and also transfer own member. +StorageAccessor::StorageAccessor(StorageAccessor&& other): + ConstStorageAccessor(std::move(other)), dataPointer(other.dataPointer) { +} + +ReturnValue_t StorageAccessor::getDataCopy(uint8_t *pointer, size_t maxSize) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(size_ > maxSize) { + sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(dataPointer, dataPointer + size_, pointer); + return HasReturnvaluesIF::RETURN_OK; +} + +uint8_t* StorageAccessor::data() { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + } + return dataPointer; +} + +ReturnValue_t StorageAccessor::write(uint8_t *data, size_t size, + uint16_t offset) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(offset + size > size_) { + sif::error << "StorageAccessor: Data too large for pool entry!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(data, data + size, dataPointer + offset); + return HasReturnvaluesIF::RETURN_OK; +} + +void StorageAccessor::assignConstPointer() { + constDataPointer = dataPointer; +} + + diff --git a/storagemanager/StorageAccessor.h b/storagemanager/StorageAccessor.h new file mode 100644 index 00000000..57c9369c --- /dev/null +++ b/storagemanager/StorageAccessor.h @@ -0,0 +1,151 @@ +#ifndef FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ +#define FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ + +#include +#include + +class StorageManagerIF; + +/** + * @brief Helper classes to facilitate safe access to storages which is also + * conforming to RAII principles + * @details + * Accessor class which can be returned by pool manager or passed and set by + * pool managers to have safe access to the pool resources. + * + * These helper can be used together with the StorageManager classes to manage + * access to a storage. It can take care of thread-safety while also providing + * mechanisms to automatically clear storage data. + */ +class ConstStorageAccessor { + //! StorageManager classes have exclusive access to private variables. + template + friend class PoolManager; + template + friend class LocalPool; +public: + /** + * @brief Simple constructor which takes the store ID of the storage + * entry to access. + * @param storeId + */ + ConstStorageAccessor(store_address_t storeId); + ConstStorageAccessor(store_address_t storeId, StorageManagerIF* store); + + /** + * @brief The destructor in default configuration takes care of + * deleting the accessed pool entry and unlocking the mutex + */ + virtual ~ConstStorageAccessor(); + + /** + * @brief Returns a pointer to the read-only data + * @return + */ + const uint8_t* data() const; + + /** + * @brief Copies the read-only data to the supplied pointer + * @param pointer + */ + virtual ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize); + + /** + * @brief Calling this will prevent the Accessor from deleting the data + * when the destructor is called. + */ + void release(); + + /** + * Get the size of the data + * @return + */ + size_t size() const; + + /** + * Get the storage ID. + * @return + */ + store_address_t getId() const; + + void print() const; + + /** + * @brief Move ctor and move assignment allow returning accessors as + * a returnvalue. They prevent resource being free prematurely. + * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ + * move-constructors-and-move-assignment-operators-cpp.md + * @param + * @return + */ + ConstStorageAccessor& operator= (ConstStorageAccessor&&); + ConstStorageAccessor (ConstStorageAccessor&&); + + //! The copy ctor and copy assignemnt should be deleted implicitely + //! according to https://foonathan.net/2019/02/special-member-functions/ + //! but I still deleted them to make it more explicit. (remember rule of 5). + ConstStorageAccessor& operator= (ConstStorageAccessor&) = delete; + ConstStorageAccessor (ConstStorageAccessor&) = delete; +protected: + const uint8_t* constDataPointer = nullptr; + store_address_t storeId; + size_t size_ = 0; + //! Managing pool, has to assign itself. + StorageManagerIF* store = nullptr; + bool deleteData = true; + + enum class AccessState { + UNINIT, + ASSIGNED + }; + //! Internal state for safety reasons. + AccessState internalState = AccessState::UNINIT; + /** + * Used by the pool manager instances to assign themselves to the + * accessor. This is necessary to delete the data when the acessor + * exits the scope ! The internal state will be considered read + * when this function is called, so take care all data is set properly as + * well. + * @param + */ + void assignStore(StorageManagerIF*); +}; + + +/** + * @brief Child class for modifyable data. Also has a normal pointer member. + */ +class StorageAccessor: public ConstStorageAccessor { + //! StorageManager classes have exclusive access to private variables. + template + friend class PoolManager; + template + friend class LocalPool; +public: + StorageAccessor(store_address_t storeId); + StorageAccessor(store_address_t storeId, StorageManagerIF* store); + /** + * @brief Move ctor and move assignment allow returning accessors as + * a returnvalue. They prevent resource being free prematurely. + * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ + * move-constructors-and-move-assignment-operators-cpp.md + * @param + * @return + */ + StorageAccessor& operator= (StorageAccessor&&); + StorageAccessor (StorageAccessor&&); + + ReturnValue_t write(uint8_t *data, size_t size, + uint16_t offset = 0); + uint8_t* data(); + ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize) override; + +private: + //! Non-const pointer for modifyable data. + uint8_t* dataPointer = nullptr; + //! For modifyable data, the const pointer is assigned to the normal + //! pointer by the pool manager so both access functions can be used safely + void assignConstPointer(); +}; + +#endif /* TEST_PROTOTYPES_STORAGEACCESSOR_H_ */ diff --git a/storagemanager/StorageManagerIF.h b/storagemanager/StorageManagerIF.h index a0c2b23d..d5ac5818 100644 --- a/storagemanager/StorageManagerIF.h +++ b/storagemanager/StorageManagerIF.h @@ -3,56 +3,14 @@ #include #include -#include +#include +#include +#include +#include -/** - * This union defines the type that identifies where a data packet is stored in the store. - * It comprises of a raw part to read it as raw value and a structured part to use it in - * pool-like stores. - */ -union store_address_t { - /** - * Default Constructor, initializing to INVALID_ADDRESS - */ - store_address_t():raw(0xFFFFFFFF){} - /** - * Constructor to create an address object using the raw address - * - * @param rawAddress - */ - store_address_t(uint32_t rawAddress):raw(rawAddress){} +using AccessorPair = std::pair; +using ConstAccessorPair = std::pair; - /** - * Constructor to create an address object using pool - * and packet indices - * - * @param poolIndex - * @param packetIndex - */ - store_address_t(uint16_t poolIndex, uint16_t packetIndex): - pool_index(poolIndex),packet_index(packetIndex){} - /** - * A structure with two elements to access the store address pool-like. - */ - struct { - /** - * The index in which pool the packet lies. - */ - uint16_t pool_index; - /** - * The position in the chosen pool. - */ - uint16_t packet_index; - }; - /** - * Alternative access to the raw value. - */ - uint32_t raw; - - bool operator==(const store_address_t& other) const { - return raw == other.raw; - } -}; /** * @brief This class provides an interface for intermediate data storage. @@ -75,6 +33,7 @@ public: static const ReturnValue_t ILLEGAL_STORAGE_ID = MAKE_RETURN_CODE(3); //!< This return code indicates that data was requested with an illegal storage ID. static const ReturnValue_t DATA_DOES_NOT_EXIST = MAKE_RETURN_CODE(4); //!< This return code indicates that the requested ID was valid, but no data is stored there. static const ReturnValue_t ILLEGAL_ADDRESS = MAKE_RETURN_CODE(5); + static const ReturnValue_t POOL_TOO_LARGE = MAKE_RETURN_CODE(6); //!< Pool size too large on initialization. static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::OBSW; static const Event GET_DATA_FAILED = MAKE_EVENT(0, SEVERITY::LOW); @@ -98,7 +57,8 @@ public: * @li RETURN_FAILED if data could not be added. * storageId is unchanged then. */ - virtual ReturnValue_t addData(store_address_t* storageId, const uint8_t * data, uint32_t size, bool ignoreFault = false) = 0; + virtual ReturnValue_t addData(store_address_t* storageId, + const uint8_t * data, size_t size, bool ignoreFault = false) = 0; /** * @brief With deleteData, the storageManager frees the memory region * identified by packet_id. @@ -109,14 +69,37 @@ public: */ virtual ReturnValue_t deleteData(store_address_t packet_id) = 0; /** - * @brief Another deleteData which uses the pointer and size of the stored data to delete the content. + * @brief Another deleteData which uses the pointer and size of the + * stored data to delete the content. * @param buffer Pointer to the data. * @param size Size of data to be stored. * @param storeId Store id of the deleted element (optional) * @return @li RETURN_OK on success. * @li failure code if deletion did not work */ - virtual ReturnValue_t deleteData(uint8_t* buffer, uint32_t size, store_address_t* storeId = NULL) = 0; + virtual ReturnValue_t deleteData(uint8_t* buffer, size_t size, + store_address_t* storeId = nullptr) = 0; + + /** + * @brief Access the data by supplying a store ID. + * @details + * A pair consisting of the retrieval result and an instance of a + * ConstStorageAccessor class is returned + * @param storeId + * @return Pair of return value and a ConstStorageAccessor instance + */ + virtual ConstAccessorPair getData(store_address_t storeId) = 0; + + /** + * @brief Access the data by supplying a store ID and a helper + * instance + * @param storeId + * @param constAccessor Wrapper function to access store data. + * @return + */ + virtual ReturnValue_t getData(store_address_t storeId, + ConstStorageAccessor& constAccessor) = 0; + /** * @brief getData returns an address to data and the size of the data * for a given packet_id. @@ -129,12 +112,34 @@ public: * (e.g. an illegal packet_id was passed). */ virtual ReturnValue_t getData(store_address_t packet_id, - const uint8_t** packet_ptr, uint32_t* size) = 0; + const uint8_t** packet_ptr, size_t* size) = 0; + + /** - * Same as above, but not const and therefore modifiable. + * Modify data by supplying a store ID + * @param storeId + * @return Pair of return value and StorageAccessor helper + */ + virtual AccessorPair modifyData(store_address_t storeId) = 0; + + /** + * Modify data by supplying a store ID and a StorageAccessor helper instance. + * @param storeId + * @param accessor Helper class to access the modifiable data. + * @return + */ + virtual ReturnValue_t modifyData(store_address_t storeId, + StorageAccessor& accessor) = 0; + + /** + * Get pointer and size of modifiable data by supplying the storeId + * @param packet_id + * @param packet_ptr [out] Pointer to pointer of data to set + * @param size [out] Pointer to size to set + * @return */ virtual ReturnValue_t modifyData(store_address_t packet_id, - uint8_t** packet_ptr, uint32_t* size) = 0; + uint8_t** packet_ptr, size_t* size) = 0; /** * This method reserves an element of \c size. * @@ -148,13 +153,14 @@ public: * @li RETURN_FAILED if data could not be added. * storageId is unchanged then. */ - virtual ReturnValue_t getFreeElement(store_address_t* storageId, const uint32_t size, uint8_t** p_data, bool ignoreFault = false ) = 0; + virtual ReturnValue_t getFreeElement(store_address_t* storageId, + const size_t size, uint8_t** p_data, bool ignoreFault = false ) = 0; + /** * Clears the whole store. * Use with care! */ virtual void clearStore() = 0; - }; #endif /* STORAGEMANAGERIF_H_ */ diff --git a/storagemanager/storeAddress.h b/storagemanager/storeAddress.h new file mode 100644 index 00000000..5dd785a3 --- /dev/null +++ b/storagemanager/storeAddress.h @@ -0,0 +1,54 @@ +#ifndef FRAMEWORK_STORAGEMANAGER_STOREADDRESS_H_ +#define FRAMEWORK_STORAGEMANAGER_STOREADDRESS_H_ +#include + +/** + * This union defines the type that identifies where a data packet is + * stored in the store. It comprises of a raw part to read it as raw value and + * a structured part to use it in pool-like stores. + */ +union store_address_t { + /** + * Default Constructor, initializing to INVALID_ADDRESS + */ + store_address_t():raw(0xFFFFFFFF){} + /** + * Constructor to create an address object using the raw address + * + * @param rawAddress + */ + store_address_t(uint32_t rawAddress):raw(rawAddress){} + + /** + * Constructor to create an address object using pool + * and packet indices + * + * @param poolIndex + * @param packetIndex + */ + store_address_t(uint16_t poolIndex, uint16_t packetIndex): + pool_index(poolIndex),packet_index(packetIndex){} + /** + * A structure with two elements to access the store address pool-like. + */ + struct { + /** + * The index in which pool the packet lies. + */ + uint16_t pool_index; + /** + * The position in the chosen pool. + */ + uint16_t packet_index; + }; + /** + * Alternative access to the raw value. + */ + uint32_t raw; + + bool operator==(const store_address_t& other) const { + return raw == other.raw; + } +}; + +#endif /* FRAMEWORK_STORAGEMANAGER_STOREADDRESS_H_ */ From d83181cb0fddcb9ad8f2572151058ca97c2e0a96 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 16:41:23 +0200 Subject: [PATCH 083/653] added author tag --- storagemanager/LocalPool.h | 1 + 1 file changed, 1 insertion(+) diff --git a/storagemanager/LocalPool.h b/storagemanager/LocalPool.h index c155f918..2d61dea5 100644 --- a/storagemanager/LocalPool.h +++ b/storagemanager/LocalPool.h @@ -22,6 +22,7 @@ * 0xFFFF-1 bytes. * It is possible to store empty packets in the pool. * The local pool is NOT thread-safe. + * @author Bastian Baetz */ template From a993223f6e32ed278b5739d407411466bea83c47 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 16:44:31 +0200 Subject: [PATCH 084/653] added include protection --- storagemanager/LocalPool.tpp | 4 ++++ storagemanager/PoolManager.tpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/storagemanager/LocalPool.tpp b/storagemanager/LocalPool.tpp index 32724bd8..dd360a0a 100644 --- a/storagemanager/LocalPool.tpp +++ b/storagemanager/LocalPool.tpp @@ -1,6 +1,10 @@ #ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ #define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ +#ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ +#error Include LocalPool.h instead of LocalPool.tpp!. +#endif + template inline LocalPool::LocalPool(object_id_t setObjectId, const uint16_t element_sizes[NUMBER_OF_POOLS], diff --git a/storagemanager/PoolManager.tpp b/storagemanager/PoolManager.tpp index 854e22da..bdc73ec2 100644 --- a/storagemanager/PoolManager.tpp +++ b/storagemanager/PoolManager.tpp @@ -1,6 +1,10 @@ #ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ #define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ +#ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_ +#error Include LocalPool.h instead of LocalPool.tpp!. +#endif + template inline PoolManager::PoolManager(object_id_t setObjectId, const uint16_t element_sizes[NUMBER_OF_POOLS], From ab17e284052297a4ab94852ecbc331a7add97159 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 16:45:52 +0200 Subject: [PATCH 085/653] include protection output fix --- storagemanager/LocalPool.tpp | 2 +- storagemanager/PoolManager.tpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/storagemanager/LocalPool.tpp b/storagemanager/LocalPool.tpp index dd360a0a..b7fa0da9 100644 --- a/storagemanager/LocalPool.tpp +++ b/storagemanager/LocalPool.tpp @@ -2,7 +2,7 @@ #define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ #ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ -#error Include LocalPool.h instead of LocalPool.tpp!. +#error Include LocalPool.h instead of LocalPool.tpp! #endif template diff --git a/storagemanager/PoolManager.tpp b/storagemanager/PoolManager.tpp index bdc73ec2..97603246 100644 --- a/storagemanager/PoolManager.tpp +++ b/storagemanager/PoolManager.tpp @@ -2,7 +2,7 @@ #define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ #ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_ -#error Include LocalPool.h instead of LocalPool.tpp!. +#error Include LocalPool.h instead of LocalPool.tpp! #endif template From acf037614ff9795ee1bea4875d76415a61388835 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 16:48:53 +0200 Subject: [PATCH 086/653] added another author tag --- storagemanager/PoolManager.h | 1 + 1 file changed, 1 insertion(+) diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index 6e353de2..c74e95c0 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -10,6 +10,7 @@ * a fixed pool size policy for inter-process communication. * @details Uses local pool calls but is thread safe by protecting the call * with a lock. + * @author Bastian Baetz */ template class PoolManager : public LocalPool { From a3f379e149dd32e4ac90e1fd58038138d8a65701 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 16:50:37 +0200 Subject: [PATCH 087/653] and another little include guard fix --- storagemanager/LocalPool.tpp | 2 +- storagemanager/PoolManager.tpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/storagemanager/LocalPool.tpp b/storagemanager/LocalPool.tpp index b7fa0da9..764bd7be 100644 --- a/storagemanager/LocalPool.tpp +++ b/storagemanager/LocalPool.tpp @@ -2,7 +2,7 @@ #define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ #ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ -#error Include LocalPool.h instead of LocalPool.tpp! +#error Include LocalPool.h before LocalPool.tpp! #endif template diff --git a/storagemanager/PoolManager.tpp b/storagemanager/PoolManager.tpp index 97603246..29b2b82a 100644 --- a/storagemanager/PoolManager.tpp +++ b/storagemanager/PoolManager.tpp @@ -2,7 +2,7 @@ #define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ #ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_ -#error Include LocalPool.h instead of LocalPool.tpp! +#error Include PoolManager.h before PoolManager.tpp! #endif template From f871f75e1c8fd5f625e4a2067492eb92f3b82289 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 17:10:57 +0200 Subject: [PATCH 088/653] added back default value for pool manager.h --- storagemanager/PoolManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index c74e95c0..144d073d 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -12,7 +12,7 @@ * with a lock. * @author Bastian Baetz */ -template +template class PoolManager : public LocalPool { public: PoolManager(object_id_t setObjectId, From 1cf5991101f9dc0e677911e1d7cfeffaa250285b Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 17:43:06 +0200 Subject: [PATCH 089/653] getClock_timval used now --- timemanager/Stopwatch.cpp | 12 +++++++----- timemanager/Stopwatch.h | 17 ++++++++++++----- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/timemanager/Stopwatch.cpp b/timemanager/Stopwatch.cpp index 2c85376d..bc8b4149 100644 --- a/timemanager/Stopwatch.cpp +++ b/timemanager/Stopwatch.cpp @@ -3,14 +3,14 @@ #include Stopwatch::Stopwatch(bool displayOnDestruction, - StopwatchDisplayMode displayMode): displayMode(displayMode), - displayOnDestruction(displayOnDestruction) { + StopwatchDisplayMode displayMode): displayOnDestruction( + displayOnDestruction), displayMode(displayMode) { // Measures start time on initialization. - startTime = Clock::getUptime(); + Clock::getClock_timeval(&startTime); } void Stopwatch::start() { - startTime = Clock::getUptime(); + Clock::getClock_timeval(&startTime); } millis_t Stopwatch::stop() { @@ -51,5 +51,7 @@ StopwatchDisplayMode Stopwatch::getDisplayMode() const { } void Stopwatch::stopInternal() { - elapsedTime = Clock::getUptime() - startTime; + timeval endTime; + Clock::getClock_timeval(&endTime); + elapsedTime = endTime - startTime; } diff --git a/timemanager/Stopwatch.h b/timemanager/Stopwatch.h index 19e1f92b..71580778 100644 --- a/timemanager/Stopwatch.h +++ b/timemanager/Stopwatch.h @@ -8,11 +8,13 @@ enum class StopwatchDisplayMode { }; /** - * @brief Simple Stopwatch implementation to measure elapsed time + * @brief Simple Stopwatch implementation to measure elapsed time * @details * This class can be used to measure elapsed times. It also displays elapsed * times automatically on destruction if not explicitely deactivated in the - * constructor. The default time format is the elapsed time in miliseconds. + * constructor. The default time format is the elapsed time in miliseconds + * in seconds as a double. + * @author R. Mueller */ class Stopwatch { public: @@ -21,8 +23,8 @@ public: * no parameters are required! * @param displayOnDestruction If set to true, displays measured time on * object destruction - * @param displayMode Display format is either MS rounded or seconds as - * double format + * @param displayMode Display format is either MS rounded or MS as double + * format * @param outputPrecision If using double format, specify precision here. */ Stopwatch(bool displayOnDestruction = true, StopwatchDisplayMode displayMode @@ -39,6 +41,10 @@ public: * @return elapsed time in milliseconds (rounded) */ millis_t stop(); + /** + * Calculates the elapsed time since start and returns it + * @return elapsed time in seconds (double precision) + */ seconds_t stopSeconds(); /** @@ -49,12 +55,13 @@ public: StopwatchDisplayMode getDisplayMode() const; void setDisplayMode(StopwatchDisplayMode displayMode); + bool displayOnDestruction = true; private: timeval startTime {0, 0}; timeval elapsedTime {0, 0}; StopwatchDisplayMode displayMode = StopwatchDisplayMode::MILLIS; - bool displayOnDestruction = true; + void stopInternal(); }; From 0be418a553a95971a56fc61a0f9e57276a345165 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 17:45:08 +0200 Subject: [PATCH 090/653] clock.h form improvements --- timemanager/Clock.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/timemanager/Clock.h b/timemanager/Clock.h index 2883878f..19991b81 100644 --- a/timemanager/Clock.h +++ b/timemanager/Clock.h @@ -2,11 +2,12 @@ #define FRAMEWORK_TIMEMANAGER_CLOCK_H_ #include -#include -#include #include #include +#include +#include + typedef uint32_t millis_t; typedef double seconds_t; @@ -22,7 +23,7 @@ public: uint32_t usecond; //!< Microseconds, 0 .. 999999 } TimeOfDay_t; - /**static Clock* TimeOfDay_t(); + /** * This method returns the number of clock ticks per second. * In RTEMS, this is typically 1000. * @return The number of ticks. @@ -34,22 +35,23 @@ public: * This system call sets the system time. * To set the time, it uses a TimeOfDay_t struct. * @param time The struct with the time settings to set. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. + * @return -@c RETURN_OK on success. Otherwise, the OS failure code + * is returned. */ static ReturnValue_t setClock(const TimeOfDay_t* time); /** * This system call sets the system time. * To set the time, it uses a timeval struct. * @param time The struct with the time settings to set. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. + * @return -@c RETURN_OK on success. Otherwise, the OS failure code is returned. */ static ReturnValue_t setClock(const timeval* time); /** * This system call returns the current system clock in timeval format. - * The timval format has the fields \c tv_sec with seconds and \c tv_usec with + * The timval format has the fields @c tv_sec with seconds and @c tv_usec with * microseconds since an OS-defined epoch. * @param time A pointer to a timeval struct where the current time is stored. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. + * @return @c RETURN_OK on success. Otherwise, the OS failure code is returned. */ static ReturnValue_t getClock_timeval(timeval* time); @@ -57,7 +59,7 @@ public: * Get the time since boot in a timeval struct * * @param[out] time A pointer to a timeval struct where the uptime is stored. - * @return\c RETURN_OK on success. Otherwise, the OS failure code is returned. + * @return @c RETURN_OK on success. Otherwise, the OS failure code is returned. * * @deprecated, I do not think this should be able to fail, use timeval getUptime() */ From f15424be4fef0a280385fc4d3a5eae85beba9ec5 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 17:47:55 +0200 Subject: [PATCH 091/653] implemented missing static function --- osal/linux/Clock.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/osal/linux/Clock.cpp b/osal/linux/Clock.cpp index e24a4fe4..630b2cf4 100644 --- a/osal/linux/Clock.cpp +++ b/osal/linux/Clock.cpp @@ -1,10 +1,10 @@ -#include -#include +#include #include - +#include #include #include +#include #include //#include @@ -65,6 +65,15 @@ ReturnValue_t Clock::getClock_usecs(uint64_t* time) { return HasReturnvaluesIF::RETURN_OK; } +timeval Clock::getUptime() { + timeval uptime; + auto result = getUptime(&uptime); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "Clock::getUptime: Error getting uptime" << std::endl; + } + return uptime; +} + ReturnValue_t Clock::getUptime(timeval* uptime) { //TODO This is not posix compatible and delivers only seconds precision struct sysinfo sysInfo; From c5bb18a7884a1b1f383581a854772ca0771cf04b Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 17:49:39 +0200 Subject: [PATCH 092/653] include improvements, nullptr used --- osal/FreeRTOS/Clock.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/osal/FreeRTOS/Clock.cpp b/osal/FreeRTOS/Clock.cpp index 82c9e170..dce20265 100644 --- a/osal/FreeRTOS/Clock.cpp +++ b/osal/FreeRTOS/Clock.cpp @@ -1,19 +1,18 @@ #include #include -#include -#include "Timekeeper.h" +#include -extern "C" { #include #include -} +#include +#include //TODO sanitize input? //TODO much of this code can be reused for tick-only systems uint16_t Clock::leapSeconds = 0; -MutexIF* Clock::timeMutex = NULL; +MutexIF* Clock::timeMutex = nullptr; uint32_t Clock::getTicksPerSecond(void) { return 1000; @@ -130,7 +129,7 @@ ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) { ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) { //SHOULDDO: works not for dates in the past (might have less leap seconds) - if (timeMutex == NULL) { + if (timeMutex == nullptr) { return HasReturnvaluesIF::RETURN_FAILED; } From a9a23d76231564d2d5bc15836455686b618a546a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 17:51:15 +0200 Subject: [PATCH 093/653] include improvements --- osal/FreeRTOS/Timekeeper.cpp | 15 ++++----------- osal/FreeRTOS/Timekeeper.h | 6 +++--- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/osal/FreeRTOS/Timekeeper.cpp b/osal/FreeRTOS/Timekeeper.cpp index 949e1df3..643b2747 100644 --- a/osal/FreeRTOS/Timekeeper.cpp +++ b/osal/FreeRTOS/Timekeeper.cpp @@ -1,17 +1,12 @@ -/** - * @file Timekeeper.cpp - * @date - */ - #include -extern "C" { -#include -} +#include "FreeRTOSConfig.h" Timekeeper * Timekeeper::myinstance = nullptr; -Timekeeper::Timekeeper() : offset( { 0, 0 }) {} +Timekeeper::Timekeeper() : offset( { 0, 0 } ) {} + +Timekeeper::~Timekeeper() {} const timeval& Timekeeper::getOffset() const { return offset; @@ -28,8 +23,6 @@ void Timekeeper::setOffset(const timeval& offset) { this->offset = offset; } -Timekeeper::~Timekeeper() {} - timeval Timekeeper::ticksToTimeval(TickType_t ticks) { timeval uptime; uptime.tv_sec = ticks / configTICK_RATE_HZ; diff --git a/osal/FreeRTOS/Timekeeper.h b/osal/FreeRTOS/Timekeeper.h index 05f0f701..7d3ca22b 100644 --- a/osal/FreeRTOS/Timekeeper.h +++ b/osal/FreeRTOS/Timekeeper.h @@ -2,9 +2,9 @@ #define FRAMEWORK_OSAL_FREERTOS_TIMEKEEPER_H_ #include -extern "C" { -#include -} + +#include +#include /** From e5cea3ead078302df24d17ce43895ceae5c5046c Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 20:31:08 +0200 Subject: [PATCH 094/653] service interface stream enhancements --- serviceinterface/ServiceInterfaceBuffer.cpp | 28 +++++++++++++-------- serviceinterface/ServiceInterfaceBuffer.h | 28 ++++++++++++++++----- serviceinterface/ServiceInterfaceStream.cpp | 6 ++--- serviceinterface/ServiceInterfaceStream.h | 7 +++--- 4 files changed, 47 insertions(+), 22 deletions(-) diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 58065994..2a97ab90 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -23,14 +23,16 @@ 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); + std::string preamble; + if(addCrToPreamble) { + preamble += "\r"; + } + preamble += log_message + ": | " + zero_padded(loggerTime.hour, 2) + + ":" + zero_padded(loggerTime.minute, 2) + ":" + + zero_padded(loggerTime.second, 2) + "." + + zero_padded(loggerTime.usecond/1000, 3) + " | "; // Write log_message and time - this->putChars(preamble, preamble + sizeof(preamble)); + this->putChars(preamble.c_str(), preamble.c_str() + preamble.size()); // Handle output this->putChars(pbase(), pptr()); } @@ -39,9 +41,13 @@ int ServiceInterfaceBuffer::sync(void) { return 0; } + + #ifndef UT699 -ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) { +ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, + uint16_t port, bool addCrToPreamble) { + this->addCrToPreamble = addCrToPreamble; this->log_message = set_message; this->isActive = true; setp( buf, buf + BUF_SIZE ); @@ -55,17 +61,19 @@ void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { } memcpy(array, begin, length); - for( ; begin != end; begin++){ + for(; begin != end; begin++){ printChar(begin); } } #endif + #ifdef UT699 #include -ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) { +ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, + uint16_t port) { this->log_message = set_message; this->isActive = true; setp( buf, buf + BUF_SIZE ); diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index b42c8a19..a2bc4f4b 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -2,32 +2,36 @@ #define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ #include -#include #include #include +#include #ifndef UT699 -class ServiceInterfaceBuffer: public std::basic_streambuf > { +class ServiceInterfaceBuffer: + public std::basic_streambuf> { friend class ServiceInterfaceStream; public: - ServiceInterfaceBuffer(std::string set_message, uint16_t port); + ServiceInterfaceBuffer(std::string set_message, uint16_t port, + bool addCrToPreamble); protected: bool isActive; // This is called when buffer becomes full. If // buffer is not used, then this is called every // time when characters are put to stream. - virtual int overflow(int c = Traits::eof()); + int overflow(int c = Traits::eof()) override; // This function is called when stream is flushed, // for example when std::endl is put to stream. - virtual int sync(void); + int sync(void) override; private: // For additional message information std::string log_message; // For EOF detection typedef std::char_traits Traits; + // This is useful for some terminal programs which do not have + // implicit carriage return with newline characters. + bool addCrToPreamble; // Work in buffer mode. It is also possible to work without buffer. static size_t const BUF_SIZE = 128; @@ -35,6 +39,18 @@ private: // In this function, the characters are parsed. void putChars(char const* begin, char const* end); + + template + std::string zero_padded(const T& num, uint8_t width) { + std::ostringstream string_to_pad; + string_to_pad << std::setw(width) << std::setfill('0') << num; + std::string result = string_to_pad.str(); + if (result.length() > width) + { + result.erase(0, result.length() - width); + } + return result; + } }; #endif diff --git a/serviceinterface/ServiceInterfaceStream.cpp b/serviceinterface/ServiceInterfaceStream.cpp index c2979f36..40f52f1f 100644 --- a/serviceinterface/ServiceInterfaceStream.cpp +++ b/serviceinterface/ServiceInterfaceStream.cpp @@ -5,7 +5,7 @@ void ServiceInterfaceStream::setActive( bool myActive) { } ServiceInterfaceStream::ServiceInterfaceStream(std::string set_message, - uint16_t port) : - std::basic_ostream >(&buf), buf( - set_message, port) { + bool addCrToPreamble, uint16_t port) : + std::basic_ostream>(&buf), + buf(set_message, port, addCrToPreamble) { } diff --git a/serviceinterface/ServiceInterfaceStream.h b/serviceinterface/ServiceInterfaceStream.h index df736a1b..a445dced 100644 --- a/serviceinterface/ServiceInterfaceStream.h +++ b/serviceinterface/ServiceInterfaceStream.h @@ -17,14 +17,15 @@ extern std::ostream error; } -class ServiceInterfaceStream : public std::basic_ostream< char, std::char_traits< char > > { +class ServiceInterfaceStream : + public std::basic_ostream> { protected: ServiceInterfaceBuffer buf; public: - ServiceInterfaceStream( std::string set_message, uint16_t port = 1234 ); + ServiceInterfaceStream( std::string set_message, + bool addCrToPreamble = false, uint16_t port = 1234); void setActive( bool ); }; - #endif /* FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ */ From d4f69633f0e45c7c379d7cc9738af2859d6a8ad3 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 2 Jun 2020 22:36:42 +0200 Subject: [PATCH 095/653] renamed timeout values --- osal/FreeRTOS/BinSemaphUsingTask.cpp | 8 ++++---- osal/FreeRTOS/BinSemaphUsingTask.h | 4 ++-- osal/FreeRTOS/BinarySemaphore.cpp | 8 ++++---- osal/FreeRTOS/BinarySemaphore.h | 4 ++-- osal/FreeRTOS/CountingSemaphUsingTask.cpp | 8 ++++---- osal/FreeRTOS/CountingSemaphUsingTask.h | 4 ++-- osal/FreeRTOS/SemaphoreFactory.cpp | 4 ++-- osal/linux/BinarySemaphore.cpp | 6 +++--- osal/linux/BinarySemaphore.h | 2 +- osal/linux/SemaphoreFactory.cpp | 4 ++-- tasks/SemaphoreIF.h | 19 +++++++++++++++---- 11 files changed, 41 insertions(+), 30 deletions(-) diff --git a/osal/FreeRTOS/BinSemaphUsingTask.cpp b/osal/FreeRTOS/BinSemaphUsingTask.cpp index 8f5fd4d8..d3351888 100644 --- a/osal/FreeRTOS/BinSemaphUsingTask.cpp +++ b/osal/FreeRTOS/BinSemaphUsingTask.cpp @@ -17,11 +17,11 @@ BinarySemaphoreUsingTask::~BinarySemaphoreUsingTask() { } ReturnValue_t BinarySemaphoreUsingTask::acquire(uint32_t timeoutMs) { - TickType_t timeout = SemaphoreIF::NO_TIMEOUT; - if(timeoutMs == SemaphoreIF::MAX_TIMEOUT) { - timeout = SemaphoreIF::MAX_TIMEOUT; + TickType_t timeout = SemaphoreIF::POLLING; + if(timeoutMs == SemaphoreIF::BLOCKING) { + timeout = SemaphoreIF::BLOCKING; } - else if(timeoutMs > SemaphoreIF::NO_TIMEOUT){ + else if(timeoutMs > SemaphoreIF::POLLING){ timeout = pdMS_TO_TICKS(timeoutMs); } return acquireWithTickTimeout(timeout); diff --git a/osal/FreeRTOS/BinSemaphUsingTask.h b/osal/FreeRTOS/BinSemaphUsingTask.h index 48c1cd12..43772e5a 100644 --- a/osal/FreeRTOS/BinSemaphUsingTask.h +++ b/osal/FreeRTOS/BinSemaphUsingTask.h @@ -26,7 +26,7 @@ public: virtual~ BinarySemaphoreUsingTask(); ReturnValue_t acquire(uint32_t timeoutMs = - SemaphoreIF::NO_TIMEOUT) override; + SemaphoreIF::BLOCKING) override; ReturnValue_t release() override; uint8_t getSemaphoreCounter() const override; static uint8_t getSemaphoreCounter(TaskHandle_t taskHandle); @@ -40,7 +40,7 @@ public: * - @c RETURN_FAILED on failure */ ReturnValue_t acquireWithTickTimeout(TickType_t timeoutTicks = - SemaphoreIF::NO_TIMEOUT); + SemaphoreIF::BLOCKING); /** * Get handle to the task related to the semaphore. diff --git a/osal/FreeRTOS/BinarySemaphore.cpp b/osal/FreeRTOS/BinarySemaphore.cpp index b6687bb7..e6d2f92f 100644 --- a/osal/FreeRTOS/BinarySemaphore.cpp +++ b/osal/FreeRTOS/BinarySemaphore.cpp @@ -36,11 +36,11 @@ BinarySemaphore& BinarySemaphore::operator =( } ReturnValue_t BinarySemaphore::acquire(uint32_t timeoutMs) { - TickType_t timeout = SemaphoreIF::NO_TIMEOUT; - if(timeoutMs == SemaphoreIF::MAX_TIMEOUT) { - timeout = SemaphoreIF::MAX_TIMEOUT; + TickType_t timeout = SemaphoreIF::POLLING; + if(timeoutMs == SemaphoreIF::BLOCKING) { + timeout = SemaphoreIF::BLOCKING; } - else if(timeoutMs > SemaphoreIF::NO_TIMEOUT){ + else if(timeoutMs > SemaphoreIF::POLLING){ timeout = pdMS_TO_TICKS(timeoutMs); } return acquireWithTickTimeout(timeout); diff --git a/osal/FreeRTOS/BinarySemaphore.h b/osal/FreeRTOS/BinarySemaphore.h index 0938dee6..2a372cd2 100644 --- a/osal/FreeRTOS/BinarySemaphore.h +++ b/osal/FreeRTOS/BinarySemaphore.h @@ -53,7 +53,7 @@ public: * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout */ ReturnValue_t acquire(uint32_t timeoutMs = - SemaphoreIF::NO_TIMEOUT) override; + SemaphoreIF::BLOCKING) override; /** * Same as lockBinarySemaphore() with timeout in FreeRTOS ticks. @@ -62,7 +62,7 @@ public: * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout */ ReturnValue_t acquireWithTickTimeout(TickType_t timeoutTicks = - BinarySemaphore::NO_TIMEOUT); + SemaphoreIF::BLOCKING); /** * Release the binary semaphore. diff --git a/osal/FreeRTOS/CountingSemaphUsingTask.cpp b/osal/FreeRTOS/CountingSemaphUsingTask.cpp index d0f63f3f..f33c7a0d 100644 --- a/osal/FreeRTOS/CountingSemaphUsingTask.cpp +++ b/osal/FreeRTOS/CountingSemaphUsingTask.cpp @@ -38,11 +38,11 @@ CountingSemaphoreUsingTask::~CountingSemaphoreUsingTask() { } ReturnValue_t CountingSemaphoreUsingTask::acquire(uint32_t timeoutMs) { - TickType_t timeout = SemaphoreIF::NO_TIMEOUT; - if(timeoutMs == SemaphoreIF::MAX_TIMEOUT) { - timeout = SemaphoreIF::MAX_TIMEOUT; + TickType_t timeout = SemaphoreIF::POLLING; + if(timeoutMs == SemaphoreIF::BLOCKING) { + timeout = SemaphoreIF::BLOCKING; } - else if(timeoutMs > SemaphoreIF::NO_TIMEOUT){ + else if(timeoutMs > SemaphoreIF::POLLING){ timeout = pdMS_TO_TICKS(timeoutMs); } return acquireWithTickTimeout(timeout); diff --git a/osal/FreeRTOS/CountingSemaphUsingTask.h b/osal/FreeRTOS/CountingSemaphUsingTask.h index 797e864b..f1d82c1d 100644 --- a/osal/FreeRTOS/CountingSemaphUsingTask.h +++ b/osal/FreeRTOS/CountingSemaphUsingTask.h @@ -31,7 +31,7 @@ public: * @return -@c RETURN_OK on success * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout */ - ReturnValue_t acquire(uint32_t timeoutMs = SemaphoreIF::NO_TIMEOUT) override; + ReturnValue_t acquire(uint32_t timeoutMs = SemaphoreIF::BLOCKING) override; /** * Release a semaphore, increasing the number of available counting @@ -61,7 +61,7 @@ public: * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout */ ReturnValue_t acquireWithTickTimeout( - TickType_t timeoutTicks = SemaphoreIF::NO_TIMEOUT); + TickType_t timeoutTicks = SemaphoreIF::BLOCKING); /** * Get handle to the task related to the semaphore. diff --git a/osal/FreeRTOS/SemaphoreFactory.cpp b/osal/FreeRTOS/SemaphoreFactory.cpp index 05a898cd..78427f6c 100644 --- a/osal/FreeRTOS/SemaphoreFactory.cpp +++ b/osal/FreeRTOS/SemaphoreFactory.cpp @@ -6,8 +6,8 @@ #include SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; -const uint32_t SemaphoreIF::NO_TIMEOUT = 0; -const uint32_t SemaphoreIF::MAX_TIMEOUT = portMAX_DELAY; +const uint32_t SemaphoreIF::POLLING = 0; +const uint32_t SemaphoreIF::BLOCKING = portMAX_DELAY; static const uint32_t USE_REGULAR_SEMAPHORES = 0; static const uint32_t USE_TASK_NOTIFICATIONS = 1; diff --git a/osal/linux/BinarySemaphore.cpp b/osal/linux/BinarySemaphore.cpp index 7c76a5c4..e2ad9b58 100644 --- a/osal/linux/BinarySemaphore.cpp +++ b/osal/linux/BinarySemaphore.cpp @@ -27,13 +27,13 @@ BinarySemaphore& BinarySemaphore::operator =( ReturnValue_t BinarySemaphore::acquire(uint32_t timeoutMs) { int result = 0; - if(timeoutMs == SemaphoreIF::NO_TIMEOUT) { + if(timeoutMs == SemaphoreIF::POLLING) { result = sem_trywait(&handle); } - else if(timeoutMs == SemaphoreIF::MAX_TIMEOUT) { + else if(timeoutMs == SemaphoreIF::BLOCKING) { result = sem_wait(&handle); } - else if(timeoutMs > SemaphoreIF::NO_TIMEOUT){ + else if(timeoutMs > SemaphoreIF::POLLING){ timespec timeOut; clock_gettime(CLOCK_REALTIME, &timeOut); uint64_t nseconds = timeOut.tv_sec * 1000000000 + timeOut.tv_nsec; diff --git a/osal/linux/BinarySemaphore.h b/osal/linux/BinarySemaphore.h index 7836cd41..9d4ed1cd 100644 --- a/osal/linux/BinarySemaphore.h +++ b/osal/linux/BinarySemaphore.h @@ -50,7 +50,7 @@ public: * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout */ ReturnValue_t acquire(uint32_t timeoutMs = - SemaphoreIF::NO_TIMEOUT) override; + SemaphoreIF::BLOCKING) override; /** * Release the binary semaphore. diff --git a/osal/linux/SemaphoreFactory.cpp b/osal/linux/SemaphoreFactory.cpp index 5aec84ea..4fbd60d9 100644 --- a/osal/linux/SemaphoreFactory.cpp +++ b/osal/linux/SemaphoreFactory.cpp @@ -3,8 +3,8 @@ #include #include -const uint32_t SemaphoreIF::NO_TIMEOUT = 0; -const uint32_t SemaphoreIF::MAX_TIMEOUT = 0xFFFFFFFF; +const uint32_t SemaphoreIF::POLLING = 0; +const uint32_t SemaphoreIF::BLOCKING = 0xffffffff; SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; diff --git a/tasks/SemaphoreIF.h b/tasks/SemaphoreIF.h index a7c5a97b..4fc92ebd 100644 --- a/tasks/SemaphoreIF.h +++ b/tasks/SemaphoreIF.h @@ -21,10 +21,21 @@ class SemaphoreIF { public: virtual~ SemaphoreIF() {}; - //! Needs to be defined in implementation. No blocking time - static const uint32_t NO_TIMEOUT; - //! Needs to be defined in implementation. Blocks indefinitely. - static const uint32_t MAX_TIMEOUT; + /** + * @brief Timeout value used for polling lock attempt. + * @details + * If the lock is not successfull, MUTEX_TIMEOUT will be returned + * immediately. Value needs to be defined in implementation. + */ + static const uint32_t POLLING; + /** + * @brief Timeout value used for permanent blocking lock attempt. + * @details + * The task will be blocked (indefinitely) until the mutex is unlocked. + * Value needs to be defined in implementation. + */ + static const uint32_t BLOCKING; + static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; //! Semaphore timeout static constexpr ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(1); From 7259a1356959ab9fb18472bfdeb45a2c88f864dd Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 3 Jun 2020 23:14:17 +0200 Subject: [PATCH 096/653] more improvements: 1. New optional flag to redirect print to stderr. THis can be useful on host environemtns (e.g linux) 2. non-buffered mode if this flag is true: the preamble msut be printed manually 2. Getter function for preamble for that case. 3. printChar function: specify whether to print to stderr or stdout --- serviceinterface/ServiceInterfaceBuffer.cpp | 94 ++++++++++++--------- serviceinterface/ServiceInterfaceBuffer.h | 50 ++++++++--- serviceinterface/ServiceInterfaceStream.cpp | 12 ++- serviceinterface/ServiceInterfaceStream.h | 37 ++++++-- 4 files changed, 131 insertions(+), 62 deletions(-) diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 2a97ab90..93de88b3 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -3,9 +3,42 @@ #include // to be implemented by bsp -extern "C" void printChar(const char*); +extern "C" void printChar(const char*, bool errStream); + +#ifndef UT699 + +ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, + bool errStream, bool addCrToPreamble, uint16_t port): + isActive(true), logMessage(setMessage), + addCrToPreamble(addCrToPreamble), errStream(errStream) { + if(not errStream) { + // Set pointers if the stream is buffered. + setp( buf, buf + BUF_SIZE ); + } +} + +void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { + char array[BUF_SIZE]; + uint32_t length = end - begin; + if (length > sizeof(array)) { + length = sizeof(array); + } + memcpy(array, begin, length); + + for(; begin != end; begin++){ + printChar(begin, false); + } +} + +#endif int ServiceInterfaceBuffer::overflow(int c) { + if(errStream and this->isActive) { + if (c != Traits::eof()) { + printChar(reinterpret_cast(&c), true); + } + return 0; + } // Handle output putChars(pbase(), pptr()); if (c != Traits::eof()) { @@ -20,53 +53,38 @@ int ServiceInterfaceBuffer::overflow(int c) { } int ServiceInterfaceBuffer::sync(void) { - if (this->isActive) { - Clock::TimeOfDay_t loggerTime; - Clock::getDateAndTime(&loggerTime); - std::string preamble; - if(addCrToPreamble) { - preamble += "\r"; + if(not this->isActive or errStream) { + if(not errStream) { + setp(buf, buf + BUF_SIZE - 1); } - preamble += log_message + ": | " + zero_padded(loggerTime.hour, 2) - + ":" + zero_padded(loggerTime.minute, 2) + ":" - + zero_padded(loggerTime.second, 2) + "." - + zero_padded(loggerTime.usecond/1000, 3) + " | "; - // Write log_message and time - this->putChars(preamble.c_str(), preamble.c_str() + preamble.size()); - // Handle output - this->putChars(pbase(), pptr()); + return 0; } + + auto preamble = getPreamble(); + // Write logMessage and time + this->putChars(preamble.c_str(), preamble.c_str() + preamble.size()); + // Handle output + this->putChars(pbase(), pptr()); // This tells that buffer is empty again setp(buf, buf + BUF_SIZE - 1); return 0; } - -#ifndef UT699 - -ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, - uint16_t port, bool addCrToPreamble) { - this->addCrToPreamble = addCrToPreamble; - this->log_message = set_message; - this->isActive = true; - setp( buf, buf + BUF_SIZE ); +std::string ServiceInterfaceBuffer::getPreamble() { + Clock::TimeOfDay_t loggerTime; + Clock::getDateAndTime(&loggerTime); + std::string preamble; + if(addCrToPreamble) { + preamble += "\r"; + } + preamble += logMessage + ": | " + zero_padded(loggerTime.hour, 2) + + ":" + zero_padded(loggerTime.minute, 2) + ":" + + zero_padded(loggerTime.second, 2) + "." + + zero_padded(loggerTime.usecond/1000, 3) + " | "; + return preamble; } -void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { - char array[BUF_SIZE]; - uint32_t length = end - begin; - if (length > sizeof(array)) { - length = sizeof(array); - } - memcpy(array, begin, length); - - for(; begin != end; begin++){ - printChar(begin); - } - -} -#endif #ifdef UT699 diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index a2bc4f4b..74facafe 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -3,43 +3,64 @@ #include #include -#include #include #ifndef UT699 + +/** + * @brief This is the underlying stream buffer which implements the + * streambuf class and overloads the overflow() and sync() methods + * @details + * This class is used to modify the output of the stream, for example by adding. + * It also calls the char printing function which is implemented in the + * board supply package (BSP). + */ class ServiceInterfaceBuffer: - public std::basic_streambuf> { + public std::streambuf { friend class ServiceInterfaceStream; public: - ServiceInterfaceBuffer(std::string set_message, uint16_t port, - bool addCrToPreamble); + ServiceInterfaceBuffer(std::string setMessage, bool errStream, + bool addCrToPreamble, uint16_t port); + protected: bool isActive; - // This is called when buffer becomes full. If - // buffer is not used, then this is called every - // time when characters are put to stream. + //! This is called when buffer becomes full. If + //! buffer is not used, then this is called every + //! time when characters are put to stream. int overflow(int c = Traits::eof()) override; - // This function is called when stream is flushed, - // for example when std::endl is put to stream. + //! This function is called when stream is flushed, + //! for example when std::endl is put to stream. int sync(void) override; private: - // For additional message information - std::string log_message; + //! For additional message information + std::string logMessage; // For EOF detection typedef std::char_traits Traits; - // This is useful for some terminal programs which do not have - // implicit carriage return with newline characters. + //! This is useful for some terminal programs which do not have + //! implicit carriage return with newline characters. bool addCrToPreamble; + //! This specifies to print to stderr and work in unbuffered mode. + bool errStream; // Work in buffer mode. It is also possible to work without buffer. static size_t const BUF_SIZE = 128; char buf[BUF_SIZE]; - // In this function, the characters are parsed. + //! In this function, the characters are parsed. void putChars(char const* begin, char const* end); + std::string getPreamble(); + + /** + * This helper function returns the zero padded string version of a number. + * The type is deduced automatically. + * @tparam T + * @param num + * @param width + * @return + */ template std::string zero_padded(const T& num, uint8_t width) { std::ostringstream string_to_pad; @@ -52,6 +73,7 @@ private: return result; } }; + #endif diff --git a/serviceinterface/ServiceInterfaceStream.cpp b/serviceinterface/ServiceInterfaceStream.cpp index 40f52f1f..78371548 100644 --- a/serviceinterface/ServiceInterfaceStream.cpp +++ b/serviceinterface/ServiceInterfaceStream.cpp @@ -1,11 +1,15 @@ #include +ServiceInterfaceStream::ServiceInterfaceStream(std::string setMessage, + bool errStream, bool addCrToPreamble, uint16_t port) : + std::ostream(&buf), + buf(setMessage, errStream, addCrToPreamble, port) { +} + void ServiceInterfaceStream::setActive( bool myActive) { this->buf.isActive = myActive; } -ServiceInterfaceStream::ServiceInterfaceStream(std::string set_message, - bool addCrToPreamble, uint16_t port) : - std::basic_ostream>(&buf), - buf(set_message, port, addCrToPreamble) { +std::string ServiceInterfaceStream::getPreamble() { + return buf.getPreamble(); } diff --git a/serviceinterface/ServiceInterfaceStream.h b/serviceinterface/ServiceInterfaceStream.h index a445dced..aecd45c3 100644 --- a/serviceinterface/ServiceInterfaceStream.h +++ b/serviceinterface/ServiceInterfaceStream.h @@ -3,11 +3,9 @@ #include #include -#include -#include #include -// Unfortunately, there must be a forward declaration of log_fe +// Unfortunately, there must be a forward declaration of the log front end // (MUST be defined in main), to let the system know where to write to. namespace sif { extern std::ostream debug; @@ -18,14 +16,41 @@ extern std::ostream error; class ServiceInterfaceStream : - public std::basic_ostream> { + public std::ostream { protected: ServiceInterfaceBuffer buf; public: - ServiceInterfaceStream( std::string set_message, - bool addCrToPreamble = false, uint16_t port = 1234); + /** + * This constructor is used by specifying the preamble message. + * Optionally, the output can be directed to stderr and a CR character + * can be prepended to the preamble. + * @param set_message + * @param errStream + * @param addCrToPreamble + * @param port + */ + ServiceInterfaceStream(std::string setMessage, + bool errStream = false, bool addCrToPreamble = false, + uint16_t port = 1234); + + //! An inactive stream will not print anything. void setActive( bool ); + + /** + * This can be used to retrieve the preamble in case it should be printed in + * the unbuffered mode. + * @return Preamle consisting of log message and timestamp. + */ + std::string getPreamble(); }; +// Forward declaration of interface streams. These are needed so the public +// functions can be used by including this header +namespace sif { +extern ServiceInterfaceStream debugStream; +extern ServiceInterfaceStream infoStream; +extern ServiceInterfaceStream warningStream; +extern ServiceInterfaceStream errorStream; +} #endif /* FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ */ From 9361568b4513645fb42a571659e8e060b3d374c7 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 3 Jun 2020 23:28:31 +0200 Subject: [PATCH 097/653] clarifying commnet --- serviceinterface/ServiceInterfaceStream.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/serviceinterface/ServiceInterfaceStream.h b/serviceinterface/ServiceInterfaceStream.h index aecd45c3..375a1875 100644 --- a/serviceinterface/ServiceInterfaceStream.h +++ b/serviceinterface/ServiceInterfaceStream.h @@ -5,8 +5,11 @@ #include #include -// Unfortunately, there must be a forward declaration of the log front end -// (MUST be defined in main), to let the system know where to write to. +/* Unfortunately, there must be a forward declaration of the log front end + * (MUST be defined in main), to let the system know where to write to. + * The ServiceInterfaceStream instances, which are declared below and + * can instantaited somewhere else can be passed to these front ends by passing + * their underlying buffers with .rdbuf() */ namespace sif { extern std::ostream debug; extern std::ostream info; From ef1324940579d307b8ba62c1270c7db3fbaa9472 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 13:01:59 +0200 Subject: [PATCH 098/653] typedef renamed --- timemanager/Clock.h | 5 +++-- timemanager/Stopwatch.cpp | 4 ++-- timemanager/Stopwatch.h | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/timemanager/Clock.h b/timemanager/Clock.h index 19991b81..121c63df 100644 --- a/timemanager/Clock.h +++ b/timemanager/Clock.h @@ -8,8 +8,9 @@ #include #include -typedef uint32_t millis_t; -typedef double seconds_t; +//! Don't use these for time points, type is not large enough for UNIX epoch. +typedef uint32_t dur_millis_t; +typedef double dur_seconds_t; class Clock { public: diff --git a/timemanager/Stopwatch.cpp b/timemanager/Stopwatch.cpp index bc8b4149..52118d58 100644 --- a/timemanager/Stopwatch.cpp +++ b/timemanager/Stopwatch.cpp @@ -13,12 +13,12 @@ void Stopwatch::start() { Clock::getClock_timeval(&startTime); } -millis_t Stopwatch::stop() { +dur_millis_t Stopwatch::stop() { stopInternal(); return elapsedTime.tv_sec * 1000 + elapsedTime.tv_usec / 1000; } -seconds_t Stopwatch::stopSeconds() { +dur_seconds_t Stopwatch::stopSeconds() { stopInternal(); return timevalOperations::toDouble(elapsedTime); } diff --git a/timemanager/Stopwatch.h b/timemanager/Stopwatch.h index 71580778..630202cc 100644 --- a/timemanager/Stopwatch.h +++ b/timemanager/Stopwatch.h @@ -40,12 +40,12 @@ public: * Calculates the elapsed time since start and returns it * @return elapsed time in milliseconds (rounded) */ - millis_t stop(); + dur_millis_t stop(); /** * Calculates the elapsed time since start and returns it * @return elapsed time in seconds (double precision) */ - seconds_t stopSeconds(); + dur_seconds_t stopSeconds(); /** * Displays the elapsed times on the osstream, depending on internal display From 764608005b0934c02faedf9913ae7b3153e11ba3 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 13:26:35 +0200 Subject: [PATCH 099/653] buf renamed to streambuf --- osal/FreeRTOS/MessageQueue.cpp | 3 ++- serviceinterface/ServiceInterfaceStream.cpp | 8 ++++---- serviceinterface/ServiceInterfaceStream.h | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/osal/FreeRTOS/MessageQueue.cpp b/osal/FreeRTOS/MessageQueue.cpp index e5da0442..18e7aa3d 100644 --- a/osal/FreeRTOS/MessageQueue.cpp +++ b/osal/FreeRTOS/MessageQueue.cpp @@ -97,7 +97,8 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, bool ignoreFault) { message->setSender(sentFrom); - BaseType_t result = xQueueSendToBack(reinterpret_cast(sendTo),reinterpret_cast(message->getBuffer()), 0); + BaseType_t result = xQueueSendToBack(reinterpret_cast(sendTo), + reinterpret_cast(message->getBuffer()), 0); if (result != pdPASS) { if (!ignoreFault) { InternalErrorReporterIF* internalErrorReporter = objectManager->get( diff --git a/serviceinterface/ServiceInterfaceStream.cpp b/serviceinterface/ServiceInterfaceStream.cpp index 78371548..d9bc980a 100644 --- a/serviceinterface/ServiceInterfaceStream.cpp +++ b/serviceinterface/ServiceInterfaceStream.cpp @@ -2,14 +2,14 @@ ServiceInterfaceStream::ServiceInterfaceStream(std::string setMessage, bool errStream, bool addCrToPreamble, uint16_t port) : - std::ostream(&buf), - buf(setMessage, errStream, addCrToPreamble, port) { + std::ostream(&streambuf), + streambuf(setMessage, errStream, addCrToPreamble, port) { } void ServiceInterfaceStream::setActive( bool myActive) { - this->buf.isActive = myActive; + this->streambuf.isActive = myActive; } std::string ServiceInterfaceStream::getPreamble() { - return buf.getPreamble(); + return streambuf.getPreamble(); } diff --git a/serviceinterface/ServiceInterfaceStream.h b/serviceinterface/ServiceInterfaceStream.h index 375a1875..c44fe03a 100644 --- a/serviceinterface/ServiceInterfaceStream.h +++ b/serviceinterface/ServiceInterfaceStream.h @@ -21,7 +21,7 @@ extern std::ostream error; class ServiceInterfaceStream : public std::ostream { protected: - ServiceInterfaceBuffer buf; + ServiceInterfaceBuffer streambuf; public: /** * This constructor is used by specifying the preamble message. From f8fb370ae7698c8b27c86428ab01129042cedfa3 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 14:08:26 +0200 Subject: [PATCH 100/653] preamble changes started --- osal/FreeRTOS/FixedTimeslotTask.cpp | 2 +- serviceinterface/ServiceInterfaceBuffer.cpp | 65 +++++++++++++++------ serviceinterface/ServiceInterfaceBuffer.h | 8 ++- serviceinterface/ServiceInterfaceStream.cpp | 28 +++++++-- serviceinterface/ServiceInterfaceStream.h | 53 ++++++++--------- 5 files changed, 104 insertions(+), 52 deletions(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index fb3c3b03..549ffbf1 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -68,7 +68,7 @@ ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, } sif::error << "Component " << std::hex << componentId << - " not found, not adding it to pst" << std::endl; + " not found, not adding it to pst\r" << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 93de88b3..321b1d3c 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -8,13 +8,15 @@ extern "C" void printChar(const char*, bool errStream); #ifndef UT699 ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, - bool errStream, bool addCrToPreamble, uint16_t port): + bool addCrToPreamble, bool buffered , bool errStream, uint16_t port): isActive(true), logMessage(setMessage), - addCrToPreamble(addCrToPreamble), errStream(errStream) { - if(not errStream) { + addCrToPreamble(addCrToPreamble), buffered(buffered), + errStream(errStream) { + if(buffered) { // Set pointers if the stream is buffered. setp( buf, buf + BUF_SIZE ); } + preamble.reserve(96); } void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { @@ -26,16 +28,27 @@ void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { memcpy(array, begin, length); for(; begin != end; begin++){ - printChar(begin, false); + if(errStream) { + printChar(begin, true); + } + else { + printChar(begin, false); + } + } } #endif int ServiceInterfaceBuffer::overflow(int c) { - if(errStream and this->isActive) { + if(not buffered and this->isActive) { if (c != Traits::eof()) { - printChar(reinterpret_cast(&c), true); + if(errStream) { + printChar(reinterpret_cast(&c), true); + } + else { + printChar(reinterpret_cast(&c), false); + } } return 0; } @@ -53,16 +66,17 @@ int ServiceInterfaceBuffer::overflow(int c) { } int ServiceInterfaceBuffer::sync(void) { - if(not this->isActive or errStream) { - if(not errStream) { + if(not this->isActive) { + if(not buffered) { setp(buf, buf + BUF_SIZE - 1); } return 0; } - auto preamble = getPreamble(); + size_t preambleSize = 0; + auto preamble = getPreamble(&preambleSize); // Write logMessage and time - this->putChars(preamble.c_str(), preamble.c_str() + preamble.size()); + this->putChars(preamble.c_str(), preamble.c_str() + preambleSize); // Handle output this->putChars(pbase(), pptr()); // This tells that buffer is empty again @@ -71,17 +85,34 @@ int ServiceInterfaceBuffer::sync(void) { } -std::string ServiceInterfaceBuffer::getPreamble() { +std::string ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { Clock::TimeOfDay_t loggerTime; Clock::getDateAndTime(&loggerTime); - std::string preamble; + //preamble.clear(); + //std::string preamble; + size_t currentSize = 0; if(addCrToPreamble) { - preamble += "\r"; + preamble[0] = '\r'; + currentSize += 1; } - preamble += logMessage + ": | " + zero_padded(loggerTime.hour, 2) - + ":" + zero_padded(loggerTime.minute, 2) + ":" - + zero_padded(loggerTime.second, 2) + "." - + zero_padded(loggerTime.usecond/1000, 3) + " | "; + logMessage.copy(preamble.data() + 1, logMessage.size()); + currentSize += logMessage.size(); + preamble[++currentSize] = ':'; + preamble[++currentSize] = ' '; + preamble[++currentSize] = '|'; + zero_padded(loggerTime.hour, 2).copy(preamble.data() + ) + //preamble.c_str() + 1 = logMessage; +// +// + ": | " + zero_padded(loggerTime.hour, 2) +// + ":" + zero_padded(loggerTime.minute, 2) + ":" +// + zero_padded(loggerTime.second, 2) + "." +// + zero_padded(loggerTime.usecond/1000, 3) + " | "; + currentSize += logMessage.size(); //+ 4 +2 +1 +2 +1 +2 +1 + 3 + 3; + preamble[currentSize] = '\0'; + printf("%s", preamble.c_str()); + uint8_t debugArray[96]; + memcpy(debugArray, preamble.data(), currentSize); + *preambleSize = currentSize; return preamble; } diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index 74facafe..ab5d8c90 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -19,8 +19,8 @@ class ServiceInterfaceBuffer: public std::streambuf { friend class ServiceInterfaceStream; public: - ServiceInterfaceBuffer(std::string setMessage, bool errStream, - bool addCrToPreamble, uint16_t port); + ServiceInterfaceBuffer(std::string setMessage, bool addCrToPreamble, + bool buffered, bool errStream, uint16_t port); protected: bool isActive; @@ -36,11 +36,13 @@ protected: private: //! For additional message information std::string logMessage; + std::string preamble; // For EOF detection typedef std::char_traits Traits; //! This is useful for some terminal programs which do not have //! implicit carriage return with newline characters. bool addCrToPreamble; + bool buffered; //! This specifies to print to stderr and work in unbuffered mode. bool errStream; @@ -51,7 +53,7 @@ private: //! In this function, the characters are parsed. void putChars(char const* begin, char const* end); - std::string getPreamble(); + std::string getPreamble(size_t * preambleSize = nullptr); /** * This helper function returns the zero padded string version of a number. diff --git a/serviceinterface/ServiceInterfaceStream.cpp b/serviceinterface/ServiceInterfaceStream.cpp index d9bc980a..bef8136e 100644 --- a/serviceinterface/ServiceInterfaceStream.cpp +++ b/serviceinterface/ServiceInterfaceStream.cpp @@ -1,15 +1,33 @@ #include ServiceInterfaceStream::ServiceInterfaceStream(std::string setMessage, - bool errStream, bool addCrToPreamble, uint16_t port) : - std::ostream(&streambuf), - streambuf(setMessage, errStream, addCrToPreamble, port) { + bool addCrToPreamble, bool buffered, bool errStream, uint16_t port) : + std::ostream(&buf), + buf(setMessage, addCrToPreamble, buffered, errStream, port) { } void ServiceInterfaceStream::setActive( bool myActive) { - this->streambuf.isActive = myActive; + this->buf.isActive = myActive; } std::string ServiceInterfaceStream::getPreamble() { - return streambuf.getPreamble(); + return buf.getPreamble(); +} + +void ServiceInterfaceStream::print(std::string error, + bool withPreamble, bool withNewline, bool flush) { + if(not buffered and withPreamble) { + *this << getPreamble() << error; + } + else { + *this << error; + } + + if(withNewline) { + *this << "\n"; + } + // if mode is non-buffered, no need to flush. + if(flush and buffered) { + this->flush(); + } } diff --git a/serviceinterface/ServiceInterfaceStream.h b/serviceinterface/ServiceInterfaceStream.h index c44fe03a..9b8b5b6e 100644 --- a/serviceinterface/ServiceInterfaceStream.h +++ b/serviceinterface/ServiceInterfaceStream.h @@ -5,36 +5,28 @@ #include #include -/* Unfortunately, there must be a forward declaration of the log front end - * (MUST be defined in main), to let the system know where to write to. - * The ServiceInterfaceStream instances, which are declared below and - * can instantaited somewhere else can be passed to these front ends by passing - * their underlying buffers with .rdbuf() */ -namespace sif { -extern std::ostream debug; -extern std::ostream info; -extern std::ostream warning; -extern std::ostream error; -} - - +/** + * Generic service interface stream which can be used like std::cout or + * std::cerr but has additional capability. Add preamble and timestamp + * to output. Can be run in buffered or unbuffered mode. + */ class ServiceInterfaceStream : public std::ostream { protected: - ServiceInterfaceBuffer streambuf; + ServiceInterfaceBuffer buf; public: /** * This constructor is used by specifying the preamble message. * Optionally, the output can be directed to stderr and a CR character * can be prepended to the preamble. - * @param set_message - * @param errStream - * @param addCrToPreamble - * @param port + * @param setMessage message of preamble. + * @param addCrToPreamble Useful for applications like Puttty. + * @param buffered specify whether to use buffered mode. + * @param errStream specify which output stream to use (stderr or stdout). */ ServiceInterfaceStream(std::string setMessage, - bool errStream = false, bool addCrToPreamble = false, - uint16_t port = 1234); + bool addCrToPreamble = false, bool buffered = true, + bool errStream = false, uint16_t port = 1234); //! An inactive stream will not print anything. void setActive( bool ); @@ -45,15 +37,24 @@ public: * @return Preamle consisting of log message and timestamp. */ std::string getPreamble(); + + /** + * This prints an error with a preamble. Useful if using the unbuffered + * mode. Flushes in default mode (prints immediately). + */ + void print(std::string error, bool withPreamble = true, + bool withNewline = true, bool flush = true); + + bool buffered = false; }; -// Forward declaration of interface streams. These are needed so the public -// functions can be used by including this header +// Forward declaration of interface streams. These should be instantiated in +// main. They can then be used like std::cout or std::cerr. namespace sif { -extern ServiceInterfaceStream debugStream; -extern ServiceInterfaceStream infoStream; -extern ServiceInterfaceStream warningStream; -extern ServiceInterfaceStream errorStream; +extern ServiceInterfaceStream debug; +extern ServiceInterfaceStream info; +extern ServiceInterfaceStream warning; +extern ServiceInterfaceStream error; } #endif /* FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ */ From 966c9c3993df460de712823a43c5fef04213dd53 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 14:22:04 +0200 Subject: [PATCH 101/653] buffer changes --- serviceinterface/ServiceInterfaceBuffer.cpp | 52 ++++++++++++++------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 321b1d3c..3c365f17 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -95,24 +95,40 @@ std::string ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { preamble[0] = '\r'; currentSize += 1; } - logMessage.copy(preamble.data() + 1, logMessage.size()); - currentSize += logMessage.size(); - preamble[++currentSize] = ':'; - preamble[++currentSize] = ' '; - preamble[++currentSize] = '|'; - zero_padded(loggerTime.hour, 2).copy(preamble.data() + ) - //preamble.c_str() + 1 = logMessage; -// -// + ": | " + zero_padded(loggerTime.hour, 2) -// + ":" + zero_padded(loggerTime.minute, 2) + ":" -// + zero_padded(loggerTime.second, 2) + "." -// + zero_padded(loggerTime.usecond/1000, 3) + " | "; - currentSize += logMessage.size(); //+ 4 +2 +1 +2 +1 +2 +1 + 3 + 3; - preamble[currentSize] = '\0'; - printf("%s", preamble.c_str()); - uint8_t debugArray[96]; - memcpy(debugArray, preamble.data(), currentSize); - *preambleSize = currentSize; + int32_t charCount = sprintf(preamble.data() + currentSize, + "%s: | %lu:%02lu:%02lu.%03lu | ", + this->logMessage.c_str(), (unsigned long) loggerTime.hour, + (unsigned long) loggerTime.minute, + (unsigned long) loggerTime.second, + (unsigned long) loggerTime.usecond /1000); + if(charCount < 0) { + printf("ServiceInterfaceBuffer: Failure parsing preamble"); + return ""; + } + currentSize += charCount; +// size_t currentSize = 0; +// if(addCrToPreamble) { +// preamble[0] = '\r'; +// currentSize += 1; +// } +// logMessage.copy(preamble.data() + 1, logMessage.size()); +// currentSize += logMessage.size(); +// preamble[++currentSize] = ':'; +// preamble[++currentSize] = ' '; +// preamble[++currentSize] = '|'; +// zero_padded(loggerTime.hour, 2).copy(preamble.data() + ) +// //preamble.c_str() + 1 = logMessage; +//// +//// + ": | " + zero_padded(loggerTime.hour, 2) +//// + ":" + zero_padded(loggerTime.minute, 2) + ":" +//// + zero_padded(loggerTime.second, 2) + "." +//// + zero_padded(loggerTime.usecond/1000, 3) + " | "; +// currentSize += logMessage.size(); //+ 4 +2 +1 +2 +1 +2 +1 + 3 + 3; +// preamble[currentSize] = '\0'; +// printf("%s", preamble.c_str()); +// uint8_t debugArray[96]; +// memcpy(debugArray, preamble.data(), currentSize); +// *preambleSize = currentSize; return preamble; } From 8e3f99a350be66308d9afabae8069426f67ce8e6 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 14:59:14 +0200 Subject: [PATCH 102/653] removed object manager changes for now --- objectmanager/ObjectManagerIF.h | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/objectmanager/ObjectManagerIF.h b/objectmanager/ObjectManagerIF.h index b5cab408..aca24a24 100644 --- a/objectmanager/ObjectManagerIF.h +++ b/objectmanager/ObjectManagerIF.h @@ -8,11 +8,10 @@ #ifndef OBJECTMANAGERIF_H_ #define OBJECTMANAGERIF_H_ -#include "systemObjectList.h" #include +#include #include #include -#include /** * @brief This class provides an interface to the global object manager. @@ -25,12 +24,9 @@ */ class ObjectManagerIF : public HasReturnvaluesIF { public: - static constexpr uint8_t INTERFACE_ID = CLASS_ID::OBJECT_MANAGER_IF; - static constexpr ReturnValue_t INSERTION_FAILED = MAKE_RETURN_CODE( 1 ); - static constexpr ReturnValue_t NOT_FOUND = MAKE_RETURN_CODE( 2 ); - static constexpr ReturnValue_t CHILD_INIT_FAILED = MAKE_RETURN_CODE( 3 ); - static constexpr ReturnValue_t INTERNAL_ERR_REPORTER_UNINIT = MAKE_RETURN_CODE( 4 ); - + static const uint8_t INTERFACE_ID = CLASS_ID::OBJECT_MANAGER_IF; + static const ReturnValue_t INSERTION_FAILED = MAKE_RETURN_CODE( 1 ); + static const ReturnValue_t NOT_FOUND = MAKE_RETURN_CODE( 2 ); protected: /** * @brief This method is used to hide the template-based get call from @@ -82,22 +78,15 @@ public: virtual void printList() = 0; }; +template +T* ObjectManagerIF::get( object_id_t id ) { + SystemObjectIF* temp = this->getSystemObject(id); + return dynamic_cast(temp); +} /** * @brief This is the forward declaration of the global objectManager instance. */ extern ObjectManagerIF *objectManager; -/*Documentation can be found in the class method declaration above.*/ -template -T* ObjectManagerIF::get( object_id_t id ) { - if(objectManager == nullptr) { - sif::error << "ObjectManagerIF: Global object manager has not " - "been initialized yet!" << std::endl; - std::exit(0); - } - SystemObjectIF* temp = this->getSystemObject(id); - return dynamic_cast(temp); -} - #endif /* OBJECTMANAGERIF_H_ */ From 1d99a99bbd79942b5f034705fd74f4e599b47444 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 15:00:05 +0200 Subject: [PATCH 103/653] I now remember why I included object manager IF changes --- objectmanager/ObjectManagerIF.h | 42 ++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/objectmanager/ObjectManagerIF.h b/objectmanager/ObjectManagerIF.h index aca24a24..0dfb7f30 100644 --- a/objectmanager/ObjectManagerIF.h +++ b/objectmanager/ObjectManagerIF.h @@ -1,17 +1,10 @@ -/** - * @file ObjectManagerIF.h - * @brief This file contains the implementation of the ObjectManagerIF interface - * @date 19.09.2012 - * @author Bastian Baetz - */ - -#ifndef OBJECTMANAGERIF_H_ -#define OBJECTMANAGERIF_H_ +#ifndef FRAMEWORK_OBJECTMANAGER_OBJECTMANAGERIF_H_ +#define FRAMEWORK_OBJECTMANAGER_OBJECTMANAGERIF_H_ #include -#include #include #include +#include /** * @brief This class provides an interface to the global object manager. @@ -20,13 +13,17 @@ * inserted, removed and retrieved from the list. On getting the * object, the call checks if the object implements the requested * interface. - * \ingroup system_objects + * @author Bastian Baetz + * @ingroup system_objects */ class ObjectManagerIF : public HasReturnvaluesIF { public: - static const uint8_t INTERFACE_ID = CLASS_ID::OBJECT_MANAGER_IF; - static const ReturnValue_t INSERTION_FAILED = MAKE_RETURN_CODE( 1 ); - static const ReturnValue_t NOT_FOUND = MAKE_RETURN_CODE( 2 ); + static constexpr uint8_t INTERFACE_ID = CLASS_ID::OBJECT_MANAGER_IF; + static constexpr ReturnValue_t INSERTION_FAILED = MAKE_RETURN_CODE( 1 ); + static constexpr ReturnValue_t NOT_FOUND = MAKE_RETURN_CODE( 2 ); + static constexpr ReturnValue_t CHILD_INIT_FAILED = MAKE_RETURN_CODE( 3 ); + static constexpr ReturnValue_t INTERNAL_ERR_REPORTER_UNINIT = MAKE_RETURN_CODE( 4 ); + protected: /** * @brief This method is used to hide the template-based get call from @@ -78,15 +75,22 @@ public: virtual void printList() = 0; }; -template -T* ObjectManagerIF::get( object_id_t id ) { - SystemObjectIF* temp = this->getSystemObject(id); - return dynamic_cast(temp); -} /** * @brief This is the forward declaration of the global objectManager instance. */ extern ObjectManagerIF *objectManager; +/*Documentation can be found in the class method declaration above.*/ +template +T* ObjectManagerIF::get( object_id_t id ) { + if(objectManager == nullptr) { + sif::error << "ObjectManagerIF: Global object manager has not " + "been initialized yet!" << std::endl; + std::exit(1); + } + SystemObjectIF* temp = this->getSystemObject(id); + return dynamic_cast(temp); +} + #endif /* OBJECTMANAGERIF_H_ */ From 3d175f603c0cfdb1a8b1c7185ab15ad248f164a6 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 15:02:14 +0200 Subject: [PATCH 104/653] removed conflict markers --- storagemanager/LocalPool.h | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/storagemanager/LocalPool.h b/storagemanager/LocalPool.h index d842294c..7e349dcd 100644 --- a/storagemanager/LocalPool.h +++ b/storagemanager/LocalPool.h @@ -1,12 +1,3 @@ -<<<<<<< HEAD -======= -/** - * @file LocalPool - * @date 02.02.2012 - * @author Bastian Baetz - * @brief This file contains the definition of the LocalPool class. - */ ->>>>>>> upstream/master #ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ #define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ @@ -44,7 +35,7 @@ public: /** * @brief This is the default constructor for a pool manager instance. * @details By passing two arrays of size NUMBER_OF_POOLS, the constructor - * allocates memory (with \c new) for store and size_list. These + * allocates memory (with @c new) for store and size_list. These * regions are all set to zero on start up. * @param setObjectId The object identifier to be set. This allows for * multiple instances of LocalPool in the system. @@ -96,7 +87,7 @@ public: ReturnValue_t initialize() override; protected: /** - * With this helper method, a free element of \c size is reserved. + * With this helper method, a free element of @c size is reserved. * @param size The minimum packet size that shall be reserved. * @param[out] address Storage ID of the reserved data. * @return - #RETURN_OK on success, @@ -109,7 +100,8 @@ protected: private: /** * Indicates that this element is free. - * This value limits the maximum size of a pool. Change to larger data type if increase is required. + * This value limits the maximum size of a pool. Change to larger data type + * if increase is required. */ static const uint32_t STORAGE_FREE = 0xFFFFFFFF; /** @@ -135,7 +127,9 @@ private: * is also dynamically allocated there. */ uint32_t* size_list[NUMBER_OF_POOLS]; - bool spillsToHigherPools; //!< A variable to determine whether higher n pools are used if the store is full. + //! A variable to determine whether higher n pools are used if + //! the store is full. + bool spillsToHigherPools; /** * @brief This method safely stores the given data in the given packet_id. * @details It also sets the size in size_list. The method does not perform From a6a31801960dca7a5949daece14c1843caaa9baf Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 15:03:29 +0200 Subject: [PATCH 105/653] removed conflict markers --- storagemanager/PoolManager.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index cbb5d54b..7c2e8a71 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -22,20 +22,12 @@ public: //! @brief In the PoolManager's destructor all allocated memory is freed. virtual ~PoolManager(); -<<<<<<< HEAD //! @brief LocalPool overrides for thread-safety. Decorator function which //! wraps LocalPool calls with a mutex protection. ReturnValue_t deleteData(store_address_t) override; ReturnValue_t deleteData(uint8_t* buffer, size_t size, store_address_t* storeId = nullptr) override; -======= - //! @brief LocalPool overrides for thread-safety. - ReturnValue_t deleteData(store_address_t) override; - ReturnValue_t deleteData(uint8_t* buffer, size_t size, - store_address_t* storeId = NULL) override; - ReturnValue_t modifyData(store_address_t packet_id, uint8_t** packet_ptr, - size_t* size) override; ->>>>>>> upstream/master + protected: ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault) override; From 1cb241ca0cb3ab729b4bf67167a3e36f5dc2bcb3 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 17:30:09 +0200 Subject: [PATCH 106/653] zero padded not using dyn mem alloc now --- serviceinterface/ServiceInterfaceBuffer.h | 31 ++++++++++++++++------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index ab5d8c90..a032691c 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -1,6 +1,7 @@ #ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ #define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ +#include #include #include #include @@ -58,21 +59,33 @@ private: /** * This helper function returns the zero padded string version of a number. * The type is deduced automatically. + * TODO: This uses dynamic memory allocation, so we should provide + * a custom streambuf class to use it (which takes maxSize as argument) + * Then we would propably * @tparam T * @param num * @param width * @return */ template - std::string zero_padded(const T& num, uint8_t width) { - std::ostringstream string_to_pad; - string_to_pad << std::setw(width) << std::setfill('0') << num; - std::string result = string_to_pad.str(); - if (result.length() > width) - { - result.erase(0, result.length() - width); - } - return result; + ReturnValue_t zeroPadded(std::string stringToFill, const T& num, + uint8_t width) { + auto numString = std::to_string(num); + uint8_t i = 0; + for(i = 0; i < width; i++) { + stringToFill[i] = '0'; + } + numString.copy(stringToFill.data() + i, numString.size()); +// std::streambuf streambuf; +// std::ostringstream string_to_pad; +// string_to_pad << std::setw(width) << std::setfill('0') << num; +// std::string result = string_to_pad.str(); +// if (result.length() > width) +// { +// result.erase(0, result.length() - width); +// } +// return result; + //std::string dest = std::string( number_of_zeros, '0').append( original_string); } }; From d466921aa0f5ac1adc8fe8b95f83d8b518eb7653 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 17:58:22 +0200 Subject: [PATCH 107/653] some more experiments --- serviceinterface/ServiceInterfaceBuffer.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 3c365f17..7cf75a36 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -75,6 +75,8 @@ int ServiceInterfaceBuffer::sync(void) { size_t preambleSize = 0; auto preamble = getPreamble(&preambleSize); + uint8_t debugArray[96]; + memcpy(debugArray, preamble.data(), preambleSize); // Write logMessage and time this->putChars(preamble.c_str(), preamble.c_str() + preambleSize); // Handle output @@ -124,12 +126,11 @@ std::string ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { //// + zero_padded(loggerTime.second, 2) + "." //// + zero_padded(loggerTime.usecond/1000, 3) + " | "; // currentSize += logMessage.size(); //+ 4 +2 +1 +2 +1 +2 +1 + 3 + 3; -// preamble[currentSize] = '\0'; -// printf("%s", preamble.c_str()); -// uint8_t debugArray[96]; -// memcpy(debugArray, preamble.data(), currentSize); -// *preambleSize = currentSize; - return preamble; + preamble[++currentSize] = '\0'; + uint8_t debugArray[96]; + memcpy(debugArray, preamble.data(), currentSize); + *preambleSize = currentSize; + return std::move(preamble); } From c0808e71d99324fd40082bbbbb16d4cbbff9a7ab Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 19:07:04 +0200 Subject: [PATCH 108/653] no dyn memory allocation, print seems to work --- objectmanager/ObjectManagerIF.h | 1 - serviceinterface/ServiceInterfaceBuffer.cpp | 48 +++++++-------------- serviceinterface/ServiceInterfaceBuffer.h | 18 +------- 3 files changed, 17 insertions(+), 50 deletions(-) diff --git a/objectmanager/ObjectManagerIF.h b/objectmanager/ObjectManagerIF.h index aca24a24..830aa400 100644 --- a/objectmanager/ObjectManagerIF.h +++ b/objectmanager/ObjectManagerIF.h @@ -9,7 +9,6 @@ #define OBJECTMANAGERIF_H_ #include -#include #include #include diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 7cf75a36..30149ce0 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -1,6 +1,7 @@ #include #include #include +#include // to be implemented by bsp extern "C" void printChar(const char*, bool errStream); @@ -17,6 +18,7 @@ ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, setp( buf, buf + BUF_SIZE ); } preamble.reserve(96); + preamble.resize(96); } void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { @@ -78,7 +80,7 @@ int ServiceInterfaceBuffer::sync(void) { uint8_t debugArray[96]; memcpy(debugArray, preamble.data(), preambleSize); // Write logMessage and time - this->putChars(preamble.c_str(), preamble.c_str() + preambleSize); + this->putChars(preamble.data(), preamble.data() + preambleSize); // Handle output this->putChars(pbase(), pptr()); // This tells that buffer is empty again @@ -90,47 +92,29 @@ int ServiceInterfaceBuffer::sync(void) { std::string ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { Clock::TimeOfDay_t loggerTime; Clock::getDateAndTime(&loggerTime); - //preamble.clear(); - //std::string preamble; + std::string preamble (96, 0); size_t currentSize = 0; + char* parsePosition = &preamble[0]; if(addCrToPreamble) { preamble[0] = '\r'; currentSize += 1; + parsePosition += 1; } - int32_t charCount = sprintf(preamble.data() + currentSize, - "%s: | %lu:%02lu:%02lu.%03lu | ", - this->logMessage.c_str(), (unsigned long) loggerTime.hour, - (unsigned long) loggerTime.minute, - (unsigned long) loggerTime.second, - (unsigned long) loggerTime.usecond /1000); + int32_t charCount = sprintf(parsePosition, + "%s: | %02" SCNu32 ":%02" SCNu32 ":%02" SCNu32 ".%03" SCNu32 " | ", + this->logMessage.c_str(), loggerTime.hour, + loggerTime.minute, + loggerTime.second, + loggerTime.usecond /1000); if(charCount < 0) { printf("ServiceInterfaceBuffer: Failure parsing preamble"); return ""; } currentSize += charCount; -// size_t currentSize = 0; -// if(addCrToPreamble) { -// preamble[0] = '\r'; -// currentSize += 1; -// } -// logMessage.copy(preamble.data() + 1, logMessage.size()); -// currentSize += logMessage.size(); -// preamble[++currentSize] = ':'; -// preamble[++currentSize] = ' '; -// preamble[++currentSize] = '|'; -// zero_padded(loggerTime.hour, 2).copy(preamble.data() + ) -// //preamble.c_str() + 1 = logMessage; -//// -//// + ": | " + zero_padded(loggerTime.hour, 2) -//// + ":" + zero_padded(loggerTime.minute, 2) + ":" -//// + zero_padded(loggerTime.second, 2) + "." -//// + zero_padded(loggerTime.usecond/1000, 3) + " | "; -// currentSize += logMessage.size(); //+ 4 +2 +1 +2 +1 +2 +1 + 3 + 3; - preamble[++currentSize] = '\0'; - uint8_t debugArray[96]; - memcpy(debugArray, preamble.data(), currentSize); - *preambleSize = currentSize; - return std::move(preamble); + if(preambleSize != nullptr) { + *preambleSize = currentSize; + } + return preamble; } diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index a032691c..9a4ae479 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -76,29 +76,13 @@ private: stringToFill[i] = '0'; } numString.copy(stringToFill.data() + i, numString.size()); -// std::streambuf streambuf; -// std::ostringstream string_to_pad; -// string_to_pad << std::setw(width) << std::setfill('0') << num; -// std::string result = string_to_pad.str(); -// if (result.length() > width) -// { -// result.erase(0, result.length() - width); -// } -// return result; - //std::string dest = std::string( number_of_zeros, '0').append( original_string); + return HasReturnvaluesIF::RETURN_OK; } }; #endif - - - - - - - #ifdef UT699 class ServiceInterfaceBuffer: public std::basic_streambuf > { From 3a573c1b4c460cb19163d8bb9f319b501657f1e8 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 19:37:33 +0200 Subject: [PATCH 109/653] no run-time dyn memory allocation now --- serviceinterface/ServiceInterfaceBuffer.cpp | 8 +++++- serviceinterface/ServiceInterfaceBuffer.h | 28 ++---------------- serviceinterface/ServiceInterfaceStream.cpp | 13 ++++----- serviceinterface/ServiceInterfaceStream.h | 32 ++++++++++----------- 4 files changed, 31 insertions(+), 50 deletions(-) diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 30149ce0..f1332637 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -68,12 +68,15 @@ int ServiceInterfaceBuffer::overflow(int c) { } int ServiceInterfaceBuffer::sync(void) { - if(not this->isActive) { + if(not this->isActive and not buffered) { if(not buffered) { setp(buf, buf + BUF_SIZE - 1); } return 0; } + if(not buffered) { + return 0; + } size_t preambleSize = 0; auto preamble = getPreamble(&preambleSize); @@ -88,6 +91,9 @@ int ServiceInterfaceBuffer::sync(void) { return 0; } +bool ServiceInterfaceBuffer::isBuffered() const { + return buffered; +} std::string ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { Clock::TimeOfDay_t loggerTime; diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index 9a4ae479..00a8e74a 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -34,6 +34,7 @@ protected: //! for example when std::endl is put to stream. int sync(void) override; + bool isBuffered() const; private: //! For additional message information std::string logMessage; @@ -43,10 +44,10 @@ private: //! This is useful for some terminal programs which do not have //! implicit carriage return with newline characters. bool addCrToPreamble; - bool buffered; + //! This specifies to print to stderr and work in unbuffered mode. bool errStream; - + bool buffered; // Work in buffer mode. It is also possible to work without buffer. static size_t const BUF_SIZE = 128; char buf[BUF_SIZE]; @@ -55,29 +56,6 @@ private: void putChars(char const* begin, char const* end); std::string getPreamble(size_t * preambleSize = nullptr); - - /** - * This helper function returns the zero padded string version of a number. - * The type is deduced automatically. - * TODO: This uses dynamic memory allocation, so we should provide - * a custom streambuf class to use it (which takes maxSize as argument) - * Then we would propably - * @tparam T - * @param num - * @param width - * @return - */ - template - ReturnValue_t zeroPadded(std::string stringToFill, const T& num, - uint8_t width) { - auto numString = std::to_string(num); - uint8_t i = 0; - for(i = 0; i < width; i++) { - stringToFill[i] = '0'; - } - numString.copy(stringToFill.data() + i, numString.size()); - return HasReturnvaluesIF::RETURN_OK; - } }; #endif diff --git a/serviceinterface/ServiceInterfaceStream.cpp b/serviceinterface/ServiceInterfaceStream.cpp index bef8136e..76481ed1 100644 --- a/serviceinterface/ServiceInterfaceStream.cpp +++ b/serviceinterface/ServiceInterfaceStream.cpp @@ -2,21 +2,20 @@ ServiceInterfaceStream::ServiceInterfaceStream(std::string setMessage, bool addCrToPreamble, bool buffered, bool errStream, uint16_t port) : - std::ostream(&buf), - buf(setMessage, addCrToPreamble, buffered, errStream, port) { -} + std::ostream(&streambuf), + streambuf(setMessage, addCrToPreamble, buffered, errStream, port) {} void ServiceInterfaceStream::setActive( bool myActive) { - this->buf.isActive = myActive; + this->streambuf.isActive = myActive; } std::string ServiceInterfaceStream::getPreamble() { - return buf.getPreamble(); + return streambuf.getPreamble(); } void ServiceInterfaceStream::print(std::string error, bool withPreamble, bool withNewline, bool flush) { - if(not buffered and withPreamble) { + if(not streambuf.isBuffered() and withPreamble) { *this << getPreamble() << error; } else { @@ -27,7 +26,7 @@ void ServiceInterfaceStream::print(std::string error, *this << "\n"; } // if mode is non-buffered, no need to flush. - if(flush and buffered) { + if(flush and streambuf.isBuffered()) { this->flush(); } } diff --git a/serviceinterface/ServiceInterfaceStream.h b/serviceinterface/ServiceInterfaceStream.h index 9b8b5b6e..9e19c228 100644 --- a/serviceinterface/ServiceInterfaceStream.h +++ b/serviceinterface/ServiceInterfaceStream.h @@ -10,25 +10,22 @@ * std::cerr but has additional capability. Add preamble and timestamp * to output. Can be run in buffered or unbuffered mode. */ -class ServiceInterfaceStream : - public std::ostream { -protected: - ServiceInterfaceBuffer buf; +class ServiceInterfaceStream : public std::ostream { public: - /** - * This constructor is used by specifying the preamble message. - * Optionally, the output can be directed to stderr and a CR character - * can be prepended to the preamble. - * @param setMessage message of preamble. - * @param addCrToPreamble Useful for applications like Puttty. - * @param buffered specify whether to use buffered mode. - * @param errStream specify which output stream to use (stderr or stdout). - */ - ServiceInterfaceStream(std::string setMessage, - bool addCrToPreamble = false, bool buffered = true, + /** + * This constructor is used by specifying the preamble message. + * Optionally, the output can be directed to stderr and a CR character + * can be prepended to the preamble. + * @param setMessage message of preamble. + * @param addCrToPreamble Useful for applications like Puttty. + * @param buffered specify whether to use buffered mode. + * @param errStream specify which output stream to use (stderr or stdout). + */ + ServiceInterfaceStream(std::string setMessage, + bool addCrToPreamble = false, bool buffered = true, bool errStream = false, uint16_t port = 1234); - //! An inactive stream will not print anything. + //! An inactive stream will not print anything. void setActive( bool ); /** @@ -45,7 +42,8 @@ public: void print(std::string error, bool withPreamble = true, bool withNewline = true, bool flush = true); - bool buffered = false; +protected: + ServiceInterfaceBuffer streambuf; }; // Forward declaration of interface streams. These should be instantiated in From 7014833c1c89938d0475e88a7a57b628933051e5 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 19:50:56 +0200 Subject: [PATCH 110/653] improvements and fixes --- serviceinterface/ServiceInterfaceBuffer.cpp | 15 ++++++++------- serviceinterface/ServiceInterfaceBuffer.h | 9 +++++++-- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index f1332637..5c80862c 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -17,8 +17,8 @@ ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, // Set pointers if the stream is buffered. setp( buf, buf + BUF_SIZE ); } - preamble.reserve(96); - preamble.resize(96); + preamble.reserve(MAX_PREAMBLE_SIZE); + preamble.resize(MAX_PREAMBLE_SIZE); } void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { @@ -36,7 +36,6 @@ void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { else { printChar(begin, false); } - } } @@ -80,8 +79,6 @@ int ServiceInterfaceBuffer::sync(void) { size_t preambleSize = 0; auto preamble = getPreamble(&preambleSize); - uint8_t debugArray[96]; - memcpy(debugArray, preamble.data(), preambleSize); // Write logMessage and time this->putChars(preamble.data(), preamble.data() + preambleSize); // Handle output @@ -98,7 +95,6 @@ bool ServiceInterfaceBuffer::isBuffered() const { std::string ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { Clock::TimeOfDay_t loggerTime; Clock::getDateAndTime(&loggerTime); - std::string preamble (96, 0); size_t currentSize = 0; char* parsePosition = &preamble[0]; if(addCrToPreamble) { @@ -113,7 +109,12 @@ std::string ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { loggerTime.second, loggerTime.usecond /1000); if(charCount < 0) { - printf("ServiceInterfaceBuffer: Failure parsing preamble"); + printf("ServiceInterfaceBuffer: Failure parsing preamble\r\n"); + return ""; + } + if(charCount > MAX_PREAMBLE_SIZE) { + printf("ServiceInterfaceBuffer: Char count too large for maximum " + "preamble size"); return ""; } currentSize += charCount; diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index 00a8e74a..39ea25c2 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -20,6 +20,8 @@ class ServiceInterfaceBuffer: public std::streambuf { friend class ServiceInterfaceStream; public: + static constexpr uint8_t MAX_PREAMBLE_SIZE = 40; + ServiceInterfaceBuffer(std::string setMessage, bool addCrToPreamble, bool buffered, bool errStream, uint16_t port); @@ -41,14 +43,17 @@ private: std::string preamble; // For EOF detection typedef std::char_traits Traits; + //! This is useful for some terminal programs which do not have //! implicit carriage return with newline characters. bool addCrToPreamble; + //! Specifies whether the stream operates in buffered or unbuffered mode. + bool buffered; //! This specifies to print to stderr and work in unbuffered mode. bool errStream; - bool buffered; - // Work in buffer mode. It is also possible to work without buffer. + + //! Needed for buffered mode. static size_t const BUF_SIZE = 128; char buf[BUF_SIZE]; From 639b517edaffc63094870cd1bcdcdb9bed9229ca Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 19:57:25 +0200 Subject: [PATCH 111/653] removed unnecessary change --- osal/FreeRTOS/FixedTimeslotTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index 549ffbf1..fb3c3b03 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -68,7 +68,7 @@ ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, } sif::error << "Component " << std::hex << componentId << - " not found, not adding it to pst\r" << std::endl; + " not found, not adding it to pst" << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } From 56340bb8b69b6a02e733960693f497b29aa75a17 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 20:12:37 +0200 Subject: [PATCH 112/653] free rtos mutex improvements --- ipc/MutexIF.h | 17 +++++++++++++++-- osal/FreeRTOS/Mutex.cpp | 12 ++++++------ osal/FreeRTOS/Mutex.h | 2 +- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/ipc/MutexIF.h b/ipc/MutexIF.h index dcb1cf33..29e59e58 100644 --- a/ipc/MutexIF.h +++ b/ipc/MutexIF.h @@ -12,8 +12,21 @@ */ class MutexIF { public: - static const uint32_t NO_TIMEOUT; //!< Needs to be defined in implementation. - static const uint32_t MAX_TIMEOUT; + /** + * @brief Timeout value used for polling lock attempt. + * @details + * If the lock is not successfull, MUTEX_TIMEOUT will be returned + * immediately. Value needs to be defined in implementation. + */ + static const uint32_t POLLING; + /** + * @brief Timeout value used for permanent blocking lock attempt. + * @details + * The task will be blocked (indefinitely) until the mutex is unlocked. + * Value needs to be defined in implementation. + */ + static const uint32_t BLOCKING; + static const uint8_t INTERFACE_ID = CLASS_ID::MUTEX_IF; /** * The system lacked the necessary resources (other than memory) to initialize another mutex. diff --git a/osal/FreeRTOS/Mutex.cpp b/osal/FreeRTOS/Mutex.cpp index cc2f865f..6d90c3f6 100644 --- a/osal/FreeRTOS/Mutex.cpp +++ b/osal/FreeRTOS/Mutex.cpp @@ -2,8 +2,8 @@ #include -const uint32_t MutexIF::NO_TIMEOUT = 0; -const uint32_t MutexIF::MAX_TIMEOUT = portMAX_DELAY; +const uint32_t MutexIF::POLLING = 0; +const uint32_t MutexIF::BLOCKING = portMAX_DELAY; Mutex::Mutex() { handle = xSemaphoreCreateMutex(); @@ -23,11 +23,11 @@ ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { if (handle == nullptr) { return MutexIF::MUTEX_NOT_FOUND; } - TickType_t timeout = MutexIF::NO_TIMEOUT; - if(timeoutMs == MutexIF::MAX_TIMEOUT) { - timeout = MutexIF::MAX_TIMEOUT; + TickType_t timeout = MutexIF::POLLING; + if(timeoutMs == MutexIF::BLOCKING) { + timeout = MutexIF::BLOCKING; } - else if(timeoutMs > MutexIF::NO_TIMEOUT){ + else if(timeoutMs > MutexIF::POLLING){ timeout = pdMS_TO_TICKS(timeoutMs); } diff --git a/osal/FreeRTOS/Mutex.h b/osal/FreeRTOS/Mutex.h index 90e82467..d6e0aab9 100644 --- a/osal/FreeRTOS/Mutex.h +++ b/osal/FreeRTOS/Mutex.h @@ -18,7 +18,7 @@ class Mutex : public MutexIF { public: Mutex(); ~Mutex(); - ReturnValue_t lockMutex(uint32_t timeoutMs = MutexIF::MAX_TIMEOUT) override; + ReturnValue_t lockMutex(uint32_t timeoutMs = MutexIF::BLOCKING) override; ReturnValue_t unlockMutex() override; private: SemaphoreHandle_t handle; From 869700e6f52eca5efe8b1c5a20e5923730b51d8e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 20:20:38 +0200 Subject: [PATCH 113/653] added mutex IF timeout name --- datapool/DataPool.cpp | 2 +- events/EventManager.cpp | 2 +- health/HealthTable.cpp | 12 ++++++------ internalError/InternalErrorReporter.cpp | 18 +++++++++--------- osal/FreeRTOS/Clock.cpp | 4 ++-- osal/linux/Mutex.cpp | 8 ++++++-- storagemanager/PoolManager.h | 6 +++--- 7 files changed, 28 insertions(+), 24 deletions(-) diff --git a/datapool/DataPool.cpp b/datapool/DataPool.cpp index 70a2a3fb..2c226c54 100644 --- a/datapool/DataPool.cpp +++ b/datapool/DataPool.cpp @@ -61,7 +61,7 @@ ReturnValue_t DataPool::freeDataPoolLock() { } ReturnValue_t DataPool::lockDataPool() { - ReturnValue_t status = mutex->lockMutex(MutexIF::NO_TIMEOUT); + ReturnValue_t status = mutex->lockMutex(MutexIF::BLOCKING); if ( status != RETURN_OK ) { sif::error << "DataPool::DataPool: lock of mutex failed with error code: " << status << std::endl; } diff --git a/events/EventManager.cpp b/events/EventManager.cpp index 0f1511e4..c7d9cf8f 100644 --- a/events/EventManager.cpp +++ b/events/EventManager.cpp @@ -147,7 +147,7 @@ void EventManager::printEvent(EventMessage* message) { #endif void EventManager::lockMutex() { - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); } void EventManager::unlockMutex() { diff --git a/health/HealthTable.cpp b/health/HealthTable.cpp index a575b282..d0e5485a 100644 --- a/health/HealthTable.cpp +++ b/health/HealthTable.cpp @@ -26,7 +26,7 @@ ReturnValue_t HealthTable::registerObject(object_id_t object, void HealthTable::setHealth(object_id_t object, HasHealthIF::HealthState newState) { - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); HealthMap::iterator iter = healthMap.find(object); if (iter != healthMap.end()) { iter->second = newState; @@ -36,7 +36,7 @@ void HealthTable::setHealth(object_id_t object, HasHealthIF::HealthState HealthTable::getHealth(object_id_t object) { HasHealthIF::HealthState state = HasHealthIF::HEALTHY; - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); HealthMap::iterator iter = healthMap.find(object); if (iter != healthMap.end()) { state = iter->second; @@ -46,7 +46,7 @@ HasHealthIF::HealthState HealthTable::getHealth(object_id_t object) { } uint32_t HealthTable::getPrintSize() { - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); uint32_t size = healthMap.size() * 5 + 2; mutex->unlockMutex(); return size; @@ -54,7 +54,7 @@ uint32_t HealthTable::getPrintSize() { bool HealthTable::hasHealth(object_id_t object) { bool exits = false; - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); HealthMap::iterator iter = healthMap.find(object); if (iter != healthMap.end()) { exits = true; @@ -64,7 +64,7 @@ bool HealthTable::hasHealth(object_id_t object) { } void HealthTable::printAll(uint8_t* pointer, uint32_t maxSize) { - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); uint32_t size = 0; uint16_t count = healthMap.size(); ReturnValue_t result = SerializeAdapter::serialize(&count, @@ -85,7 +85,7 @@ void HealthTable::printAll(uint8_t* pointer, uint32_t maxSize) { ReturnValue_t HealthTable::iterate( std::pair *value, bool reset) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); if (reset) { mapIterator = healthMap.begin(); } diff --git a/internalError/InternalErrorReporter.cpp b/internalError/InternalErrorReporter.cpp index 9a8ede00..dbcd2622 100644 --- a/internalError/InternalErrorReporter.cpp +++ b/internalError/InternalErrorReporter.cpp @@ -54,7 +54,7 @@ void InternalErrorReporter::lostTm() { uint32_t InternalErrorReporter::getAndResetQueueHits() { uint32_t value; - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); value = queueHits; queueHits = 0; mutex->unlockMutex(); @@ -63,21 +63,21 @@ uint32_t InternalErrorReporter::getAndResetQueueHits() { uint32_t InternalErrorReporter::getQueueHits() { uint32_t value; - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); value = queueHits; mutex->unlockMutex(); return value; } void InternalErrorReporter::incrementQueueHits() { - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); queueHits++; mutex->unlockMutex(); } uint32_t InternalErrorReporter::getAndResetTmHits() { uint32_t value; - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); value = tmHits; tmHits = 0; mutex->unlockMutex(); @@ -86,14 +86,14 @@ uint32_t InternalErrorReporter::getAndResetTmHits() { uint32_t InternalErrorReporter::getTmHits() { uint32_t value; - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); value = tmHits; mutex->unlockMutex(); return value; } void InternalErrorReporter::incrementTmHits() { - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); tmHits++; mutex->unlockMutex(); } @@ -104,7 +104,7 @@ void InternalErrorReporter::storeFull() { uint32_t InternalErrorReporter::getAndResetStoreHits() { uint32_t value; - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); value = storeHits; storeHits = 0; mutex->unlockMutex(); @@ -113,14 +113,14 @@ uint32_t InternalErrorReporter::getAndResetStoreHits() { uint32_t InternalErrorReporter::getStoreHits() { uint32_t value; - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); value = storeHits; mutex->unlockMutex(); return value; } void InternalErrorReporter::incrementStoreHits() { - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); storeHits++; mutex->unlockMutex(); } diff --git a/osal/FreeRTOS/Clock.cpp b/osal/FreeRTOS/Clock.cpp index cffc2125..589f44d5 100644 --- a/osal/FreeRTOS/Clock.cpp +++ b/osal/FreeRTOS/Clock.cpp @@ -154,7 +154,7 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) { if (checkOrCreateClockMutex() != HasReturnvaluesIF::RETURN_OK) { return HasReturnvaluesIF::RETURN_FAILED; } - ReturnValue_t result = timeMutex->lockMutex(MutexIF::NO_TIMEOUT); + ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -169,7 +169,7 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) { if (timeMutex == NULL) { return HasReturnvaluesIF::RETURN_FAILED; } - ReturnValue_t result = timeMutex->lockMutex(MutexIF::NO_TIMEOUT); + ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } diff --git a/osal/linux/Mutex.cpp b/osal/linux/Mutex.cpp index 36bb3ce4..62fbccd7 100644 --- a/osal/linux/Mutex.cpp +++ b/osal/linux/Mutex.cpp @@ -2,7 +2,8 @@ #include #include -const uint32_t MutexIF::NO_TIMEOUT = 0; +const uint32_t MutexIF::POLLING = 0; +const uint32_t MutexIF::NO_TIMEOUT = 0xffffffff; uint8_t Mutex::count = 0; @@ -39,7 +40,10 @@ Mutex::~Mutex() { ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { int status = 0; - if (timeoutMs != MutexIF::NO_TIMEOUT) { + if(timeoutMs == MutexIF::POLLING) { + status = pthread_mutex_trylock(&mutex); + } + else if (timeoutMs != MutexIF::BLOCKING) { timespec timeOut; clock_gettime(CLOCK_REALTIME, &timeOut); uint64_t nseconds = timeOut.tv_sec * 1000000000 + timeOut.tv_nsec; diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index 68a7addc..5fd9b5f7 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -49,7 +49,7 @@ public: template inline ReturnValue_t PoolManager::reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault) { - MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); + MutexHelper mutexHelper(mutex,MutexIF::BLOCKING); ReturnValue_t status = LocalPool::reserveSpace(size,address,ignoreFault); return status; } @@ -70,7 +70,7 @@ template inline ReturnValue_t PoolManager::deleteData( store_address_t packet_id) { // debug << "PoolManager( " << translateObject(getObjectId()) << " )::deleteData from store " << packet_id.pool_index << ". id is " << packet_id.packet_index << std::endl; - MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); + MutexHelper mutexHelper(mutex,MutexIF::BLOCKING); ReturnValue_t status = LocalPool::deleteData(packet_id); return status; } @@ -78,7 +78,7 @@ inline ReturnValue_t PoolManager::deleteData( template inline ReturnValue_t PoolManager::deleteData(uint8_t* buffer, uint32_t size, store_address_t* storeId) { - MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); + MutexHelper mutexHelper(mutex,MutexIF::BLOCKING); ReturnValue_t status = LocalPool::deleteData(buffer, size, storeId); return status; } From fbf804cdca0c13e0d272af81f09493550f1ee13d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 20:25:15 +0200 Subject: [PATCH 114/653] linux changes for mutex --- osal/linux/Clock.cpp | 4 ++-- osal/linux/Mutex.cpp | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/osal/linux/Clock.cpp b/osal/linux/Clock.cpp index e24a4fe4..53a597d6 100644 --- a/osal/linux/Clock.cpp +++ b/osal/linux/Clock.cpp @@ -170,7 +170,7 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) { if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){ return HasReturnvaluesIF::RETURN_FAILED; } - ReturnValue_t result = timeMutex->lockMutex(MutexIF::NO_TIMEOUT); + ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -185,7 +185,7 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) { if(timeMutex==NULL){ return HasReturnvaluesIF::RETURN_FAILED; } - ReturnValue_t result = timeMutex->lockMutex(MutexIF::NO_TIMEOUT); + ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } diff --git a/osal/linux/Mutex.cpp b/osal/linux/Mutex.cpp index 62fbccd7..169ac354 100644 --- a/osal/linux/Mutex.cpp +++ b/osal/linux/Mutex.cpp @@ -3,7 +3,7 @@ #include const uint32_t MutexIF::POLLING = 0; -const uint32_t MutexIF::NO_TIMEOUT = 0xffffffff; +const uint32_t MutexIF::BLOCKING = 0xffffffff; uint8_t Mutex::count = 0; @@ -43,7 +43,10 @@ ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { if(timeoutMs == MutexIF::POLLING) { status = pthread_mutex_trylock(&mutex); } - else if (timeoutMs != MutexIF::BLOCKING) { + else if (timeoutMs == MutexIF::BLOCKING) { + status = pthread_mutex_lock(&mutex); + } + else { timespec timeOut; clock_gettime(CLOCK_REALTIME, &timeOut); uint64_t nseconds = timeOut.tv_sec * 1000000000 + timeOut.tv_nsec; @@ -51,9 +54,8 @@ ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { timeOut.tv_sec = nseconds / 1000000000; timeOut.tv_nsec = nseconds - timeOut.tv_sec * 1000000000; status = pthread_mutex_timedlock(&mutex, &timeOut); - } else { - status = pthread_mutex_lock(&mutex); } + switch (status) { case EINVAL: //The mutex was created with the protocol attribute having the value PTHREAD_PRIO_PROTECT and the calling thread's priority is higher than the mutex's current priority ceiling. From cef5fda3796754ae28b3982a8de2bdca6c92a86e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 5 Jun 2020 13:43:06 +0200 Subject: [PATCH 115/653] refactored initializer list --- datapool/PoolEntry.cpp | 35 ++++++++------ datapool/PoolEntry.h | 95 +++++++++++++++++++++++++------------- datapool/PoolEntryIF.h | 57 +++++++++++------------ datapool/PoolRawAccess.cpp | 2 + 4 files changed, 111 insertions(+), 78 deletions(-) diff --git a/datapool/PoolEntry.cpp b/datapool/PoolEntry.cpp index 1d8d2486..a87a6c4e 100644 --- a/datapool/PoolEntry.cpp +++ b/datapool/PoolEntry.cpp @@ -1,26 +1,34 @@ #include #include +#include +#include template -PoolEntry::PoolEntry(std::initializer_list initValue, uint8_t set_length, - uint8_t set_valid ) : length(set_length), valid(set_valid) { +PoolEntry::PoolEntry(std::initializer_list initValue, uint8_t setLength, + bool setValid ) : length(setLength), valid(setValid) { this->address = new T[this->length]; if(initValue.size() == 0) { - memset(this->address, 0, this->getByteSize()); + std::memset(this->address, 0, this->getByteSize()); + } + else if (initValue.size() != setLength){ + sif::warning << "PoolEntry: setLength is not equal to initializer list" + "length! Performing zero initialization with given setLength" + << std::endl; + std::memset(this->address, 0, this->getByteSize()); } else { - memcpy(this->address, initValue.begin(), this->getByteSize()); + std::copy(initValue.begin(), initValue.end(), this->address); } } template -PoolEntry::PoolEntry( T* initValue, uint8_t set_length, uint8_t set_valid ) : - length(set_length), valid(set_valid) { +PoolEntry::PoolEntry( T* initValue, uint8_t setLength, bool setValid ) : + length(setLength), valid(setValid) { this->address = new T[this->length]; if (initValue != nullptr) { - memcpy(this->address, initValue, this->getByteSize() ); + std::memcpy(this->address, initValue, this->getByteSize() ); } else { - memset(this->address, 0, this->getByteSize() ); + std::memset(this->address, 0, this->getByteSize() ); } } @@ -47,21 +55,20 @@ void* PoolEntry::getRawData() { } template -void PoolEntry::setValid( uint8_t isValid ) { +void PoolEntry::setValid(bool isValid) { this->valid = isValid; } template -uint8_t PoolEntry::getValid() { +bool PoolEntry::getValid() { return valid; } template void PoolEntry::print() { - for (uint8_t size = 0; size < this->length; size++ ) { - sif::debug << "| " << std::hex << (double)this->address[size] - << (this->valid? " (valid) " : " (invalid) "); - } + sif::debug << "Pool Entry Validity: " << + (this->valid? " (valid) " : " (invalid) ") << std::endl; + printer::print(reinterpret_cast(address), length); sif::debug << std::dec << std::endl; } diff --git a/datapool/PoolEntry.h b/datapool/PoolEntry.h index 4487db72..1a22bb63 100644 --- a/datapool/PoolEntry.h +++ b/datapool/PoolEntry.h @@ -1,59 +1,86 @@ -#ifndef POOLENTRY_H_ -#define POOLENTRY_H_ +#ifndef FRAMEWORK_DATAPOOL_POOLENTRY_H_ +#define FRAMEWORK_DATAPOOL_POOLENTRY_H_ #include -#include -#include + #include #include +#include + /** * @brief This is a small helper class that defines a single data pool entry. * @details * The helper is used to store all information together with the data as a - * single data pool entry.The content's type is defined by the template argument. - * It is prepared for use with plain old data types, but may be extended to - * complex types if necessary. It can be initialized with a certain value, - * size and validity flag. It holds a pointer to the real data and offers - * methods to access this data and to acquire additional information - * (such as validity and array/byte size). It is NOT intended to be used - * outside the DataPool class. + * single data pool entry. The content's type is defined by the template + * argument. + * + * It is prepared for use with plain old data types, but may be + * extended to complex types if necessary. It can be initialized with a + * certain value, size and validity flag. + * + * It holds a pointer to the real data and offers methods to access this data + * and to acquire additional information (such as validity and array/byte size). + * It is NOT intended to be used outside DataPool implementations as it performs + * dynamic memory allocation. * * @ingroup data_pool - * */ template class PoolEntry : public PoolEntryIF { public: static_assert(not std::is_same::value, - "Do not use boolean for the PoolEntry type, use uint8_t instead!" - "Warum? Darum :-)"); + "Do not use boolean for the PoolEntry type, use uint8_t " + "instead! The ECSS standard defines a boolean as a one bit " + "field. Therefore it is preferred to store a boolean as an " + "uint8_t"); /** * @brief In the classe's constructor, space is allocated on the heap and * potential init values are copied to that space. - * @param initValue Initializer list with values to initialize with - * @param set_length Defines the array length of this entry. - * @param set_valid Sets the initialization flag. - * It is invalid (0) by default. + * @details + * Not passing any arguments will initialize an non-array pool entry + * (setLength = 1) with an initial invalid state. + * Please note that if an initializer list is passed, the correct + * corresponding length should be passed too, otherwise a zero + * initialization will be performed with the given setLength. + * @param initValue + * Initializer list with values to initialize with, for example {0,0} to + * initialize the two entries to zero. + * @param setLength + * Defines the array length of this entry. Should be equal to the + * intializer list length. + * @param setValid + * Sets the initialization flag. It is invalid by default. */ - PoolEntry(std::initializer_list initValue = {}, uint8_t set_length = 1, - uint8_t set_valid = 0); + PoolEntry(std::initializer_list initValue = {}, uint8_t setLength = 1, + bool setValid = false); /** * @brief In the classe's constructor, space is allocated on the heap and * potential init values are copied to that space. - * @param initValue A pointer to the single value or array that holds - * the init value. With the default value (nullptr), the entry is - * initalized with all 0. - * @param set_length Defines the array length of this entry. - * @param set_valid Sets the initialization flag. It is invalid (0) by default. + * @param initValue + * A pointer to the single value or array that holds the init value. + * With the default value (nullptr), the entry is initalized with all 0. + * @param setLength + * Defines the array length of this entry. + * @param setValid + * Sets the initialization flag. It is invalid by default. */ - PoolEntry(T* initValue = nullptr, uint8_t set_length = 1, uint8_t set_valid = 0); + PoolEntry(T* initValue, uint8_t setLength = 1, bool setValid = false); + + //! Explicitely deleted copy ctor, copying is not allowed! + PoolEntry(const PoolEntry&) = delete; + //! Explicitely deleted copy assignment, copying is not allowed! + PoolEntry& operator=(const PoolEntry&) = delete; /** - * @brief The allocated memory for the variable is freed in the destructor. - * @details As the data pool is global, this dtor is only called on program exit. - * PoolEntries shall never be copied, as a copy might delete the variable on the heap. + * @brief The allocated memory for the variable is freed + * in the destructor. + * @details + * As the data pool is global, this dtor is only called on program exit. + * PoolEntries shall never be copied, as a copy might delete the variable + * on the heap. */ ~PoolEntry(); + /** * @brief This is the address pointing to the allocated memory. */ @@ -82,13 +109,15 @@ public: */ void* getRawData(); /** - * @brief This method allows to set the valid information of the pool entry. + * @brief This method allows to set the valid information + * of the pool entry. */ - void setValid( uint8_t isValid ); + void setValid( bool isValid ); /** - * @brief This method allows to get the valid information of the pool entry. + * @brief This method allows to get the valid information + * of the pool entry. */ - uint8_t getValid(); + bool getValid(); /** * @brief This is a debug method that prints all values and the valid * information to the screen. It prints all array entries in a row. diff --git a/datapool/PoolEntryIF.h b/datapool/PoolEntryIF.h index 514e67ef..a075436e 100644 --- a/datapool/PoolEntryIF.h +++ b/datapool/PoolEntryIF.h @@ -1,62 +1,57 @@ -/** - * \file PoolEntryIF.h - * - * \brief This file holds the class that defines the Interface for Pool Entry elements. - * - * \date 10/18/2012 - * - * \author Bastian Baetz - */ - -#ifndef POOLENTRYIF_H_ -#define POOLENTRYIF_H_ +#ifndef FRAMEWORK_DATAPOOL_POOLENTRYIF_H_ +#define FRAMEWORK_DATAPOOL_POOLENTRYIF_H_ #include -#include - - +#include /** - * \brief This interface defines the access possibilities to a single data pool entry. + * @brief This interface defines the access possibilities to a + * single data pool entry. + * @details + * The interface provides methods to determine the size and the validity + * information of a value. It also defines a method to receive a pointer to the + * raw data content. It is mainly used by DataPool itself, but also as a + * return pointer. * - * \details The interface provides methods to determine the size and the validity information of a value. - * It also defines a method to receive a pointer to the raw data content. - * It is mainly used by DataPool itself, but also as a return pointer. - * - * \ingroup data_pool + * @author Bastian Baetz + * @ingroup data_pool * */ class PoolEntryIF { public: /** - * \brief This is an empty virtual destructor, as it is proposed for C++ interfaces. + * @brief This is an empty virtual destructor, + * as it is required for C++ interfaces. */ virtual ~PoolEntryIF() { } /** - * \brief getSize returns the array size of the entry. A single variable parameter has size 1. + * @brief getSize returns the array size of the entry. + * A single variable parameter has size 1. */ virtual uint8_t getSize() = 0; /** - * \brief This operation returns the size in bytes, which is calculated by + * @brief This operation returns the size in bytes, which is calculated by * sizeof(type) * array_size. */ virtual uint16_t getByteSize() = 0; /** - * \brief This operation returns a the address pointer casted to void*. + * @brief This operation returns a the address pointer casted to void*. */ virtual void* getRawData() = 0; /** - * \brief This method allows to set the valid information of the pool entry. + * @brief This method allows to set the valid information of the pool entry. */ - virtual void setValid(uint8_t isValid) = 0; + virtual void setValid(bool isValid) = 0; /** - * \brief This method allows to set the valid information of the pool entry. + * @brief This method allows to set the valid information of the pool entry. */ - virtual uint8_t getValid() = 0; + virtual bool getValid() = 0; /** - * \brief This is a debug method that prints all values and the valid information to the screen. - * It prints all array entries in a row. + * @brief This is a debug method that prints all values and the valid + * information to the screen. It prints all array entries in a row. + * @details + * Also displays whether the pool entry is valid or invalid. */ virtual void print() = 0; /** diff --git a/datapool/PoolRawAccess.cpp b/datapool/PoolRawAccess.cpp index ba68bcd2..fd81b894 100644 --- a/datapool/PoolRawAccess.cpp +++ b/datapool/PoolRawAccess.cpp @@ -4,6 +4,8 @@ #include #include +#include + PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry, DataSetIF* data_set, ReadWriteMode_t setReadWriteMode) : dataPoolId(set_id), arrayEntry(setArrayEntry), valid(false), type(Type::UNKNOWN_TYPE), typeSize( From 03e9362825e474b26fe79fc9405104496bdac221 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 5 Jun 2020 20:42:39 +0200 Subject: [PATCH 116/653] mutex helper special output for timeout fail --- ipc/MutexHelper.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ipc/MutexHelper.h b/ipc/MutexHelper.h index 671cd5a6..20760b32 100644 --- a/ipc/MutexHelper.h +++ b/ipc/MutexHelper.h @@ -9,8 +9,12 @@ public: MutexHelper(MutexIF* mutex, uint32_t timeoutMs) : internalMutex(mutex) { ReturnValue_t status = mutex->lockMutex(timeoutMs); - if(status != HasReturnvaluesIF::RETURN_OK){ - sif::error << "MutexHelper: Lock of Mutex failed " << + if(status == MutexIF::MUTEX_TIMEOUT) { + sif::error << "MutexHelper: Lock of mutex failed with timeout of" + << timeoutMs << " milliseconds!" << std::endl; + } + else if(status != HasReturnvaluesIF::RETURN_OK){ + sif::error << "MutexHelper: Lock of Mutex failed with code " << status << std::endl; } } From 9c766c123d965726805e8a7f471dda7f91f621f2 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 6 Jun 2020 20:56:09 +0200 Subject: [PATCH 117/653] device command iter was uninitialized --- devicehandlers/DeviceHandlerBase.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 338ed9b2..054112b1 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -31,19 +31,21 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, healthHelper(this,setObjectId), modeHelper(this), parameterHelper(this), childTransitionFailure(RETURN_OK), fdirInstance(fdirInstance), hkSwitcher(this), defaultFDIRUsed(fdirInstance == nullptr), - switchOffWasReported(false), actionHelper(this, nullptr), cookieInfo(), + switchOffWasReported(false), actionHelper(this, nullptr), 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); + cookieInfo.state = COOKIE_UNUSED; + cookieInfo.pendingCommand = deviceCommandMap.end(); if (comCookie == nullptr) { sif::error << "DeviceHandlerBase: ObjectID 0x" << std::hex << std::setw(8) << std::setfill('0') << this->getObjectId() << std::dec << ": Do not pass nullptr as a cookie, consider " - "passing a dummy cookie instead!" << std::endl; + << std::setfill(' ') << "passing a dummy cookie instead!" << + std::endl; } if (this->fdirInstance == nullptr) { this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, @@ -553,12 +555,12 @@ void DeviceHandlerBase::doSendRead() { ReturnValue_t result; size_t requestLen = 0; - DeviceReplyIter iter = deviceReplyMap.find(cookieInfo.pendingCommand->first); - if(iter != deviceReplyMap.end()) { - requestLen = iter->second.replyLen; - } - else { - requestLen = 0; + if(cookieInfo.pendingCommand != deviceCommandMap.end()) { + DeviceReplyIter iter = deviceReplyMap.find( + cookieInfo.pendingCommand->first); + if(iter != deviceReplyMap.end()) { + requestLen = iter->second.replyLen; + } } result = communicationInterface->requestReceiveMessage(comCookie, requestLen); From 20abb810f2ba16ab9781e07bd0c06c7fde4e9efb Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 8 Jun 2020 14:11:38 +0200 Subject: [PATCH 118/653] i hope this is correct --- osal/rtems/Mutex.cpp | 3 ++- osal/rtems/Mutex.h | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osal/rtems/Mutex.cpp b/osal/rtems/Mutex.cpp index d094e1dc..0c1675b1 100644 --- a/osal/rtems/Mutex.cpp +++ b/osal/rtems/Mutex.cpp @@ -1,7 +1,8 @@ #include "Mutex.h" #include -const uint32_t MutexIF::NO_TIMEOUT = RTEMS_NO_TIMEOUT; +const uint32_t MutexIF::BLOCKING = RTEMS_NO_TIMEOUT; +const uint32_t MutexIF::POLLING = RTEMS_NO_WAIT; uint8_t Mutex::count = 0; Mutex::Mutex() : diff --git a/osal/rtems/Mutex.h b/osal/rtems/Mutex.h index 19b34e7f..486055ba 100644 --- a/osal/rtems/Mutex.h +++ b/osal/rtems/Mutex.h @@ -1,5 +1,5 @@ -#ifndef OS_RTEMS_MUTEX_H_ -#define OS_RTEMS_MUTEX_H_ +#ifndef FRAMEWORK_OSAL_RTEMS_MUTEX_H_ +#define FRAMEWORK_OSAL_RTEMS_MUTEX_H_ #include #include "RtemsBasic.h" From b5567e8aae90e5f87e6d94b45b9c51889387bb41 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 9 Jun 2020 13:26:27 +0200 Subject: [PATCH 119/653] rtems mutex update --- osal/rtems/Mutex.cpp | 17 +++++++++++++++-- osal/rtems/Mutex.h | 2 +- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/osal/rtems/Mutex.cpp b/osal/rtems/Mutex.cpp index 0c1675b1..5487a503 100644 --- a/osal/rtems/Mutex.cpp +++ b/osal/rtems/Mutex.cpp @@ -1,7 +1,7 @@ #include "Mutex.h" #include -const uint32_t MutexIF::BLOCKING = RTEMS_NO_TIMEOUT; +const uint32_t MutexIF::BLOCKING = RTEMS_WAIT; const uint32_t MutexIF::POLLING = RTEMS_NO_WAIT; uint8_t Mutex::count = 0; @@ -26,7 +26,20 @@ Mutex::~Mutex() { } ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { - rtems_status_code status = rtems_semaphore_obtain(mutexId, RTEMS_WAIT, timeoutMs); + if(timeoutMs == MutexIF::BLOCKING) { + rtems_status_code status = rtems_semaphore_obtain(mutexId, + RTEMS_WAIT, timeoutMs); + } + else if(timeoutMs == MutexIF::POLLING) { + timeoutMs = RTEMS_NO_TIMEOUT; + rtems_status_code status = rtems_semaphore_obtain(mutexId, + RTEMS_NO_WAIT, timeoutMs); + } + else { + rtems_status_code status = rtems_semaphore_obtain(mutexId, + RTEMS_NO_WAIT, timeoutMs); + } + switch(status){ case RTEMS_SUCCESSFUL: //semaphore obtained successfully diff --git a/osal/rtems/Mutex.h b/osal/rtems/Mutex.h index 486055ba..4aa25e40 100644 --- a/osal/rtems/Mutex.h +++ b/osal/rtems/Mutex.h @@ -8,7 +8,7 @@ class Mutex : public MutexIF { public: Mutex(); ~Mutex(); - ReturnValue_t lockMutex(uint32_t timeoutMs); + ReturnValue_t lockMutex(uint32_t timeoutMs = MutexIF::BLOCKING); ReturnValue_t unlockMutex(); private: rtems_id mutexId; From 860cdba94d4cb6d1de1ba59f4a0f1dd68f761549 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 10 Jun 2020 20:28:44 +0200 Subject: [PATCH 120/653] subservicve passed to handleRequest() --- tmtcservices/PusServiceBase.cpp | 3 ++- tmtcservices/PusServiceBase.h | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tmtcservices/PusServiceBase.cpp b/tmtcservices/PusServiceBase.cpp index b1d97293..c27defe6 100644 --- a/tmtcservices/PusServiceBase.cpp +++ b/tmtcservices/PusServiceBase.cpp @@ -29,7 +29,8 @@ ReturnValue_t PusServiceBase::performOperation(uint8_t opCode) { this->currentPacket.setStoreAddress(message.getStorageId()); // info << "Service " << (uint16_t) this->serviceId << ": new packet!" << std::endl; - ReturnValue_t return_code = this->handleRequest(); + ReturnValue_t return_code = this->handleRequest(currentPacket.getSubService()); + // debug << "Service " << (uint16_t)this->serviceId << ": handleRequest returned: " << (int)return_code << std::endl; if (return_code == RETURN_OK) { this->verifyReporter.sendSuccessReport( diff --git a/tmtcservices/PusServiceBase.h b/tmtcservices/PusServiceBase.h index d318ff1e..dbb1754c 100644 --- a/tmtcservices/PusServiceBase.h +++ b/tmtcservices/PusServiceBase.h @@ -30,7 +30,10 @@ void setStaticFrameworkObjectIds(); * All PUS Services are System Objects, so an Object ID needs to be specified on construction. * \ingroup pus_services */ -class PusServiceBase : public ExecutableObjectIF, public AcceptsTelecommandsIF, public SystemObject, public HasReturnvaluesIF { +class PusServiceBase : public ExecutableObjectIF, + public AcceptsTelecommandsIF, + public SystemObject, + public HasReturnvaluesIF { friend void (Factory::setStaticFrameworkObjectIds)(); public: /** @@ -63,7 +66,7 @@ public: * @return The returned status_code is directly taken as main error code in the Verification Report. * On success, RETURN_OK shall be returned. */ - virtual ReturnValue_t handleRequest() = 0; + virtual ReturnValue_t handleRequest(uint8_t subservice) = 0; /** * In performService, implementations can handle periodic, non-TC-triggered activities. * The performService method is always called. From ed7b4e2a3a88142ff6ff1aed74e3f0cb009c85ea Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 10 Jun 2020 20:49:30 +0200 Subject: [PATCH 121/653] PSB improvements --- objectmanager/ObjectManager.cpp | 1 + tmtcservices/PusServiceBase.cpp | 74 +++++++++++++++++++-------------- tmtcservices/PusServiceBase.h | 8 ++-- 3 files changed, 49 insertions(+), 34 deletions(-) diff --git a/objectmanager/ObjectManager.cpp b/objectmanager/ObjectManager.cpp index cfdf6562..1c54355a 100644 --- a/objectmanager/ObjectManager.cpp +++ b/objectmanager/ObjectManager.cpp @@ -1,5 +1,6 @@ #include #include +#include #include ObjectManager::ObjectManager( void (*setProducer)() ): diff --git a/tmtcservices/PusServiceBase.cpp b/tmtcservices/PusServiceBase.cpp index c27defe6..f5d1e30b 100644 --- a/tmtcservices/PusServiceBase.cpp +++ b/tmtcservices/PusServiceBase.cpp @@ -9,10 +9,11 @@ object_id_t PusServiceBase::packetSource = 0; object_id_t PusServiceBase::packetDestination = 0; -PusServiceBase::PusServiceBase(object_id_t setObjectId, uint16_t setApid, uint8_t setServiceId) : - SystemObject(setObjectId), apid(setApid), serviceId(setServiceId), errorParameter1( - 0), errorParameter2(0), requestQueue(NULL) { - requestQueue = QueueFactory::instance()->createMessageQueue(PUS_SERVICE_MAX_RECEPTION); +PusServiceBase::PusServiceBase(object_id_t setObjectId, uint16_t setApid, + uint8_t setServiceId) : + SystemObject(setObjectId), apid(setApid), serviceId(setServiceId) { + requestQueue = QueueFactory::instance()-> + createMessageQueue(PUS_SERVICE_MAX_RECEPTION); } PusServiceBase::~PusServiceBase() { @@ -20,51 +21,60 @@ PusServiceBase::~PusServiceBase() { } ReturnValue_t PusServiceBase::performOperation(uint8_t opCode) { + handleRequestQueue(); + ReturnValue_t result = this->performService(); + if (result != RETURN_OK) { + sif::error << "PusService " << (uint16_t) this->serviceId + << ": performService returned with " << (int16_t) result + << std::endl; + return RETURN_FAILED; + } + return RETURN_OK; +} + +void PusServiceBase::handleRequestQueue() { TmTcMessage message; + ReturnValue_t result = RETURN_FAILED; for (uint8_t count = 0; count < PUS_SERVICE_MAX_RECEPTION; count++) { ReturnValue_t status = this->requestQueue->receiveMessage(&message); - // debug << "PusServiceBase::performOperation: Receiving from MQ ID: " << std::hex << this->requestQueue.getId() - // << std::dec << " returned: " << status << std::endl; + // debug << "PusServiceBase::performOperation: Receiving from MQ ID: " + // << std::hex << this->requestQueue.getId() + // << std::dec << " returned: " << status << std::endl; if (status == RETURN_OK) { this->currentPacket.setStoreAddress(message.getStorageId()); - // info << "Service " << (uint16_t) this->serviceId << ": new packet!" << std::endl; + //info << "Service " << (uint16_t) this->serviceId << + // ": new packet!" << std::endl; - ReturnValue_t return_code = this->handleRequest(currentPacket.getSubService()); + result = this->handleRequest(currentPacket.getSubService()); - // debug << "Service " << (uint16_t)this->serviceId << ": handleRequest returned: " << (int)return_code << std::endl; - if (return_code == RETURN_OK) { + // debug << "Service " << (uint16_t)this->serviceId << + // ": handleRequest returned: " << (int)return_code << std::endl; + if (result == RETURN_OK) { this->verifyReporter.sendSuccessReport( TC_VERIFY::COMPLETION_SUCCESS, &this->currentPacket); - } else { + } + else { this->verifyReporter.sendFailureReport( TC_VERIFY::COMPLETION_FAILURE, &this->currentPacket, - return_code, 0, errorParameter1, errorParameter2); + result, 0, errorParameter1, errorParameter2); } this->currentPacket.deletePacket(); errorParameter1 = 0; errorParameter2 = 0; - } else if (status == MessageQueueIF::EMPTY) { + } + else if (status == MessageQueueIF::EMPTY) { status = RETURN_OK; - // debug << "PusService " << (uint16_t)this->serviceId << ": no new packet." << std::endl; + // debug << "PusService " << (uint16_t)this->serviceId << + // ": no new packet." << std::endl; break; - } else { - + } + else { sif::error << "PusServiceBase::performOperation: Service " << (uint16_t) this->serviceId << ": Error receiving packet. Code: " << std::hex << status << std::dec << std::endl; } } - ReturnValue_t return_code = this->performService(); - if (return_code == RETURN_OK) { - return RETURN_OK; - } else { - - sif::error << "PusService " << (uint16_t) this->serviceId - << ": performService returned with " << (int16_t) return_code - << std::endl; - return RETURN_FAILED; - } } uint16_t PusServiceBase::getIdentifier() { @@ -80,19 +90,21 @@ ReturnValue_t PusServiceBase::initialize() { if (result != RETURN_OK) { return result; } - AcceptsTelemetryIF* dest_service = objectManager->get( + AcceptsTelemetryIF* destService = objectManager->get( packetDestination); PUSDistributorIF* distributor = objectManager->get( packetSource); - if ((dest_service != NULL) && (distributor != NULL)) { + if ((destService != nullptr) && (distributor != nullptr)) { this->requestQueue->setDefaultDestination( - dest_service->getReportReceptionQueue()); + destService->getReportReceptionQueue()); distributor->registerService(this); return RETURN_OK; - } else { + } + else { sif::error << "PusServiceBase::PusServiceBase: Service " << (uint32_t) this->serviceId << ": Configuration error." - << " Make sure packetSource and packetDestination are defined correctly" << std::endl; + << " Make sure packetSource and packetDestination are defined " + "correctly" << std::endl; return RETURN_FAILED; } } diff --git a/tmtcservices/PusServiceBase.h b/tmtcservices/PusServiceBase.h index dbb1754c..5f741410 100644 --- a/tmtcservices/PusServiceBase.h +++ b/tmtcservices/PusServiceBase.h @@ -97,16 +97,16 @@ protected: /** * One of two error parameters for additional error information. */ - uint32_t errorParameter1; + uint32_t errorParameter1 = 0; /** * One of two error parameters for additional error information. */ - uint32_t errorParameter2; + uint32_t errorParameter2 = 0; /** * This is a complete instance of the Telecommand reception queue of the class. * It is initialized on construction of the class. */ - MessageQueueIF* requestQueue; + MessageQueueIF* requestQueue = nullptr; /** * An instance of the VerificationReporter class, that simplifies sending any kind of * Verification Message to the TC Verification Service. @@ -127,6 +127,8 @@ private: * Remember that one packet must be completely handled in one #handleRequest call. */ static const uint8_t PUS_SERVICE_MAX_RECEPTION = 10; + + void handleRequestQueue(); }; #endif /* PUSSERVICEBASE_H_ */ From 39d5fe34bb3ee1ddda0d8724ec4beb3459eed783 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 10 Jun 2020 21:36:21 +0200 Subject: [PATCH 122/653] better include guard, doc form improvement --- tmtcservices/PusServiceBase.h | 80 +++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 32 deletions(-) diff --git a/tmtcservices/PusServiceBase.h b/tmtcservices/PusServiceBase.h index 5f741410..39600c41 100644 --- a/tmtcservices/PusServiceBase.h +++ b/tmtcservices/PusServiceBase.h @@ -1,5 +1,5 @@ -#ifndef PUSSERVICEBASE_H_ -#define PUSSERVICEBASE_H_ +#ifndef FRAMEWORK_TMTCSERVICES_PUSSERVICEBASE_H_ +#define FRAMEWORK_TMTCSERVICES_PUSSERVICEBASE_H_ #include #include @@ -9,7 +9,6 @@ #include #include #include -#include #include namespace Factory{ @@ -17,18 +16,22 @@ void setStaticFrameworkObjectIds(); } /** - * \defgroup pus_services PUS Service Framework + * @defgroup pus_services PUS Service Framework * These group contains all implementations of PUS Services in the OBSW. * Most of the Services are directly taken from the ECSS PUS Standard. */ /** - * \brief This class is the basis for all PUS Services, which can immediately process Telecommand Packets. - * It manages Telecommand reception and the generation of Verification Reports. Every class that inherits - * from this abstract class has to implement handleRequest and performService. Services that are created with this + * @brief This class is the basis for all PUS Services, + * which can immediately process Telecommand Packets. + * @details + * It manages Telecommand reception and the generation of Verification Reports. + * Every class that inherits from this abstract class has to implement + * handleRequest and performService. Services that are created with this * Base class have to handle any kind of request immediately on reception. - * All PUS Services are System Objects, so an Object ID needs to be specified on construction. - * \ingroup pus_services + * All PUS Services are System Objects, so an Object ID needs to be specified + * on construction. + * @ingroup pus_services */ class PusServiceBase : public ExecutableObjectIF, public AcceptsTelecommandsIF, @@ -37,49 +40,61 @@ class PusServiceBase : public ExecutableObjectIF, friend void (Factory::setStaticFrameworkObjectIds)(); public: /** - * The constructor for the class. - * The passed values are set, but inter-object initialization is done in the initialize method. - * @param setObjectId The system object identifier of this Service instance. - * @param set_apid The APID the Service is instantiated for. - * @param set_service_id The Service Identifier as specified in ECSS PUS. + * @brief The passed values are set, but inter-object initialization is + * done in the initialize method. + * @param setObjectId + * The system object identifier of this Service instance. + * @param setApid + * The APID the Service is instantiated for. + * @param setServiceId + * The Service Identifier as specified in ECSS PUS. */ - PusServiceBase( object_id_t setObjectId, uint16_t setApid, uint8_t setServiceId); + PusServiceBase( object_id_t setObjectId, uint16_t setApid, + uint8_t setServiceId); /** * The destructor is empty. */ virtual ~PusServiceBase(); /** - * @brief The handleRequest method shall handle any kind of Telecommand Request immediately. + * @brief The handleRequest method shall handle any kind of Telecommand + * Request immediately. * @details - * Implemetations can take the Telecommand in currentPacket and perform any kind of operation. - * They may send additional "Start Success (1,3)" messages with the verifyReporter, but Completion - * Success or Failure Reports are generated automatically after execution of this method. + * Implemetations can take the Telecommand in currentPacket and perform + * any kind of operation. + * They may send additional "Start Success (1,3)" messages with the + * verifyReporter, but Completion Success or Failure Reports are generated + * automatically after execution of this method. * * If a Telecommand can not be executed within one call cycle, * this Base class is not the right parent. * - * The child class may add additional error information by setting #errorParameters which are - * attached to the generated verification message. + * The child class may add additional error information by setting + * #errorParameters which aren attached to the generated verification + * message. * * Subservice checking should be implemented in this method. * - * @return The returned status_code is directly taken as main error code in the Verification Report. + * @return The returned status_code is directly taken as main error code + * in the Verification Report. * On success, RETURN_OK shall be returned. */ virtual ReturnValue_t handleRequest(uint8_t subservice) = 0; /** - * In performService, implementations can handle periodic, non-TC-triggered activities. + * In performService, implementations can handle periodic, + * non-TC-triggered activities. * The performService method is always called. - * @return A success or failure code that does not trigger any kind of verification message. + * @return Currently, everything other that RETURN_OK only triggers + * diagnostic output. */ virtual ReturnValue_t performService() = 0; /** * This method implements the typical activity of a simple PUS Service. - * It checks for new requests, and, if found, calls handleRequest, sends completion verification messages and deletes + * 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(); @@ -103,13 +118,13 @@ protected: */ uint32_t errorParameter2 = 0; /** - * This is a complete instance of the Telecommand reception queue of the class. - * It is initialized on construction of the class. + * This is a complete instance of the telecommand reception queue + * of the class. It is initialized on construction of the class. */ MessageQueueIF* requestQueue = nullptr; /** - * An instance of the VerificationReporter class, that simplifies sending any kind of - * Verification Message to the TC Verification Service. + * An instance of the VerificationReporter class, that simplifies + * sending any kind of verification message to the TC Verification Service. */ VerificationReporter verifyReporter; /** @@ -124,7 +139,8 @@ protected: private: /** * This constant sets the maximum number of packets accepted per call. - * Remember that one packet must be completely handled in one #handleRequest call. + * Remember that one packet must be completely handled in one + * #handleRequest call. */ static const uint8_t PUS_SERVICE_MAX_RECEPTION = 10; From 5dc2133c3a4218f5027955fc77c3a505f0e948f4 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 10 Jun 2020 21:41:48 +0200 Subject: [PATCH 123/653] CSB improvements --- tmtcservices/CommandingServiceBase.cpp | 56 +++++++++++++------------- tmtcservices/CommandingServiceBase.h | 48 +++++++++++----------- 2 files changed, 54 insertions(+), 50 deletions(-) diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index d70b9042..adc9400f 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -218,9 +218,9 @@ void CommandingServiceBase::handleRequestQueue() { } -void CommandingServiceBase::sendTmPacket(uint8_t subservice, - const uint8_t* data, uint32_t dataLen, const uint8_t* headerData, - uint32_t headerSize) { +ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice, + const uint8_t* data, size_t dataLen, const uint8_t* headerData, + size_t headerSize) { TmPacketStored tmPacketStored(this->apid, this->service, subservice, this->tmPacketCounter, data, dataLen, headerData, headerSize); ReturnValue_t result = tmPacketStored.sendPacket( @@ -228,36 +228,38 @@ void CommandingServiceBase::sendTmPacket(uint8_t subservice, if (result == HasReturnvaluesIF::RETURN_OK) { this->tmPacketCounter++; } + return result; } -void CommandingServiceBase::sendTmPacket(uint8_t subservice, - object_id_t objectId, const uint8_t *data, uint32_t dataLen) { - uint8_t buffer[sizeof(object_id_t)]; - uint8_t* pBuffer = buffer; - uint32_t size = 0; - SerializeAdapter::serialize(&objectId, &pBuffer, &size, - sizeof(object_id_t), true); - TmPacketStored tmPacketStored(this->apid, this->service, subservice, - this->tmPacketCounter, data, dataLen, buffer, size); - ReturnValue_t result = tmPacketStored.sendPacket( - requestQueue->getDefaultDestination(), requestQueue->getId()); - if (result == HasReturnvaluesIF::RETURN_OK) { - this->tmPacketCounter++; - } - +ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice, + object_id_t objectId, const uint8_t *data, size_t dataLen) { + uint8_t buffer[sizeof(object_id_t)]; + uint8_t* pBuffer = buffer; + size_t size = 0; + SerializeAdapter::serialize(&objectId, &pBuffer, &size, + sizeof(object_id_t), true); + TmPacketStored tmPacketStored(this->apid, this->service, subservice, + this->tmPacketCounter, data, dataLen, buffer, size); + ReturnValue_t result = tmPacketStored.sendPacket( + requestQueue->getDefaultDestination(), requestQueue->getId()); + if (result == HasReturnvaluesIF::RETURN_OK) { + this->tmPacketCounter++; + } + return result; } -void CommandingServiceBase::sendTmPacket(uint8_t subservice, - SerializeIF* content, SerializeIF* header) { - TmPacketStored tmPacketStored(this->apid, this->service, subservice, - this->tmPacketCounter, content, header); - ReturnValue_t result = tmPacketStored.sendPacket( - requestQueue->getDefaultDestination(), requestQueue->getId()); - if (result == HasReturnvaluesIF::RETURN_OK) { - this->tmPacketCounter++; - } +ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice, + SerializeIF* content, SerializeIF* header) { + TmPacketStored tmPacketStored(this->apid, this->service, subservice, + this->tmPacketCounter, content, header); + ReturnValue_t result = tmPacketStored.sendPacket( + requestQueue->getDefaultDestination(), requestQueue->getId()); + if (result == HasReturnvaluesIF::RETURN_OK) { + this->tmPacketCounter++; + } + return result; } diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index bf2e8242..e79e806d 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -125,7 +125,7 @@ protected: * - @c CSB or implementation specific return codes */ virtual ReturnValue_t getMessageQueueAndObject(uint8_t subservice, - const uint8_t *tcData, uint32_t tcDataLen, MessageQueueId_t *id, + const uint8_t *tcData, size_t tcDataLen, MessageQueueId_t *id, object_id_t *objectId) = 0; /** @@ -133,18 +133,16 @@ protected: * the command is prepared by using an implementation specific CommandMessage type * which is sent to the target object. * It contains all necessary information for the device to execute telecommands. - * @param message[out] message to be sent to the object - * @param subservice[in] Subservice of the current communication - * @param tcData Additional data of the command - * @param tcDataLen Length of the additional data - * @param state[out] Setable state of the communication + * @param message + * @param subservice + * @param tcData + * @param tcDataLen + * @param state * @param objectId Target object ID - * @return - @c RETURN_OK on success - * - @c EXECUTION_COMPLETE if exectuin is finished - * - any other return code will be part of (1,4) start failure + * @return */ virtual ReturnValue_t prepareCommand(CommandMessage *message, - uint8_t subservice, const uint8_t *tcData, uint32_t tcDataLen, + uint8_t subservice, const uint8_t *tcData, size_t tcDataLen, uint32_t *state, object_id_t objectId) = 0; /** @@ -152,10 +150,10 @@ 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 contains information about the command - * @param previousCommand Command_t of last command - * @param state state of the communication - * @param optionalNextCommand[out] An optional next command which can be set in this function + * @param reply[out] Command Message which contains information about the command + * @param previousCommand [out] + * @param state + * @param optionalNextCommand * @param objectId Source object ID * @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 @@ -215,34 +213,38 @@ protected: PeriodicTaskIF* executingTask; /** - * Send TM data from pointer to data. If a header is supplied it is added before data + * @brief Send TM data from pointer to data. + * If a header is supplied it is added before data * @param subservice Number of subservice * @param data Pointer to the data in the Packet * @param dataLen Lenght of data in the Packet * @param headerData HeaderData will be placed before data * @param headerSize Size of HeaderData */ - void sendTmPacket(uint8_t subservice, const uint8_t *data, uint32_t dataLen, - const uint8_t* headerData = NULL, uint32_t headerSize = 0); + ReturnValue_t sendTmPacket(uint8_t subservice, const uint8_t *data, + size_t dataLen, const uint8_t* headerData = nullptr, + size_t headerSize = 0); /** - * To send TM packets of objects that still need to be serialized and consist of an object ID with appended data + * @brief To send TM packets of objects that still need to be serialized + * and consist of an object ID with appended data. * @param subservice Number of subservice * @param objectId ObjectId is placed before data * @param data Data to append to the packet * @param dataLen Length of Data */ - void sendTmPacket(uint8_t subservice, object_id_t objectId, - const uint8_t *data, uint32_t dataLen); + ReturnValue_t sendTmPacket(uint8_t subservice, object_id_t objectId, + const uint8_t *data, size_t dataLen); /** - * To send packets has data which is in form of a SerializeIF or Adapters implementing it + * @brief To send packets which are contained inside a class implementing + * SerializeIF. * @param subservice Number of subservice * @param content This is a pointer to the serialized packet * @param header Serialize IF header which will be placed before content */ - void sendTmPacket(uint8_t subservice, SerializeIF* content, - SerializeIF* header = NULL); + ReturnValue_t sendTmPacket(uint8_t subservice, SerializeIF* content, + SerializeIF* header = nullptr); virtual void handleUnrequestedReply(CommandMessage *reply); From 482aedfaf23cca466dcd9bb060b6238ac63f185c Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 10 Jun 2020 22:13:49 +0200 Subject: [PATCH 124/653] cleaned up includes, improved doc --- tmtcservices/CommandingServiceBase.cpp | 27 +++--- tmtcservices/CommandingServiceBase.h | 114 ++++++++++++++----------- 2 files changed, 76 insertions(+), 65 deletions(-) diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index adc9400f..361baf3b 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -1,22 +1,21 @@ -/* - * CommandingServiceBase.cpp - * - * Created on: 28.08.2019 - * Author: gaisser - */ +#include +#include +#include #include +#include +#include +#include +#include CommandingServiceBase::CommandingServiceBase(object_id_t setObjectId, uint16_t apid, uint8_t service, uint8_t numberOfParallelCommands, - uint16_t commandTimeout_seconds, object_id_t setPacketSource, + uint16_t commandTimeoutSeconds, object_id_t setPacketSource, object_id_t setPacketDestination, size_t queueDepth) : - SystemObject(setObjectId), apid(apid), service(service), timeout_seconds( - commandTimeout_seconds), tmPacketCounter(0), IPCStore(NULL), TCStore( - NULL), commandQueue(NULL), requestQueue(NULL), commandMap( - numberOfParallelCommands), failureParameter1(0), failureParameter2( - 0), packetSource(setPacketSource), packetDestination( - setPacketDestination),executingTask(NULL) { + SystemObject(setObjectId), apid(apid), service(service), + timeoutSeconds(commandTimeoutSeconds), + commandMap(numberOfParallelCommands), packetSource(setPacketSource), + packetDestination(setPacketDestination) { commandQueue = QueueFactory::instance()->createMessageQueue(queueDepth); requestQueue = QueueFactory::instance()->createMessageQueue(queueDepth); } @@ -369,7 +368,7 @@ void CommandingServiceBase::checkTimeout() { typename FixedMap::Iterator iter; for (iter = commandMap.begin(); iter != commandMap.end(); ++iter) { - if ((iter->uptimeOfStart + (timeout_seconds * 1000)) < uptime) { + if ((iter->uptimeOfStart + (timeoutSeconds * 1000)) < uptime) { verificationReporter.sendFailureReport( TC_VERIFY::COMPLETION_FAILURE, iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, iter->tcInfo.tcSequenceControl, diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index e79e806d..37f6891c 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -1,35 +1,33 @@ -#ifndef COMMANDINGSERVICEBASE_H_ -#define COMMANDINGSERVICEBASE_H_ +#ifndef FRAMEWORK_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ +#define FRAMEWORK_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ -#include -#include -#include -#include #include -#include #include #include -#include -#include -#include +#include #include -#include -#include + #include -#include -#include -#include +#include +#include +#include +#include + +class TcPacketStored; /** - * \brief This class is the basis for all PUS Services, which have to relay Telecommands to software bus. + * @brief This class is the basis for all PUS Services, which have to + * relay Telecommands to software bus. * - * It manages Telecommand reception and the generation of Verification Reports like PUSServiceBase. - * Every class that inherits from this abstract class has to implement four adaption points: + * It manages Telecommand reception and the generation of Verification Reports + * similar to PusServiceBase. This class is used if a telecommand can't be + * handled immediately and must be relayed to the internal software bus. * - isValidSubservice * - getMessageQueueAndObject * - prepareCommand * - handleReply - * \ingroup pus_services + * @author gaisser + * @ingroup pus_services */ class CommandingServiceBase: public SystemObject, public AcceptsTelecommandsIF, @@ -59,7 +57,7 @@ public: */ CommandingServiceBase(object_id_t setObjectId, uint16_t apid, uint8_t service, uint8_t numberOfParallelCommands, - uint16_t commandTimeout_seconds, object_id_t setPacketSource, + uint16_t commandTimeoutSeconds, object_id_t setPacketSource, object_id_t setPacketDestination, size_t queueDepth = 20); virtual ~CommandingServiceBase(); @@ -113,8 +111,9 @@ protected: 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. + * 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 @@ -129,10 +128,10 @@ protected: 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 object. - * It contains all necessary information for the device to execute telecommands. + * 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 object. It contains all necessary information + * for the device to execute telecommands. * @param message * @param subservice * @param tcData @@ -146,25 +145,40 @@ protected: 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[out] Command Message which contains information about the command - * @param previousCommand [out] - * @param state - * @param optionalNextCommand + * This function is implemented by child services to specify how replies + * to a command from another software component are handled + * @param reply + * This is the reply in form of a command message. + * @param previousCommand + * Command_t of related command + * @param state [out/in] + * Additional parameter which can be used to pass state information. + * State of the communication + * @param optionalNextCommand [out] + * An optional next command which can be set in this function * @param objectId Source object ID * @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 + * @return + * - @c RETURN_OK, @c EXECUTION_COMPLETE or @c NO_STEP_MESSAGE to + * generate TC verification success + * - @c INVALID_REPLY calls handleUnrequestedReply + * - 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; + /** + * This function can be overidden to handle unrequested reply, + * when the reply sender ID is unknown or is not found is the command map. + * @param reply + */ + virtual void handleUnrequestedReply(CommandMessage *reply); + + virtual void doPeriodicOperation(); + + struct CommandInfo { struct tcInfo { uint8_t ackFlags; @@ -184,33 +198,35 @@ protected: const uint8_t service; - const uint16_t timeout_seconds; + const uint16_t timeoutSeconds; - uint8_t tmPacketCounter; + uint8_t tmPacketCounter = 0; - StorageManagerIF *IPCStore; + StorageManagerIF *IPCStore = nullptr; - StorageManagerIF *TCStore; + StorageManagerIF *TCStore = nullptr; - MessageQueueIF* commandQueue; + MessageQueueIF* commandQueue = nullptr; - MessageQueueIF* requestQueue; + MessageQueueIF* requestQueue = nullptr; VerificationReporter verificationReporter; FixedMap commandMap; - uint32_t failureParameter1; //!< May be set be children to return a more precise failure condition. - uint32_t failureParameter2; //!< May be set be children to return a more precise failure condition. + /* May be set be children to return a more precise failure condition. */ + uint32_t failureParameter1 = 0; + uint32_t failureParameter2 = 0; object_id_t packetSource; object_id_t packetDestination; /** - * Pointer to the task which executes this component, is invalid before setTaskIF was called. + * Pointer to the task which executes this component, + * is invalid before setTaskIF was called. */ - PeriodicTaskIF* executingTask; + PeriodicTaskIF* executingTask = nullptr; /** * @brief Send TM data from pointer to data. @@ -246,10 +262,6 @@ protected: ReturnValue_t sendTmPacket(uint8_t subservice, SerializeIF* content, SerializeIF* header = nullptr); - virtual void handleUnrequestedReply(CommandMessage *reply); - - virtual void doPeriodicOperation(); - void checkAndExecuteFifo( typename FixedMap::Iterator *iter); From 534fddd2c6443f52bfedbe3532cd4263470ee18c Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 10 Jun 2020 22:19:08 +0200 Subject: [PATCH 125/653] added back comment removed for unknown reasons --- tmtcservices/CommandingServiceBase.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index 37f6891c..f97eabb0 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -132,11 +132,12 @@ protected: * prepared by using an implementation specific CommandMessage type * which is sent to the target object. It contains all necessary information * for the device to execute telecommands. - * @param message - * @param subservice - * @param tcData - * @param tcDataLen - * @param state + * @param message [out] message which can be set and is sent to the object + * @param subservice Subservice of the current communication + * @param tcData Application data of command + * @param tcDataLen Application data length + * @param state [out/in] Setable state of the communication. + * communication * @param objectId Target object ID * @return */ From 72f3b16c2474eadbf1569edd60b06b0296ae6bf6 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 10 Jun 2020 22:53:24 +0200 Subject: [PATCH 126/653] split up huge member function for readability --- tmtcservices/CommandingServiceBase.cpp | 193 ++++++++++++++----------- tmtcservices/CommandingServiceBase.h | 7 + 2 files changed, 113 insertions(+), 87 deletions(-) diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index 361baf3b..4c557f82 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -56,7 +56,7 @@ ReturnValue_t CommandingServiceBase::initialize() { objectManager->get(packetDestination); PUSDistributorIF* distributor = objectManager->get( packetSource); - if ((packetForwarding == NULL) && (distributor == NULL)) { + if (packetForwarding == nullptr or distributor == nullptr) { return RETURN_FAILED; } @@ -67,7 +67,7 @@ ReturnValue_t CommandingServiceBase::initialize() { IPCStore = objectManager->get(objects::IPC_STORE); TCStore = objectManager->get(objects::TC_STORE); - if ((IPCStore == NULL) || (TCStore == NULL)) { + if (IPCStore == nullptr or TCStore == nullptr) { return RETURN_FAILED; } @@ -76,97 +76,116 @@ ReturnValue_t CommandingServiceBase::initialize() { } void CommandingServiceBase::handleCommandQueue() { - CommandMessage reply, nextCommand; - ReturnValue_t result, sendResult = RETURN_OK; - bool isStep = false; + CommandMessage reply; + ReturnValue_t result = RETURN_FAILED; for (result = commandQueue->receiveMessage(&reply); result == RETURN_OK; result = commandQueue->receiveMessage(&reply)) { - isStep = false; - typename FixedMap::Iterator iter; - if (reply.getSender() == MessageQueueIF::NO_QUEUE) { - handleUnrequestedReply(&reply); - continue; - } - if ((iter = commandMap.find(reply.getSender())) == commandMap.end()) { - handleUnrequestedReply(&reply); - continue; - } - nextCommand.setCommand(CommandMessage::CMD_NONE); - result = handleReply(&reply, iter->command, &iter->state, &nextCommand, - iter->objectId, &isStep); - switch (result) { - case EXECUTION_COMPLETE: - case RETURN_OK: - case NO_STEP_MESSAGE: - iter->command = nextCommand.getCommand(); - if (nextCommand.getCommand() != CommandMessage::CMD_NONE) { - sendResult = commandQueue->sendMessage(reply.getSender(), - &nextCommand); - } - if (sendResult == RETURN_OK) { - if (isStep) { - if (result != NO_STEP_MESSAGE) { - verificationReporter.sendSuccessReport( - TC_VERIFY::PROGRESS_SUCCESS, - iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, - iter->tcInfo.tcSequenceControl, ++iter->step); - } - } else { - verificationReporter.sendSuccessReport( - TC_VERIFY::COMPLETION_SUCCESS, - iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, - iter->tcInfo.tcSequenceControl, 0); - checkAndExecuteFifo(&iter); - } - } else { - if (isStep) { - nextCommand.clearCommandMessage(); - verificationReporter.sendFailureReport( - TC_VERIFY::PROGRESS_FAILURE, iter->tcInfo.ackFlags, - iter->tcInfo.tcPacketId, - iter->tcInfo.tcSequenceControl, sendResult, - ++iter->step, failureParameter1, failureParameter2); - } else { - nextCommand.clearCommandMessage(); - verificationReporter.sendFailureReport( - TC_VERIFY::COMPLETION_FAILURE, - iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, - iter->tcInfo.tcSequenceControl, sendResult, 0, - failureParameter1, failureParameter2); - } - failureParameter1 = 0; - failureParameter2 = 0; - checkAndExecuteFifo(&iter); - } - break; - case INVALID_REPLY: - //might be just an unrequested reply at a bad moment - handleUnrequestedReply(&reply); - break; - default: - if (isStep) { - verificationReporter.sendFailureReport( - TC_VERIFY::PROGRESS_FAILURE, iter->tcInfo.ackFlags, - iter->tcInfo.tcPacketId, iter->tcInfo.tcSequenceControl, - result, ++iter->step, failureParameter1, - failureParameter2); - } else { - verificationReporter.sendFailureReport( - TC_VERIFY::COMPLETION_FAILURE, iter->tcInfo.ackFlags, - iter->tcInfo.tcPacketId, iter->tcInfo.tcSequenceControl, - result, 0, failureParameter1, failureParameter2); - } - failureParameter1 = 0; - failureParameter2 = 0; - checkAndExecuteFifo(&iter); - break; - } - + handleCommandMessage(reply); } } +void CommandingServiceBase::handleCommandMessage(CommandMessage& reply) { + bool isStep = false; + CommandMessage nextCommand; + CommandMapIter iter; + if (reply.getSender() == MessageQueueIF::NO_QUEUE) { + handleUnrequestedReply(&reply); + return; + } + if ((iter = commandMap.find(reply.getSender())) == commandMap.end()) { + handleUnrequestedReply(&reply); + return; + } + nextCommand.setCommand(CommandMessage::CMD_NONE); + + // Implemented by child class, specifies what to do with reply. + ReturnValue_t result = handleReply(&reply, iter->command, &iter->state, + &nextCommand, iter->objectId, &isStep); + + switch (result) { + case EXECUTION_COMPLETE: + case RETURN_OK: + case NO_STEP_MESSAGE: + // handle result of reply handler implemented by developer. + handleReplyHandlerResult(result, iter, nextCommand, reply, isStep); + break; + case INVALID_REPLY: + //might be just an unrequested reply at a bad moment + handleUnrequestedReply(&reply); + break; + default: + if (isStep) { + verificationReporter.sendFailureReport( + TC_VERIFY::PROGRESS_FAILURE, iter->tcInfo.ackFlags, + iter->tcInfo.tcPacketId, iter->tcInfo.tcSequenceControl, + result, ++iter->step, failureParameter1, + failureParameter2); + } else { + verificationReporter.sendFailureReport( + TC_VERIFY::COMPLETION_FAILURE, iter->tcInfo.ackFlags, + iter->tcInfo.tcPacketId, iter->tcInfo.tcSequenceControl, + result, 0, failureParameter1, failureParameter2); + } + failureParameter1 = 0; + failureParameter2 = 0; + checkAndExecuteFifo(&iter); + break; + } + +} + +void CommandingServiceBase::handleReplyHandlerResult(ReturnValue_t result, + CommandMapIter iter, CommandMessage& nextCommand, CommandMessage& reply, + bool& isStep) { + iter->command = nextCommand.getCommand(); + + // In case a new command is to be sent immediately, this is performed here. + // If no new command is sent, only analyse reply result by initializing + // sendResult as RETURN_OK + ReturnValue_t sendResult = RETURN_OK; + if (nextCommand.getCommand() != CommandMessage::CMD_NONE) { + sendResult = commandQueue->sendMessage(reply.getSender(), + &nextCommand); + } + + if (sendResult == RETURN_OK) { + if (isStep and result != NO_STEP_MESSAGE) { + verificationReporter.sendSuccessReport( + TC_VERIFY::PROGRESS_SUCCESS, + iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, + iter->tcInfo.tcSequenceControl, ++iter->step); + } + else { + verificationReporter.sendSuccessReport( + TC_VERIFY::COMPLETION_SUCCESS, + iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, + iter->tcInfo.tcSequenceControl, 0); + checkAndExecuteFifo(&iter); + } + } + else { + if (isStep) { + nextCommand.clearCommandMessage(); + verificationReporter.sendFailureReport( + TC_VERIFY::PROGRESS_FAILURE, iter->tcInfo.ackFlags, + iter->tcInfo.tcPacketId, + iter->tcInfo.tcSequenceControl, sendResult, + ++iter->step, failureParameter1, failureParameter2); + } else { + nextCommand.clearCommandMessage(); + verificationReporter.sendFailureReport( + TC_VERIFY::COMPLETION_FAILURE, + iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, + iter->tcInfo.tcSequenceControl, sendResult, 0, + failureParameter1, failureParameter2); + } + failureParameter1 = 0; + failureParameter2 = 0; + checkAndExecuteFifo(&iter); + } +} + void CommandingServiceBase::handleRequestQueue() { TmTcMessage message; ReturnValue_t result; diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index f97eabb0..9a68a2d3 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -267,6 +267,9 @@ protected: typename FixedMap::Iterator *iter); private: + using CommandMapIter = FixedMap::Iterator; + /** * This method handles internal execution of a command, * once it has been started by @sa{startExecution()} in the Request Queue handler. @@ -298,6 +301,10 @@ private: void startExecution(TcPacketStored *storedPacket, typename FixedMap::Iterator *iter); + void handleCommandMessage(CommandMessage& reply); + void handleReplyHandlerResult(ReturnValue_t result, CommandMapIter iter, + CommandMessage& nextCommand,CommandMessage& reply, bool& isStep); + void checkTimeout(); }; From eb4880f60348969b2b70147c97e545577a32c7df Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 17 Jun 2020 20:53:10 +0200 Subject: [PATCH 127/653] singly linked list improvements --- container/SinglyLinkedList.h | 69 +++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/container/SinglyLinkedList.h b/container/SinglyLinkedList.h index 0a2e0531..3c0078fc 100644 --- a/container/SinglyLinkedList.h +++ b/container/SinglyLinkedList.h @@ -1,10 +1,13 @@ -#ifndef SINGLYLINKEDLIST_H_ -#define SINGLYLINKEDLIST_H_ +#ifndef FRAMEWORK_CONTAINER_SINGLYLINKEDLIST_H_ +#define FRAMEWORK_CONTAINER_SINGLYLINKEDLIST_H_ + +#include +#include -#include -#include /** - * \ingroup container + * @brief Linked list data structure, + * each entry has a pointer to the next entry (singly) + * @ingroup container */ template class LinkedElement { @@ -12,11 +15,8 @@ public: T *value; class Iterator { public: - LinkedElement *value; - Iterator() : - value(NULL) { - - } + LinkedElement *value = nullptr; + Iterator() {} Iterator(LinkedElement *element) : value(element) { @@ -45,12 +45,11 @@ public: } }; - LinkedElement(T* setElement, LinkedElement* setNext = NULL) : value(setElement), - next(setNext) { - } - virtual ~LinkedElement(){ + LinkedElement(T* setElement, LinkedElement* setNext = nullptr): + value(setElement), next(setNext) {} + + virtual ~LinkedElement(){} - } virtual LinkedElement* getNext() const { return next; } @@ -58,11 +57,16 @@ public: virtual void setNext(LinkedElement* next) { this->next = next; } + + virtual void setEnd() { + this->next = nullptr; + } + LinkedElement* begin() { return this; } LinkedElement* end() { - return NULL; + return nullptr; } private: LinkedElement *next; @@ -71,21 +75,21 @@ private: template class SinglyLinkedList { public: - SinglyLinkedList() : - start(NULL) { - } + using ElementIterator = typename LinkedElement::Iterator; + + SinglyLinkedList() {} + + SinglyLinkedList(ElementIterator start) : + start(start.value) {} - SinglyLinkedList(typename LinkedElement::Iterator start) : - start(start.value) { - } SinglyLinkedList(LinkedElement* startElement) : - start(startElement) { - } - typename LinkedElement::Iterator begin() const { - return LinkedElement::Iterator::Iterator(start); + start(startElement) {} + + ElementIterator begin() const { + return ElementIterator::Iterator(start); } - typename LinkedElement::Iterator::Iterator end() const { - return LinkedElement::Iterator::Iterator(); + typename ElementIterator::Iterator end() const { + return ElementIterator::Iterator(); } uint32_t getSize() const { @@ -100,8 +104,15 @@ public: void setStart(LinkedElement* setStart) { start = setStart; } + + void setEnd(LinkedElement* setEnd) { + setEnd->setEnd(); + } + + // SHOULDDO: Insertion operation ? + protected: - LinkedElement *start; + LinkedElement *start = nullptr; }; #endif /* SINGLYLINKEDLIST_H_ */ From 0c4552254089de1b5626a4bca31114acb39a0290 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 17 Jun 2020 20:57:35 +0200 Subject: [PATCH 128/653] hybrid iterator fix and improvement --- container/HybridIterator.h | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/container/HybridIterator.h b/container/HybridIterator.h index b34fdfd0..db1ce4bc 100644 --- a/container/HybridIterator.h +++ b/container/HybridIterator.h @@ -8,13 +8,11 @@ template class HybridIterator: public LinkedElement::Iterator, public ArrayList::Iterator { public: - HybridIterator() : - value(NULL), linked(NULL), end(NULL) { - } + HybridIterator() {} HybridIterator(typename LinkedElement::Iterator *iter) : - LinkedElement::Iterator(*iter), value( - iter->value), linked(true), end(NULL) { + LinkedElement::Iterator(*iter), value(iter->value), + linked(true) { } @@ -66,11 +64,11 @@ public: return tmp; } - bool operator==(HybridIterator other) { - return value == other->value; + bool operator==(const HybridIterator& other) { + return value == other.value; } - bool operator!=(HybridIterator other) { + bool operator!=(const HybridIterator& other) { return !(*this == other); } @@ -82,11 +80,11 @@ public: return value; } - T* value; + T* value = nullptr; private: - bool linked; - T *end; + bool linked = false; + T *end = nullptr; }; #endif /* HYBRIDITERATOR_H_ */ From 952fc7303a0a55f1a9fb8a39d5b05cf2fb5886eb Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 17 Jun 2020 21:15:19 +0200 Subject: [PATCH 129/653] renamed MESSAGE_TYPE to messagetypes --- action/ActionMessage.h | 2 +- devicehandlers/DeviceHandlerMessage.h | 2 +- health/HealthMessage.h | 2 +- ipc/CommandMessage.cpp | 22 +++++++++++----------- ipc/CommandMessage.h | 2 +- ipc/FwMessageTypes.h | 2 +- memory/MemoryMessage.h | 2 +- modes/ModeMessage.h | 2 +- monitoring/MonitoringMessage.h | 2 +- parameters/ParameterMessage.h | 2 +- subsystem/modes/ModeSequenceMessage.h | 2 +- tmstorage/TmStoreMessage.h | 2 +- 12 files changed, 22 insertions(+), 22 deletions(-) diff --git a/action/ActionMessage.h b/action/ActionMessage.h index 5d8332cb..59ad619e 100644 --- a/action/ActionMessage.h +++ b/action/ActionMessage.h @@ -10,7 +10,7 @@ class ActionMessage { private: ActionMessage(); public: - static const uint8_t MESSAGE_ID = MESSAGE_TYPE::ACTION; + static const uint8_t MESSAGE_ID = messagetypes::ACTION; static const Command_t EXECUTE_ACTION = MAKE_COMMAND_ID(1); static const Command_t STEP_SUCCESS = MAKE_COMMAND_ID(2); static const Command_t STEP_FAILED = MAKE_COMMAND_ID(3); diff --git a/devicehandlers/DeviceHandlerMessage.h b/devicehandlers/DeviceHandlerMessage.h index fad0f1b1..26f3b4ed 100644 --- a/devicehandlers/DeviceHandlerMessage.h +++ b/devicehandlers/DeviceHandlerMessage.h @@ -25,7 +25,7 @@ public: /** * These are the commands that can be sent to a DeviceHandlerBase */ - static const uint8_t MESSAGE_ID = MESSAGE_TYPE::DEVICE_HANDLER_COMMAND; + static const uint8_t MESSAGE_ID = messagetypes::DEVICE_HANDLER_COMMAND; static const Command_t CMD_RAW = MAKE_COMMAND_ID( 1 ); //!< Sends a raw command, setParameter is a ::store_id_t containing the raw packet to send // static const Command_t CMD_DIRECT = MAKE_COMMAND_ID( 2 ); //!< Sends a direct command, setParameter is a ::DeviceCommandId_t, setParameter2 is a ::store_id_t containing the data needed for the command static const Command_t CMD_SWITCH_IOBOARD = MAKE_COMMAND_ID( 3 ); //!< Requests a IO-Board switch, setParameter() is the IO-Board identifier diff --git a/health/HealthMessage.h b/health/HealthMessage.h index 7fd00904..13e79b88 100644 --- a/health/HealthMessage.h +++ b/health/HealthMessage.h @@ -6,7 +6,7 @@ class HealthMessage { public: - static const uint8_t MESSAGE_ID = MESSAGE_TYPE::HEALTH_COMMAND; + static const uint8_t MESSAGE_ID = messagetypes::HEALTH_COMMAND; static const Command_t HEALTH_SET = MAKE_COMMAND_ID(1);//REPLY_COMMAND_OK/REPLY_REJECTED static const Command_t HEALTH_ANNOUNCE = MAKE_COMMAND_ID(3); //NO REPLY! static const Command_t HEALTH_INFO = MAKE_COMMAND_ID(5); diff --git a/ipc/CommandMessage.cpp b/ipc/CommandMessage.cpp index fa41c653..69a0bfd3 100644 --- a/ipc/CommandMessage.cpp +++ b/ipc/CommandMessage.cpp @@ -15,7 +15,7 @@ #include #include -namespace MESSAGE_TYPE { +namespace messagetypes { void clearMissionMessage(CommandMessage* message); } @@ -67,35 +67,35 @@ void CommandMessage::setParameter2(uint32_t parameter2) { void CommandMessage::clearCommandMessage() { switch((getCommand()>>8) & 0xff){ - case MESSAGE_TYPE::MODE_COMMAND: + case messagetypes::MODE_COMMAND: ModeMessage::clear(this); break; - case MESSAGE_TYPE::HEALTH_COMMAND: + case messagetypes::HEALTH_COMMAND: HealthMessage::clear(this); break; - case MESSAGE_TYPE::MODE_SEQUENCE: + case messagetypes::MODE_SEQUENCE: ModeSequenceMessage::clear(this); break; - case MESSAGE_TYPE::ACTION: + case messagetypes::ACTION: ActionMessage::clear(this); break; - case MESSAGE_TYPE::DEVICE_HANDLER_COMMAND: + case messagetypes::DEVICE_HANDLER_COMMAND: DeviceHandlerMessage::clear(this); break; - case MESSAGE_TYPE::MEMORY: + case messagetypes::MEMORY: MemoryMessage::clear(this); break; - case MESSAGE_TYPE::MONITORING: + case messagetypes::MONITORING: MonitoringMessage::clear(this); break; - case MESSAGE_TYPE::TM_STORE: + case messagetypes::TM_STORE: TmStoreMessage::clear(this); break; - case MESSAGE_TYPE::PARAMETER: + case messagetypes::PARAMETER: ParameterMessage::clear(this); break; default: - MESSAGE_TYPE::clearMissionMessage(this); + messagetypes::clearMissionMessage(this); break; } } diff --git a/ipc/CommandMessage.h b/ipc/CommandMessage.h index 2d966063..3d563607 100644 --- a/ipc/CommandMessage.h +++ b/ipc/CommandMessage.h @@ -23,7 +23,7 @@ public: static const ReturnValue_t UNKNOW_COMMAND = MAKE_RETURN_CODE(0x01); - static const uint8_t MESSAGE_ID = MESSAGE_TYPE::COMMAND; + static const uint8_t MESSAGE_ID = messagetypes::COMMAND; static const Command_t CMD_NONE = MAKE_COMMAND_ID( 0 );//!< Used internally, will be ignored static const Command_t REPLY_COMMAND_OK = MAKE_COMMAND_ID( 3 ); static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID( 0xD1 );//!< Reply indicating that the current command was rejected, par1 should contain the error code diff --git a/ipc/FwMessageTypes.h b/ipc/FwMessageTypes.h index ec1c9aa2..e820b1df 100644 --- a/ipc/FwMessageTypes.h +++ b/ipc/FwMessageTypes.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_IPC_FWMESSAGETYPES_H_ #define FRAMEWORK_IPC_FWMESSAGETYPES_H_ -namespace MESSAGE_TYPE { +namespace messagetypes { //Remember to add new Message Types to the clearCommandMessage function! enum FW_MESSAGE_TYPE { COMMAND = 0, diff --git a/memory/MemoryMessage.h b/memory/MemoryMessage.h index 124fad08..48badb05 100644 --- a/memory/MemoryMessage.h +++ b/memory/MemoryMessage.h @@ -9,7 +9,7 @@ class MemoryMessage { private: MemoryMessage(); //A private ctor inhibits instantiation public: - static const uint8_t MESSAGE_ID = MESSAGE_TYPE::MEMORY; + static const uint8_t MESSAGE_ID = messagetypes::MEMORY; static const Command_t CMD_MEMORY_LOAD = MAKE_COMMAND_ID( 0x01 ); static const Command_t CMD_MEMORY_DUMP = MAKE_COMMAND_ID( 0x02 ); static const Command_t CMD_MEMORY_CHECK = MAKE_COMMAND_ID( 0x03 ); diff --git a/modes/ModeMessage.h b/modes/ModeMessage.h index f72fdeec..675c614b 100644 --- a/modes/ModeMessage.h +++ b/modes/ModeMessage.h @@ -17,7 +17,7 @@ class ModeMessage { private: ModeMessage(); public: - static const uint8_t MESSAGE_ID = MESSAGE_TYPE::MODE_COMMAND; + static const uint8_t MESSAGE_ID = messagetypes::MODE_COMMAND; static const Command_t CMD_MODE_COMMAND = MAKE_COMMAND_ID(0x01);//!> Command to set the specified Mode, replies are: REPLY_MODE_REPLY, REPLY_WRONG_MODE_REPLY, and REPLY_REJECTED; don't add any replies, as this will break the subsystem mode machine!! static const Command_t CMD_MODE_COMMAND_FORCED = MAKE_COMMAND_ID(0xF1);//!> Command to set the specified Mode, regardless of external control flag, replies are: REPLY_MODE_REPLY, REPLY_WRONG_MODE_REPLY, and REPLY_REJECTED; don't add any replies, as this will break the subsystem mode machine!! static const Command_t REPLY_MODE_REPLY = MAKE_COMMAND_ID(0x02);//!> Reply to a CMD_MODE_COMMAND or CMD_MODE_READ diff --git a/monitoring/MonitoringMessage.h b/monitoring/MonitoringMessage.h index d2ff9b4d..793e1fbf 100644 --- a/monitoring/MonitoringMessage.h +++ b/monitoring/MonitoringMessage.h @@ -6,7 +6,7 @@ class MonitoringMessage: public CommandMessage { public: - static const uint8_t MESSAGE_ID = MESSAGE_TYPE::MONITORING; + static const uint8_t MESSAGE_ID = messagetypes::MONITORING; //Object id could be useful, but we better manage that on service level (register potential reporters). static const Command_t LIMIT_VIOLATION_REPORT = MAKE_COMMAND_ID(10); virtual ~MonitoringMessage(); diff --git a/parameters/ParameterMessage.h b/parameters/ParameterMessage.h index 0f286675..43283294 100644 --- a/parameters/ParameterMessage.h +++ b/parameters/ParameterMessage.h @@ -9,7 +9,7 @@ class ParameterMessage { private: ParameterMessage(); public: - static const uint8_t MESSAGE_ID = MESSAGE_TYPE::PARAMETER; + static const uint8_t MESSAGE_ID = messagetypes::PARAMETER; static const Command_t CMD_PARAMETER_LOAD = MAKE_COMMAND_ID( 0x01 ); static const Command_t CMD_PARAMETER_DUMP = MAKE_COMMAND_ID( 0x02 ); static const Command_t REPLY_PARAMETER_DUMP = MAKE_COMMAND_ID( 0x03 ); diff --git a/subsystem/modes/ModeSequenceMessage.h b/subsystem/modes/ModeSequenceMessage.h index 830cf532..61d1b628 100644 --- a/subsystem/modes/ModeSequenceMessage.h +++ b/subsystem/modes/ModeSequenceMessage.h @@ -7,7 +7,7 @@ class ModeSequenceMessage { public: - static const uint8_t MESSAGE_ID = MESSAGE_TYPE::MODE_SEQUENCE; + static const uint8_t MESSAGE_ID = messagetypes::MODE_SEQUENCE; static const Command_t ADD_SEQUENCE = MAKE_COMMAND_ID(0x01); static const Command_t ADD_TABLE = MAKE_COMMAND_ID(0x02); diff --git a/tmstorage/TmStoreMessage.h b/tmstorage/TmStoreMessage.h index 0883063c..bd6b2def 100644 --- a/tmstorage/TmStoreMessage.h +++ b/tmstorage/TmStoreMessage.h @@ -41,7 +41,7 @@ public: static store_address_t getStoreId(const CommandMessage* cmd); virtual ~TmStoreMessage(); - static const uint8_t MESSAGE_ID = MESSAGE_TYPE::TM_STORE; + static const uint8_t MESSAGE_ID = messagetypes::TM_STORE; static const Command_t ENABLE_STORING = MAKE_COMMAND_ID(1); static const Command_t DELETE_STORE_CONTENT = MAKE_COMMAND_ID(2); static const Command_t DOWNLINK_STORE_CONTENT = MAKE_COMMAND_ID(3); From cda3130b34b6885455c76bb46d94f1b48d9056ab Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 19 Jun 2020 01:05:51 +0200 Subject: [PATCH 130/653] periodic reply map param is bool now --- devicehandlers/DeviceHandlerBase.cpp | 10 +++++----- devicehandlers/DeviceHandlerBase.h | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 7620a116..fe6152cf 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -184,7 +184,7 @@ void DeviceHandlerBase::decrementDeviceReplyMap() { if (iter->second.delayCycles != 0) { iter->second.delayCycles--; if (iter->second.delayCycles == 0) { - if (iter->second.periodic != 0) { + if (iter->second.periodic) { iter->second.delayCycles = iter->second.maxDelayCycles; } replyToReply(iter, TIMEOUT); @@ -344,7 +344,7 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode, } ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, - uint16_t maxDelayCycles, size_t replyLen, uint8_t periodic, + uint16_t maxDelayCycles, size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) { //No need to check, as we may try to insert multiple times. insertInCommandMap(deviceCommand); @@ -356,7 +356,7 @@ ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(DeviceCommandId_t de } ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId, - uint16_t maxDelayCycles, size_t replyLen, uint8_t periodic) { + uint16_t maxDelayCycles, size_t replyLen, bool periodic) { DeviceReplyInfo info; info.maxDelayCycles = maxDelayCycles; info.periodic = periodic; @@ -385,7 +385,7 @@ ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceComm } ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply, - uint16_t delayCycles, uint16_t maxDelayCycles, uint8_t periodic) { + uint16_t delayCycles, uint16_t maxDelayCycles, bool periodic) { std::map::iterator iter = deviceReplyMap.find(deviceReply); if (iter == deviceReplyMap.end()) { @@ -741,7 +741,7 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, if (info->delayCycles != 0) { - if (info->periodic != 0) { + if (info->periodic) { info->delayCycles = info->maxDelayCycles; } else { info->delayCycles = 0; diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index b959c9de..435f8e06 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -381,7 +381,7 @@ protected: * - @c RETURN_FAILED else. */ ReturnValue_t insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, - uint16_t maxDelayCycles, size_t replyLen = 0, uint8_t periodic = 0, + uint16_t maxDelayCycles, size_t replyLen = 0, bool periodic = false, bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0); /** @@ -395,7 +395,7 @@ protected: * - @c RETURN_FAILED else. */ ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, - uint16_t maxDelayCycles, size_t replyLen = 0, uint8_t periodic = 0); + uint16_t maxDelayCycles, size_t replyLen = 0, bool periodic = false); /** * @brief A simple command to add a command to the commandList. @@ -421,7 +421,7 @@ protected: */ ReturnValue_t updateReplyMapEntry(DeviceCommandId_t deviceReply, uint16_t delayCycles, uint16_t maxDelayCycles, - uint8_t periodic = 0); + bool periodic = false); /** * @brief Can be implemented by child handler to @@ -625,7 +625,7 @@ protected: uint16_t maxDelayCycles; //!< The maximum number of cycles the handler should wait for a reply to this command. uint16_t delayCycles; //!< The currently remaining cycles the handler should wait for a reply, 0 means there is no reply expected size_t replyLen = 0; //!< Expected size of the reply. - uint8_t periodic; //!< if this is !=0, the delayCycles will not be reset to 0 but to maxDelayCycles + bool 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. }; From d8e9e34ad9fc33b365f98ef3497fdc84fa698c8a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 19 Jun 2020 14:36:49 +0200 Subject: [PATCH 131/653] framework submakefile improvements --- framework.mk | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/framework.mk b/framework.mk index a5a65364..c8822981 100644 --- a/framework.mk +++ b/framework.mk @@ -1,5 +1,5 @@ -# This file needs FRAMEWORK_PATH and API set correctly -# Valid API settings: rtems, linux, freeRTOS +# This file needs FRAMEWORK_PATH and OS_FSFW set correctly by another Makefile. +# Valid API settings: rtems, linux, freeRTOS, host CXXSRC += $(wildcard $(FRAMEWORK_PATH)/action/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/container/*.cpp) @@ -8,11 +8,13 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/controller/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/coordinates/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datalinklayer/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapool/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoolglob/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoollocal/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/housekeeping/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/devicehandlers/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/eventmatching/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/fdir/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/framework.mk/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/globalfunctions/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/globalfunctions/matching/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/globalfunctions/math/*.cpp) @@ -26,14 +28,16 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/objectmanager/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/*.cpp) # select the OS -ifeq ($(OS),rtems) +ifeq ($(OS_FSFW),rtems) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/rtems/*.cpp) -else ifeq ($(OS),linux) +else ifeq ($(OS_FSFW),linux) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/linux/*.cpp) -else ifeq ($(OS),freeRTOS) +else ifeq ($(OS_FSFW),freeRTOS) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/FreeRTOS/*.cpp) +else ifeq ($(OS_FSFW),host) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/host/*.cpp) else -$(error invalid OS specified, valid OS are rtems, linux, freeRTOS) +$(error invalid OS specified, valid OS are rtems, linux, freeRTOS, host) endif CXXSRC += $(wildcard $(FRAMEWORK_PATH)/parameters/*.cpp) @@ -54,3 +58,4 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/packetmatcher/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/pus/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcservices/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/test/*.cpp) \ No newline at end of file From 31e557776373eb5334430ae6f1e68616aba4a617 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 19 Jun 2020 14:45:29 +0200 Subject: [PATCH 132/653] added deadline missed check --- osal/FreeRTOS/PeriodicTask.cpp | 55 ++++++++++++------- osal/FreeRTOS/PeriodicTask.h | 96 +++++++++++++++++++--------------- 2 files changed, 90 insertions(+), 61 deletions(-) diff --git a/osal/FreeRTOS/PeriodicTask.cpp b/osal/FreeRTOS/PeriodicTask.cpp index deab2dc1..31867639 100644 --- a/osal/FreeRTOS/PeriodicTask.cpp +++ b/osal/FreeRTOS/PeriodicTask.cpp @@ -1,17 +1,19 @@ +#include "PeriodicTask.h" + #include #include -#include "PeriodicTask.h" PeriodicTask::PeriodicTask(const char *name, TaskPriority setPriority, TaskStackSize setStack, TaskPeriod setPeriod, void (*setDeadlineMissedFunc)()) : started(false), handle(NULL), period(setPeriod), deadlineMissedFunc( - setDeadlineMissedFunc) { - - BaseType_t status = xTaskCreate(taskEntryPoint, name, setStack, this, setPriority, &handle); + setDeadlineMissedFunc) +{ + BaseType_t status = xTaskCreate(taskEntryPoint, name, + setStack, this, setPriority, &handle); if(status != pdPASS){ - sif::debug << "PeriodicTask Insufficient heap memory remaining. Status: " - << status << std::endl; + sif::debug << "PeriodicTask Insufficient heap memory remaining. " + "Status: " << status << std::endl; } } @@ -21,16 +23,19 @@ PeriodicTask::~PeriodicTask(void) { } void PeriodicTask::taskEntryPoint(void* argument) { - //The argument is re-interpreted as PeriodicTask. The Task object is global, so it is found from any place. + // The argument is re-interpreted as PeriodicTask. The Task object is + // global, so it is found from any place. PeriodicTask *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. - // to be able to accommodate both cases we check a member which is set in #startTask() - // if it is not set and we get here, the scheduler was started before #startTask() was called and we need to suspend - // if it is set, the scheduler was not running before #startTask() was called and we can continue + /* Task should not start until explicitly requested, + * but in FreeRTOS, tasks start as soon as they are created if the scheduler + * is running but not if the scheduler is not running. + * To be able to accommodate both cases we check a member which is set in + * #startTask(). If it is not set and we get here, the scheduler was started + * before #startTask() was called and we need to suspend if it is set, + * the scheduler was not running before #startTask() was called and we + * can continue */ - if (!originalTask->started) { + if (not originalTask->started) { vTaskSuspend(NULL); } @@ -59,9 +64,9 @@ void PeriodicTask::taskFunctionality() { TickType_t xLastWakeTime; const TickType_t xPeriod = pdMS_TO_TICKS(this->period * 1000.); /* The xLastWakeTime variable needs to be initialized with the current tick - count. Note that this is the only time the variable is written to explicitly. - After this assignment, xLastWakeTime is updated automatically internally within - vTaskDelayUntil(). */ + count. Note that this is the only time the variable is written to + explicitly. After this assignment, xLastWakeTime is updated automatically + internally within vTaskDelayUntil(). */ xLastWakeTime = xTaskGetTickCount(); /* Enter the loop that defines the task behavior. */ for (;;) { @@ -69,8 +74,22 @@ void PeriodicTask::taskFunctionality() { it != objectList.end(); ++it) { (*it)->performOperation(); } - //TODO deadline missed check + + /* If all operations are finished and the difference of the + * current time minus the last wake time is larger than the + * wait period, a deadline was missed. */ + if(xTaskGetTickCount() - xLastWakeTime >= xPeriod) { +#ifdef DEBUG + sif::warning << "PeriodicTask: " << pcTaskGetName(NULL) << + " missed deadline!\n" << std::flush; +#endif + if(deadlineMissedFunc != nullptr) { + this->deadlineMissedFunc(); + } + } + vTaskDelayUntil(&xLastWakeTime, xPeriod); + } } diff --git a/osal/FreeRTOS/PeriodicTask.h b/osal/FreeRTOS/PeriodicTask.h index e7ba8dd2..b9930a73 100644 --- a/osal/FreeRTOS/PeriodicTask.h +++ b/osal/FreeRTOS/PeriodicTask.h @@ -1,48 +1,49 @@ -#ifndef MULTIOBJECTTASK_H_ -#define MULTIOBJECTTASK_H_ +#ifndef FRAMEWORK_OSAL_FREERTOS_PERIODICTASK_H_ +#define FRAMEWORK_OSAL_FREERTOS_PERIODICTASK_H_ #include #include #include -#include -#include "task.h" +#include +#include #include class ExecutableObjectIF; /** - * @brief This class represents a specialized task for periodic activities of multiple objects. - * - * @details MultiObjectTask is an extension to ObjectTask in the way that it is able to execute - * multiple objects that implement the ExecutableObjectIF interface. The objects must be - * added prior to starting the task. - * + * @brief This class represents a specialized task for + * periodic activities of multiple objects. * @ingroup task_handling */ class PeriodicTask: public PeriodicTaskIF { public: /** - * @brief Standard constructor of the class. - * @details The class is initialized without allocated objects. These need to be added - * with #addObject. - * In the underlying TaskBase class, a new operating system task is created. - * In addition to the TaskBase parameters, the period, the pointer to the - * aforementioned initialization function and an optional "deadline-missed" - * function pointer is passed. - * @param priority Sets the priority of a task. Values range from a low 0 to a high 99. - * @param stack_size The stack size reserved by the operating system for the task. - * @param setPeriod The length of the period with which the task's functionality will be - * executed. It is expressed in clock ticks. - * @param setDeadlineMissedFunc The function pointer to the deadline missed function - * that shall be assigned. + * Keep in Mind that you need to call before this vTaskStartScheduler()! + * A lot of task parameters are set in "FreeRTOSConfig.h". + * TODO: why does this need to be called before vTaskStartScheduler? + * @details + * The class is initialized without allocated objects. + * These need to be added with #addComponent. + * @param priority + * Sets the priority of a task. Values depend on freeRTOS configuration, + * high number means high priority. + * @param stack_size + * The stack size reserved by the operating system for the task. + * @param setPeriod + * The length of the period with which the task's + * functionality will be executed. It is expressed in clock ticks. + * @param setDeadlineMissedFunc + * The function pointer to the deadline missed function that shall + * be assigned. */ - PeriodicTask(const char *name, TaskPriority setPriority, TaskStackSize setStack, TaskPeriod setPeriod, - void (*setDeadlineMissedFunc)()); + PeriodicTask(const char *name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod setPeriod, + void (*setDeadlineMissedFunc)()); /** - * @brief Currently, the executed object's lifetime is not coupled with the task object's - * lifetime, so the destructor is empty. + * @brief Currently, the executed object's lifetime is not coupled with + * the task object's lifetime, so the destructor is empty. */ virtual ~PeriodicTask(void); @@ -58,7 +59,9 @@ public: * Adds an object to the list of objects to be executed. * The objects are executed in the order added. * @param object Id of the object to add. - * @return RETURN_OK on success, RETURN_FAILED if the object could not be added. + * @return + * -@c RETURN_OK on success + * -@c RETURN_FAILED if the object could not be added. */ ReturnValue_t addComponent(object_id_t object); @@ -69,42 +72,49 @@ protected: bool started; TaskHandle_t handle; - typedef std::vector ObjectList; //!< Typedef for the List of objects. + //! Typedef for the List of objects. + typedef std::vector ObjectList; /** * @brief This attribute holds a list of objects to be executed. */ ObjectList objectList; /** * @brief The period of the task. - * @details The period determines the frequency of the task's execution. It is expressed in clock ticks. + * @details + * The period determines the frequency of the task's execution. + * It is expressed in clock ticks. */ TaskPeriod period; /** * @brief The pointer to the deadline-missed function. - * @details This pointer stores the function that is executed if the task's deadline is missed. - * So, each may react individually on a timing failure. The pointer may be NULL, - * then nothing happens on missing the deadline. The deadline is equal to the next execution - * of the periodic task. + * @details + * This pointer stores the function that is executed if the task's deadline + * is missed so each may react individually on a timing failure. + * The pointer may be NULL, then nothing happens on missing the deadline. + * The deadline is equal to the next execution of the periodic task. */ void (*deadlineMissedFunc)(void); /** * @brief This is the function executed in the new task's context. - * @details It converts the argument back to the thread object type and copies the class instance - * to the task context. The taskFunctionality method is called afterwards. + * @details + * It converts the argument back to the thread object type and copies the + * class instance to the task context. The taskFunctionality method is + * called afterwards. * @param A pointer to the task object itself is passed as argument. */ static void taskEntryPoint(void* argument); /** * @brief The function containing the actual functionality of the task. - * @details The method sets and starts - * the task's period, then enters a loop that is repeated as long as the isRunning - * attribute is true. Within the loop, all performOperation methods of the added - * objects are called. Afterwards the checkAndRestartPeriod system call blocks the task - * until the next period. - * On missing the deadline, the deadlineMissedFunction is executed. + * @details + * The method sets and starts the task's period, then enters a loop that is + * repeated as long as the isRunning attribute is true. Within the loop, + * all performOperation methods of the added objects are called. + * Afterwards the checkAndRestartPeriod system call blocks the task until + * the next period. + * On missing the deadline, the deadlineMissedFunction is executed. */ void taskFunctionality(void); }; -#endif /* MULTIOBJECTTASK_H_ */ +#endif /* PERIODICTASK_H_ */ From 56aaa299854f4a7e0cf02499cdb2cb11db0899b9 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 19 Jun 2020 14:47:01 +0200 Subject: [PATCH 133/653] added deadline missed check --- osal/FreeRTOS/FixedTimeslotTask.cpp | 64 ++++++++++++++++---------- osal/FreeRTOS/FixedTimeslotTask.h | 69 ++++++++++++++++------------- 2 files changed, 77 insertions(+), 56 deletions(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index fb3c3b03..ea324d35 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -1,6 +1,7 @@ -#include #include "FixedTimeslotTask.h" +#include + uint32_t FixedTimeslotTask::deadlineMissedCount = 0; const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE; @@ -18,16 +19,19 @@ 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. + // The argument is re-interpreted as FixedTimeslotTask. The Task object is + // global, so it is found from any place. 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. - // to be able to accommodate both cases we check a member which is set in #startTask() - // if it is not set and we get here, the scheduler was started before #startTask() was called and we need to suspend - // if it is set, the scheduler was not running before #startTask() was called and we can continue + /* Task should not start until explicitly requested, + * but in FreeRTOS, tasks start as soon as they are created if the scheduler + * is running but not if the scheduler is not running. + * To be able to accommodate both cases we check a member which is set in + * #startTask(). If it is not set and we get here, the scheduler was started + * before #startTask() was called and we need to suspend if it is set, + * the scheduler was not running before #startTask() was called and we + * can continue */ - if (!originalTask->started) { + if (not originalTask->started) { vTaskSuspend(NULL); } @@ -81,11 +85,12 @@ ReturnValue_t FixedTimeslotTask::checkSequence() const { } void FixedTimeslotTask::taskFunctionality() { - // A local iterator for the Polling Sequence Table is created to find the start time for the first entry. - std::list::iterator it = pst.current; + // A local iterator for the Polling Sequence Table is created to find the + // start time for the first entry. + SlotListIter slotListIter = pst.current; //The start time for the first entry is read. - uint32_t intervalMs = (*it)->pollingTimeMs; + uint32_t intervalMs = slotListIter->pollingTimeMs; TickType_t interval = pdMS_TO_TICKS(intervalMs); TickType_t xLastWakeTime; @@ -101,18 +106,30 @@ void FixedTimeslotTask::taskFunctionality() { /* Enter the loop that defines the task behavior. */ for (;;) { //The component for this slot is executed and the next one is chosen. - this->pst.executeAndAdvance(); - if (pst.slotFollowsImmediately()) { - //Do nothing - } else { - // we need to wait before executing the current slot - //this gives us the time to wait: - intervalMs = this->pst.getIntervalToPreviousSlotMs(); - interval = pdMS_TO_TICKS(intervalMs); - vTaskDelayUntil(&xLastWakeTime, interval); - //TODO deadline missed check - } + this->pst.executeAndAdvance(); + if (not pst.slotFollowsImmediately()) { + /* If all operations are finished and the difference of the + * current time minus the last wake time is larger than the + * expected wait period, a deadline was missed. */ + if(xTaskGetTickCount() - xLastWakeTime >= + pdMS_TO_TICKS(this->pst.getIntervalToPreviousSlotMs())) { +#ifdef DEBUG + sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) << + " missed deadline!\n" << std::flush; +#endif + if(deadlineMissedFunc != nullptr) { + this->deadlineMissedFunc(); + } + // Continue immediately, no need to wait. + break; + } + // we need to wait before executing the current slot + //this gives us the time to wait: + intervalMs = this->pst.getIntervalToPreviousSlotMs(); + interval = pdMS_TO_TICKS(intervalMs); + vTaskDelayUntil(&xLastWakeTime, interval); + } } } @@ -120,4 +137,3 @@ ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { vTaskDelay(pdMS_TO_TICKS(ms)); return HasReturnvaluesIF::RETURN_OK; } - diff --git a/osal/FreeRTOS/FixedTimeslotTask.h b/osal/FreeRTOS/FixedTimeslotTask.h index bed13051..39db667c 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.h +++ b/osal/FreeRTOS/FixedTimeslotTask.h @@ -1,24 +1,27 @@ -#ifndef POLLINGTASK_H_ -#define POLLINGTASK_H_ +#ifndef FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ +#define FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ #include #include #include -#include -#include "task.h" +#include +#include class FixedTimeslotTask: public FixedTimeslotTaskIF { public: + /** - * @brief The standard constructor of the class. - * - * @details This is the general constructor of the class. In addition to the TaskBase parameters, - * the following variables are passed: - * - * @param (*setDeadlineMissedFunc)() The function pointer to the deadline missed function that shall be assigned. - * - * @param getPst The object id of the completely initialized polling sequence. + * Keep in Mind that you need to call before this vTaskStartScheduler()! + * A lot of task parameters are set in "FreeRTOSConfig.h". + * @param name Name of the task, lenght limited by configMAX_TASK_NAME_LEN + * @param setPriority Number of priorities specified by + * configMAX_PRIORITIES. High taskPriority_ number means high priority. + * @param setStack Stack size in words (not bytes!). + * Lower limit specified by configMINIMAL_STACK_SIZE + * @param overallPeriod Period in seconds. + * @param setDeadlineMissedFunc Callback if a deadline was missed. + * @return Pointer to the newly created task. */ FixedTimeslotTask(const char *name, TaskPriority setPriority, TaskStackSize setStack, TaskPeriod overallPeriod, @@ -26,16 +29,18 @@ public: /** * @brief The destructor of the class. - * - * @details The destructor frees all heap memory that was allocated on thread initialization for the PST and - * the device handlers. This is done by calling the PST's destructor. + * @details + * The destructor frees all heap memory that was allocated on thread + * initialization for the PST and the device handlers. This is done by + * calling the PST's destructor. */ virtual ~FixedTimeslotTask(void); ReturnValue_t startTask(void); /** * This static function can be used as #deadlineMissedFunc. - * It counts missedDeadlines and prints the number of missed deadlines every 10th time. + * It counts missedDeadlines and prints the number of missed deadlines + * every 10th time. */ static void missedDeadlineCounter(); /** @@ -51,6 +56,7 @@ public: ReturnValue_t checkSequence() const; ReturnValue_t sleepFor(uint32_t ms); + protected: bool started; TaskHandle_t handle; @@ -58,30 +64,29 @@ protected: FixedSlotSequence pst; /** - * @brief This attribute holds a function pointer that is executed when a deadline was missed. - * - * @details Another function may be announced to determine the actions to perform when a deadline was missed. - * Currently, only one function for missing any deadline is allowed. - * If not used, it shall be declared NULL. + * @brief This attribute holds a function pointer that is executed when + * a deadline was missed. + * @details + * Another function may be announced to determine the actions to perform + * when a deadline was missed. Currently, only one function for missing + * any deadline is allowed. If not used, it shall be declared NULL. */ void (*deadlineMissedFunc)(void); /** - * @brief This is the entry point in a new polling thread. - * - * @details This method, that is the generalOSAL::checkAndRestartPeriod( this->periodId, interval ); entry point in the new thread, is here set to generate - * and link the Polling Sequence Table to the thread object and start taskFunctionality() - * on success. If operation of the task is ended for some reason, - * the destructor is called to free allocated memory. + * @brief This is the entry point for a new task. + * @details + * This method starts the task by calling taskFunctionality(), as soon as + * all requirements (task scheduler has started and startTask() + * has been called) are met. */ static void taskEntryPoint(void* argument); /** * @brief This function holds the main functionality of the thread. - * - * - * @details Holding the main functionality of the task, this method is most important. - * It links the functionalities provided by FixedSlotSequence with the OS's System Calls - * to keep the timing of the periods. + * @details + * Core function holding the main functionality of the task + * It links the functionalities provided by FixedSlotSequence with the + * OS's System Calls to keep the timing of the periods. */ void taskFunctionality(void); }; From ffe2a7bffefbb744d1149e4c4d53807649c0570e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 22 Jun 2020 19:00:02 +0200 Subject: [PATCH 134/653] fix for fixed timeslot task improvement --- osal/FreeRTOS/FixedTimeslotTask.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index ea324d35..a4acc420 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -87,10 +87,10 @@ ReturnValue_t FixedTimeslotTask::checkSequence() const { void FixedTimeslotTask::taskFunctionality() { // A local iterator for the Polling Sequence Table is created to find the // start time for the first entry. - SlotListIter slotListIter = pst.current; + std::list::iterator slotListIter = pst.current; //The start time for the first entry is read. - uint32_t intervalMs = slotListIter->pollingTimeMs; + uint32_t intervalMs = (*slotListIter)->pollingTimeMs; TickType_t interval = pdMS_TO_TICKS(intervalMs); TickType_t xLastWakeTime; @@ -121,7 +121,7 @@ void FixedTimeslotTask::taskFunctionality() { this->deadlineMissedFunc(); } // Continue immediately, no need to wait. - break; + continue; } // we need to wait before executing the current slot From 2cada2df4a611daf5d8c9e6bfa1e8026dc98e09b Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 22 Jun 2020 20:21:11 +0200 Subject: [PATCH 135/653] some fixes and improvements --- osal/FreeRTOS/FixedTimeslotTask.cpp | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index a4acc420..edb7f835 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -62,11 +62,6 @@ ReturnValue_t FixedTimeslotTask::startTask() { ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep) { if (objectManager->get(componentId) != nullptr) { - if(slotTimeMs == 0) { - // FreeRTOS throws a sanity error for zero values, so we set - // the time to one millisecond. - slotTimeMs = 1; - } pst.addSlot(componentId, slotTimeMs, executionStep, this); return HasReturnvaluesIF::RETURN_OK; } @@ -87,7 +82,7 @@ ReturnValue_t FixedTimeslotTask::checkSequence() const { void FixedTimeslotTask::taskFunctionality() { // A local iterator for the Polling Sequence Table is created to find the // start time for the first entry. - std::list::iterator slotListIter = pst.current; + auto slotListIter = pst.current; //The start time for the first entry is read. uint32_t intervalMs = (*slotListIter)->pollingTimeMs; @@ -101,18 +96,23 @@ void FixedTimeslotTask::taskFunctionality() { xLastWakeTime = xTaskGetTickCount(); // wait for first entry's start time - vTaskDelayUntil(&xLastWakeTime, interval); + if(interval > 0) { + vTaskDelayUntil(&xLastWakeTime, interval); + } /* Enter the loop that defines the task behavior. */ for (;;) { //The component for this slot is executed and the next one is chosen. this->pst.executeAndAdvance(); if (not pst.slotFollowsImmediately()) { + // Get the interval till execution of the next slot. + intervalMs = this->pst.getIntervalToPreviousSlotMs(); + interval = pdMS_TO_TICKS(intervalMs); + /* If all operations are finished and the difference of the * current time minus the last wake time is larger than the * expected wait period, a deadline was missed. */ - if(xTaskGetTickCount() - xLastWakeTime >= - pdMS_TO_TICKS(this->pst.getIntervalToPreviousSlotMs())) { + if(xTaskGetTickCount() - xLastWakeTime >= interval) { #ifdef DEBUG sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) << " missed deadline!\n" << std::flush; @@ -120,14 +120,9 @@ void FixedTimeslotTask::taskFunctionality() { if(deadlineMissedFunc != nullptr) { this->deadlineMissedFunc(); } - // Continue immediately, no need to wait. - continue; } - - // we need to wait before executing the current slot - //this gives us the time to wait: - intervalMs = this->pst.getIntervalToPreviousSlotMs(); - interval = pdMS_TO_TICKS(intervalMs); + // Wait for the interval. This exits immediately if a deadline was + // missed while also updating the last wake time. vTaskDelayUntil(&xLastWakeTime, interval); } } @@ -137,3 +132,4 @@ ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { vTaskDelay(pdMS_TO_TICKS(ms)); return HasReturnvaluesIF::RETURN_OK; } + From 3c7ac60dbe2e2e623f6aea1d746418335a2a6dbe Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 22 Jun 2020 20:39:36 +0200 Subject: [PATCH 136/653] added overflow checking --- osal/FreeRTOS/FixedTimeslotTask.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index edb7f835..d92474c7 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -111,8 +111,15 @@ void FixedTimeslotTask::taskFunctionality() { /* If all operations are finished and the difference of the * current time minus the last wake time is larger than the - * expected wait period, a deadline was missed. */ - if(xTaskGetTickCount() - xLastWakeTime >= interval) { + * expected wait period, a deadline was missed. + * We also check whether an overflow has occured first. + * In this special case, we will ignore missed deadlines for now. */ + const TickType_t constTickCount = xTaskGetTickCount(); + if(constTickCount < xLastWakeTime or + constTickCount + interval < xLastWakeTime) { + // don't do anything for now. + } + else if(xTaskGetTickCount() - xLastWakeTime >= interval) { #ifdef DEBUG sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) << " missed deadline!\n" << std::flush; From bf63ba15fedfacd7ae19de5298d49a0a05154aae Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 22 Jun 2020 23:30:17 +0200 Subject: [PATCH 137/653] finished overflow checking (hopefully) --- osal/FreeRTOS/FixedTimeslotTask.cpp | 55 +++++++++++++++++++---------- osal/FreeRTOS/FixedTimeslotTask.h | 4 +++ 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index d92474c7..d72354ae 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -109,25 +109,8 @@ void FixedTimeslotTask::taskFunctionality() { intervalMs = this->pst.getIntervalToPreviousSlotMs(); interval = pdMS_TO_TICKS(intervalMs); - /* If all operations are finished and the difference of the - * current time minus the last wake time is larger than the - * expected wait period, a deadline was missed. - * We also check whether an overflow has occured first. - * In this special case, we will ignore missed deadlines for now. */ - const TickType_t constTickCount = xTaskGetTickCount(); - if(constTickCount < xLastWakeTime or - constTickCount + interval < xLastWakeTime) { - // don't do anything for now. - } - else if(xTaskGetTickCount() - xLastWakeTime >= interval) { -#ifdef DEBUG - sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) << - " missed deadline!\n" << std::flush; -#endif - if(deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); - } - } + checkMissedDeadline(xLastWakeTime, interval); + // Wait for the interval. This exits immediately if a deadline was // missed while also updating the last wake time. vTaskDelayUntil(&xLastWakeTime, interval); @@ -135,6 +118,40 @@ void FixedTimeslotTask::taskFunctionality() { } } +void FixedTimeslotTask::checkMissedDeadline(const TickType_t xLastWakeTime, + const TickType_t interval) { + /* Check whether deadline was missed while also taking overflows + * into account. Drawing this on paper with a timeline helps to understand + * it. */ + TickType_t currentTickCount = xTaskGetTickCount(); + TickType_t timeToWake = xLastWakeTime + interval; + // Tick count has overflown + if(currentTickCount < xLastWakeTime) { + // Time to wake has overflown as well. If the tick count + // is larger than the time to wake, a deadline was missed. + if(timeToWake < xLastWakeTime and + currentTickCount > timeToWake) { + handleMissedDeadline(); + } + } + // No tick count overflow. If the timeToWake has not overflown + // and the current tick count is larger than the time to wake, + // a deadline was missed. + else if(timeToWake > xLastWakeTime and currentTickCount > timeToWake) { + handleMissedDeadline(); + } +} + +void FixedTimeslotTask::handleMissedDeadline() { +#ifdef DEBUG + sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) << + " missed deadline!\n" << std::flush; +#endif + if(deadlineMissedFunc != nullptr) { + this->deadlineMissedFunc(); + } +} + ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { vTaskDelay(pdMS_TO_TICKS(ms)); return HasReturnvaluesIF::RETURN_OK; diff --git a/osal/FreeRTOS/FixedTimeslotTask.h b/osal/FreeRTOS/FixedTimeslotTask.h index 39db667c..cddd5ecd 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.h +++ b/osal/FreeRTOS/FixedTimeslotTask.h @@ -89,6 +89,10 @@ protected: * OS's System Calls to keep the timing of the periods. */ void taskFunctionality(void); + + void checkMissedDeadline(const TickType_t xLastWakeTime, + const TickType_t interval); + void handleMissedDeadline(); }; #endif /* POLLINGTASK_H_ */ From 0c9c9c581ba1aa05acc9de1e6af9528c99b1a4fd Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 22 Jun 2020 23:31:27 +0200 Subject: [PATCH 138/653] minor formatting --- osal/FreeRTOS/FixedTimeslotTask.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index d72354ae..871b7922 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -90,9 +90,9 @@ void FixedTimeslotTask::taskFunctionality() { TickType_t xLastWakeTime; /* The xLastWakeTime variable needs to be initialized with the current tick - count. Note that this is the only time the variable is written to explicitly. - After this assignment, xLastWakeTime is updated automatically internally within - vTaskDelayUntil(). */ + count. Note that this is the only time the variable is written to + explicitly. After this assignment, xLastWakeTime is updated automatically + internally within vTaskDelayUntil(). */ xLastWakeTime = xTaskGetTickCount(); // wait for first entry's start time From 1cc50639c7ca8d99377d6bc753f9c6815469b659 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 22 Jun 2020 23:49:31 +0200 Subject: [PATCH 139/653] improvements integrated --- osal/FreeRTOS/FixedTimeslotTask.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.h b/osal/FreeRTOS/FixedTimeslotTask.h index cddd5ecd..08a9c3b3 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.h +++ b/osal/FreeRTOS/FixedTimeslotTask.h @@ -12,7 +12,7 @@ class FixedTimeslotTask: public FixedTimeslotTaskIF { public: /** - * Keep in Mind that you need to call before this vTaskStartScheduler()! + * Keep in mind that you need to call before vTaskStartScheduler()! * A lot of task parameters are set in "FreeRTOSConfig.h". * @param name Name of the task, lenght limited by configMAX_TASK_NAME_LEN * @param setPriority Number of priorities specified by @@ -49,13 +49,13 @@ public: static uint32_t deadlineMissedCount; ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, - int8_t executionStep); + int8_t executionStep) override; - uint32_t getPeriodMs() const; + uint32_t getPeriodMs() const override; - ReturnValue_t checkSequence() const; + ReturnValue_t checkSequence() const override; - ReturnValue_t sleepFor(uint32_t ms); + ReturnValue_t sleepFor(uint32_t ms) override; protected: bool started; From 4507bdfb69f9a8239b8af6c51d1f9c1a32338ae8 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 23 Jun 2020 01:14:28 +0200 Subject: [PATCH 140/653] added setting task IF --- osal/FreeRTOS/PeriodicTask.cpp | 62 +++++++++++++++++++++++--------- osal/FreeRTOS/PeriodicTask.h | 13 ++++--- osal/linux/PeriodicPosixTask.cpp | 9 +++-- osal/linux/PeriodicPosixTask.h | 7 ++-- tasks/PeriodicTaskIF.h | 26 +++++++++++--- 5 files changed, 87 insertions(+), 30 deletions(-) diff --git a/osal/FreeRTOS/PeriodicTask.cpp b/osal/FreeRTOS/PeriodicTask.cpp index 31867639..170eb0a4 100644 --- a/osal/FreeRTOS/PeriodicTask.cpp +++ b/osal/FreeRTOS/PeriodicTask.cpp @@ -70,39 +70,67 @@ void PeriodicTask::taskFunctionality() { xLastWakeTime = xTaskGetTickCount(); /* Enter the loop that defines the task behavior. */ for (;;) { - for (ObjectList::iterator it = objectList.begin(); - it != objectList.end(); ++it) { - (*it)->performOperation(); + for (auto const& object: objectList) { + object->performOperation(); } - /* If all operations are finished and the difference of the - * current time minus the last wake time is larger than the - * wait period, a deadline was missed. */ - if(xTaskGetTickCount() - xLastWakeTime >= xPeriod) { -#ifdef DEBUG - sif::warning << "PeriodicTask: " << pcTaskGetName(NULL) << - " missed deadline!\n" << std::flush; -#endif - if(deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); - } - } + checkMissedDeadline(xLastWakeTime, xPeriod); vTaskDelayUntil(&xLastWakeTime, xPeriod); } } -ReturnValue_t PeriodicTask::addComponent(object_id_t object) { +ReturnValue_t PeriodicTask::addComponent(object_id_t object, bool setTaskIF) { ExecutableObjectIF* newObject = objectManager->get( object); - if (newObject == NULL) { + if (newObject == nullptr) { + sif::error << "PeriodicTask::addComponent: Invalid object. Make sure" + "it implement ExecutableObjectIF" << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } objectList.push_back(newObject); + + if(setTaskIF) { + newObject->setTaskIF(this); + } return HasReturnvaluesIF::RETURN_OK; } uint32_t PeriodicTask::getPeriodMs() const { return period * 1000; } + +void PeriodicTask::checkMissedDeadline(const TickType_t xLastWakeTime, + const TickType_t interval) { + /* Check whether deadline was missed while also taking overflows + * into account. Drawing this on paper with a timeline helps to understand + * it. */ + TickType_t currentTickCount = xTaskGetTickCount(); + TickType_t timeToWake = xLastWakeTime + interval; + // Tick count has overflown + if(currentTickCount < xLastWakeTime) { + // Time to wake has overflown as well. If the tick count + // is larger than the time to wake, a deadline was missed. + if(timeToWake < xLastWakeTime and + currentTickCount > timeToWake) { + handleMissedDeadline(); + } + } + // No tick count overflow. If the timeToWake has not overflown + // and the current tick count is larger than the time to wake, + // a deadline was missed. + else if(timeToWake > xLastWakeTime and currentTickCount > timeToWake) { + handleMissedDeadline(); + } +} + +void PeriodicTask::handleMissedDeadline() { +#ifdef DEBUG + sif::warning << "PeriodicTask: " << pcTaskGetName(NULL) << + " missed deadline!\n" << std::flush; +#endif + if(deadlineMissedFunc != nullptr) { + this->deadlineMissedFunc(); + } +} diff --git a/osal/FreeRTOS/PeriodicTask.h b/osal/FreeRTOS/PeriodicTask.h index b9930a73..09aa6bc7 100644 --- a/osal/FreeRTOS/PeriodicTask.h +++ b/osal/FreeRTOS/PeriodicTask.h @@ -54,7 +54,7 @@ public: * The address of the task object is passed as an argument * to the system call. */ - ReturnValue_t startTask(void); + ReturnValue_t startTask() override; /** * Adds an object to the list of objects to be executed. * The objects are executed in the order added. @@ -63,11 +63,12 @@ public: * -@c RETURN_OK on success * -@c RETURN_FAILED if the object could not be added. */ - ReturnValue_t addComponent(object_id_t object); + ReturnValue_t addComponent(object_id_t object, + bool setTaskIF = true) override; - uint32_t getPeriodMs() const; + uint32_t getPeriodMs() const override; - ReturnValue_t sleepFor(uint32_t ms); + ReturnValue_t sleepFor(uint32_t ms) override; protected: bool started; TaskHandle_t handle; @@ -115,6 +116,10 @@ protected: * On missing the deadline, the deadlineMissedFunction is executed. */ void taskFunctionality(void); + + void checkMissedDeadline(const TickType_t xLastWakeTime, + const TickType_t interval); + void handleMissedDeadline(); }; #endif /* PERIODICTASK_H_ */ diff --git a/osal/linux/PeriodicPosixTask.cpp b/osal/linux/PeriodicPosixTask.cpp index b754c3f4..1a06a8bf 100644 --- a/osal/linux/PeriodicPosixTask.cpp +++ b/osal/linux/PeriodicPosixTask.cpp @@ -20,13 +20,18 @@ void* PeriodicPosixTask::taskEntryPoint(void* arg) { return NULL; } -ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object) { +ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object, + bool addTaskIF) { ExecutableObjectIF* newObject = objectManager->get( object); - if (newObject == NULL) { + if (newObject == nullptr) { return HasReturnvaluesIF::RETURN_FAILED; } objectList.push_back(newObject); + + if(setTaskIF) { + newObject->setTaskIF(this); + } return HasReturnvaluesIF::RETURN_OK; } diff --git a/osal/linux/PeriodicPosixTask.h b/osal/linux/PeriodicPosixTask.h index 43647eda..e994898a 100644 --- a/osal/linux/PeriodicPosixTask.h +++ b/osal/linux/PeriodicPosixTask.h @@ -26,11 +26,12 @@ public: * @param object Id of the object to add. * @return RETURN_OK on success, RETURN_FAILED if the object could not be added. */ - ReturnValue_t addComponent(object_id_t object); + ReturnValue_t addComponent(object_id_t object, + bool addTaskIF = true) override; - uint32_t getPeriodMs() const; + uint32_t getPeriodMs() const override; - ReturnValue_t sleepFor(uint32_t ms); + ReturnValue_t sleepFor(uint32_t ms) override; private: typedef std::vector ObjectList; //!< Typedef for the List of objects. diff --git a/tasks/PeriodicTaskIF.h b/tasks/PeriodicTaskIF.h index 304a7de6..6f490977 100644 --- a/tasks/PeriodicTaskIF.h +++ b/tasks/PeriodicTaskIF.h @@ -1,9 +1,11 @@ -#ifndef PERIODICTASKIF_H_ -#define PERIODICTASKIF_H_ +#ifndef FRAMEWORK_TASK_PERIODICTASKIF_H_ +#define FRAMEWORK_TASK_PERIODICTASKIF_H_ #include +#include #include class ExecutableObjectIF; + /** * New version of TaskIF * Follows RAII principles, i.e. there's no create or delete method. @@ -17,11 +19,27 @@ public: */ virtual ~PeriodicTaskIF() { } /** - * @brief With the startTask method, a created task can be started for the first time. + * @brief With the startTask method, a created task can be started + * for the first time. */ virtual ReturnValue_t startTask() = 0; - virtual ReturnValue_t addComponent(object_id_t object) {return HasReturnvaluesIF::RETURN_FAILED;}; + /** + * Add a component (object) to a periodic task. The pointer to the + * task can be set optionally + * @param object + * Add an object to the task. The most important case is to add an + * executable object with a function which will be called regularly + * (see ExecutableObjectIF) + * @param setTaskIF + * Can be used to specify whether the task object pointer is passed + * to the component. + * @return + */ + virtual ReturnValue_t addComponent(object_id_t object, + bool setTaskIF = true) { + return HasReturnvaluesIF::RETURN_FAILED; + }; virtual ReturnValue_t sleepFor(uint32_t ms) = 0; From e935b8bd04ee349e45c4bdcd60a2fa306cc73d74 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 23 Jun 2020 10:45:47 +0200 Subject: [PATCH 141/653] some minor improvements --- tmtcservices/TmTcBridge.cpp | 50 ++++++++++++++++--------------------- tmtcservices/TmTcBridge.h | 20 ++++++++------- 2 files changed, 32 insertions(+), 38 deletions(-) diff --git a/tmtcservices/TmTcBridge.cpp b/tmtcservices/TmTcBridge.cpp index b4732a85..f9a7d3bc 100644 --- a/tmtcservices/TmTcBridge.cpp +++ b/tmtcservices/TmTcBridge.cpp @@ -1,9 +1,9 @@ #include #include -#include #include #include +#include TmTcBridge::TmTcBridge(object_id_t objectId_, object_id_t ccsdsPacketDistributor_): SystemObject(objectId_), @@ -22,7 +22,7 @@ ReturnValue_t TmTcBridge::setNumberOfSentPacketsPerCycle( return RETURN_OK; } else { - warning << "TmTcBridge: Number of packets sent per cycle " + sif::warning << "TmTcBridge: Number of packets sent per cycle " "exceeds limits. Keeping default value." << std::endl; return RETURN_FAILED; } @@ -35,7 +35,7 @@ ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored( return RETURN_OK; } else { - warning << "TmTcBridge: Number of packets stored " + sif::warning << "TmTcBridge: Number of packets stored " "exceeds limits. Keeping default value." << std::endl; return RETURN_FAILED; } @@ -63,11 +63,11 @@ ReturnValue_t TmTcBridge::performOperation(uint8_t operationCode) { ReturnValue_t result; result = handleTc(); if(result != RETURN_OK) { - error << "TMTC Bridge: Error handling TCs" << std::endl; + sif::error << "TMTC Bridge: Error handling TCs" << std::endl; } result = handleTm(); if (result != RETURN_OK) { - error << "TMTC Bridge: Error handling TMs" << std::endl; + sif::error << "TMTC Bridge: Error handling TMs" << std::endl; } return result; } @@ -82,11 +82,11 @@ ReturnValue_t TmTcBridge::handleTc() { ReturnValue_t TmTcBridge::handleTm() { ReturnValue_t result = handleTmQueue(); if(result != RETURN_OK) { - error << "TMTC Bridge: Reading TM Queue failed" << std::endl; + sif::error << "TMTC Bridge: Reading TM Queue failed" << std::endl; return RETURN_FAILED; } - if(tmStored && communicationLinkUp) { + if(tmStored and communicationLinkUp) { result = handleStoredTm(); } return result; @@ -95,8 +95,8 @@ ReturnValue_t TmTcBridge::handleTm() { ReturnValue_t TmTcBridge::handleTmQueue() { TmTcMessage message; - const uint8_t* data = nullptr; - uint32_t size = 0; + const uint8_t* data = nullptr; + size_t size = 0; for (ReturnValue_t result = TmTcReceptionQueue->receiveMessage(&message); result == RETURN_OK; result = TmTcReceptionQueue->receiveMessage(&message)) { @@ -112,7 +112,7 @@ ReturnValue_t TmTcBridge::handleTmQueue() { result = sendTm(data, size); if (result != RETURN_OK) { - error << "TMTC Bridge: Could not send TM packet"<< std::endl; + sif::error << "TMTC Bridge: Could not send TM packet"<< std::endl; tmStore->deleteData(message.getStorageId()); return result; @@ -127,14 +127,14 @@ ReturnValue_t TmTcBridge::storeDownlinkData(TmTcMessage *message) { // "Saving packet ID to be sent later\r\n" << std::flush; store_address_t storeId = 0; - if(fifo.full()) { - error << "TMTC Bridge: TM downlink max. number of stored packet IDs " + if(tmFifo.full()) { + sif::error << "TMTC Bridge: TM downlink max. number of stored packet IDs " "reached! Overwriting old data" << std::endl; - fifo.retrieve(&storeId); + tmFifo.retrieve(&storeId); tmStore->deleteData(storeId); } storeId = message->getStorageId(); - fifo.insert(storeId); + tmFifo.insert(storeId); tmStored = true; return RETURN_OK; } @@ -142,25 +142,25 @@ ReturnValue_t TmTcBridge::storeDownlinkData(TmTcMessage *message) { ReturnValue_t TmTcBridge::handleStoredTm() { uint8_t counter = 0; ReturnValue_t result = RETURN_OK; - while(not fifo.empty() && counter < sentPacketsPerCycle) { + while(not tmFifo.empty() and counter < sentPacketsPerCycle) { //info << "TMTC Bridge: Sending stored TM data. There are " // << (int) fifo.size() << " left to send\r\n" << std::flush; store_address_t storeId; - const uint8_t* data = NULL; - uint32_t size = 0; - fifo.retrieve(&storeId); + const uint8_t* data = nullptr; + size_t size = 0; + tmFifo.retrieve(&storeId); result = tmStore->getData(storeId, &data, &size); sendTm(data,size); if(result != RETURN_OK) { - error << "TMTC Bridge: Could not send stored downlink data" + sif::error << "TMTC Bridge: Could not send stored downlink data" << std::endl; result = RETURN_FAILED; } counter ++; - if(fifo.empty()) { + if(tmFifo.empty()) { tmStored = false; } tmStore->deleteData(storeId); @@ -187,14 +187,6 @@ MessageQueueId_t TmTcBridge::getReportReceptionQueue(uint8_t virtualChannel) { } - void TmTcBridge::printData(uint8_t * data, size_t dataLen) { - info << "TMTC Bridge: Printing data: ["; - for(uint32_t i = 0; i < dataLen; i++) { - info << std::hex << (int)data[i]; - if(i < dataLen-1){ - info << " , "; - } - } - info << " ] " << std::endl; + arrayprinter::print(data, dataLen); } diff --git a/tmtcservices/TmTcBridge.h b/tmtcservices/TmTcBridge.h index 15fd42c1..3e0432d8 100644 --- a/tmtcservices/TmTcBridge.h +++ b/tmtcservices/TmTcBridge.h @@ -25,8 +25,6 @@ public: TmTcBridge(object_id_t objectId_, object_id_t ccsdsPacketDistributor_); virtual ~TmTcBridge(); - void setDelayBetweenSentPackets(uint32_t delayBetweenSentPackets); - /** * Set number of packets sent per performOperation().Please note that this * value must be smaller than MAX_STORED_DATA_SENT_PER_CYCLE @@ -45,8 +43,8 @@ public: */ ReturnValue_t setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored); - void registerCommConnect(); - void registerCommDisconnect(); + virtual void registerCommConnect(); + virtual void registerCommDisconnect(); /** * Initializes necessary FSFW components for the TMTC Bridge @@ -64,7 +62,8 @@ public: * @param virtualChannel * @return */ - MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel = 0) override; + MessageQueueId_t getReportReceptionQueue( + uint8_t virtualChannel = 0) override; protected: //! Used to send and receive TMTC messages. //! TmTcMessage is used to transport messages between tasks. @@ -75,7 +74,6 @@ protected: //! Used to specify whether communication link is up bool communicationLinkUp = false; bool tmStored = false; - FIFO fifo; /** * @brief Handle TC reception @@ -141,9 +139,13 @@ protected: */ void printData(uint8_t * data, size_t dataLen); -private: - uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE; - uint8_t maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED; + /** + * This fifo can be used to store downlink data + * which can not be sent at the moment. + */ + FIFO tmFifo; + uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE; + uint8_t maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED; }; From 4c59b043e13aa8f21949d9adf9662e75ecb98611 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 23 Jun 2020 10:57:14 +0200 Subject: [PATCH 142/653] const store accessor in separate file now --- storagemanager/ConstStoreAccessor.cpp | 93 +++++++++++++++++++++ storagemanager/ConstStoreAccessor.h | 116 ++++++++++++++++++++++++++ storagemanager/StorageAccessor.cpp | 98 ++-------------------- storagemanager/StorageAccessor.h | 109 +----------------------- 4 files changed, 215 insertions(+), 201 deletions(-) create mode 100644 storagemanager/ConstStoreAccessor.cpp create mode 100644 storagemanager/ConstStoreAccessor.h diff --git a/storagemanager/ConstStoreAccessor.cpp b/storagemanager/ConstStoreAccessor.cpp new file mode 100644 index 00000000..84f40053 --- /dev/null +++ b/storagemanager/ConstStoreAccessor.cpp @@ -0,0 +1,93 @@ +#include +#include +#include + +ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): + storeId(storeId) {} + +ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId, + StorageManagerIF* store): + storeId(storeId), store(store) { + internalState = AccessState::ASSIGNED; +} + +ConstStorageAccessor::~ConstStorageAccessor() { + if(deleteData and store != nullptr) { + sif::debug << "deleting store data" << std::endl; + store->deleteData(storeId); + } +} + +ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other): + constDataPointer(other.constDataPointer), storeId(other.storeId), + size_(other.size_), store(other.store), deleteData(other.deleteData), + internalState(other.internalState) { + // This prevent premature deletion + other.store = nullptr; +} + +ConstStorageAccessor& ConstStorageAccessor::operator=( + ConstStorageAccessor&& other) { + constDataPointer = other.constDataPointer; + storeId = other.storeId; + store = other.store; + size_ = other.size_; + deleteData = other.deleteData; + this->store = other.store; + // This prevents premature deletion + other.store = nullptr; + return *this; +} + +const uint8_t* ConstStorageAccessor::data() const { + return constDataPointer; +} + +size_t ConstStorageAccessor::size() const { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + } + return size_; +} + +ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t *pointer, + size_t maxSize) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(size_ > maxSize) { + sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(constDataPointer, constDataPointer + size_, pointer); + return HasReturnvaluesIF::RETURN_OK; +} + +void ConstStorageAccessor::release() { + deleteData = false; +} + +store_address_t ConstStorageAccessor::getId() const { + return storeId; +} + +void ConstStorageAccessor::print() const { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return; + } + sif::info << "StorageAccessor: Printing data: ["; + for(uint16_t iPool = 0; iPool < size_; iPool++) { + sif::info << std::hex << (int)constDataPointer[iPool]; + if(iPool < size_ - 1){ + sif::info << " , "; + } + } + sif::info << " ] " << std::endl; +} + +void ConstStorageAccessor::assignStore(StorageManagerIF* store) { + internalState = AccessState::ASSIGNED; + this->store = store; +} diff --git a/storagemanager/ConstStoreAccessor.h b/storagemanager/ConstStoreAccessor.h new file mode 100644 index 00000000..2420893c --- /dev/null +++ b/storagemanager/ConstStoreAccessor.h @@ -0,0 +1,116 @@ +#ifndef FRAMEWORK_STORAGEMANAGER_CONSTSTOREACCESSOR_H_ +#define FRAMEWORK_STORAGEMANAGER_CONSTSTOREACCESSOR_H_ + +#include +#include +#include + +class StorageManagerIF; + +/** + * @brief Helper classes to facilitate safe access to storages which is also + * conforming to RAII principles + * @details + * Accessor class which can be returned by pool manager or passed and set by + * pool managers to have safe access to the pool resources. + * + * These helper can be used together with the StorageManager classes to manage + * access to a storage. It can take care of thread-safety while also providing + * mechanisms to automatically clear storage data. + */ +class ConstStorageAccessor { + //! StorageManager classes have exclusive access to private variables. + template + friend class PoolManager; + template + friend class LocalPool; +public: + /** + * @brief Simple constructor which takes the store ID of the storage + * entry to access. + * @param storeId + */ + ConstStorageAccessor(store_address_t storeId); + ConstStorageAccessor(store_address_t storeId, StorageManagerIF* store); + + /** + * @brief The destructor in default configuration takes care of + * deleting the accessed pool entry and unlocking the mutex + */ + virtual ~ConstStorageAccessor(); + + /** + * @brief Returns a pointer to the read-only data + * @return + */ + const uint8_t* data() const; + + /** + * @brief Copies the read-only data to the supplied pointer + * @param pointer + */ + virtual ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize); + + /** + * @brief Calling this will prevent the Accessor from deleting the data + * when the destructor is called. + */ + void release(); + + /** + * Get the size of the data + * @return + */ + size_t size() const; + + /** + * Get the storage ID. + * @return + */ + store_address_t getId() const; + + void print() const; + + /** + * @brief Move ctor and move assignment allow returning accessors as + * a returnvalue. They prevent resource being free prematurely. + * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ + * move-constructors-and-move-assignment-operators-cpp.md + * @param + * @return + */ + ConstStorageAccessor& operator= (ConstStorageAccessor&&); + ConstStorageAccessor (ConstStorageAccessor&&); + + //! The copy ctor and copy assignemnt should be deleted implicitely + //! according to https://foonathan.net/2019/02/special-member-functions/ + //! but I still deleted them to make it more explicit. (remember rule of 5). + ConstStorageAccessor& operator= (ConstStorageAccessor&) = delete; + ConstStorageAccessor (ConstStorageAccessor&) = delete; +protected: + const uint8_t* constDataPointer = nullptr; + store_address_t storeId; + size_t size_ = 0; + //! Managing pool, has to assign itself. + StorageManagerIF* store = nullptr; + bool deleteData = true; + + enum class AccessState { + UNINIT, + ASSIGNED + }; + //! Internal state for safety reasons. + AccessState internalState = AccessState::UNINIT; + /** + * Used by the pool manager instances to assign themselves to the + * accessor. This is necessary to delete the data when the acessor + * exits the scope ! The internal state will be considered read + * when this function is called, so take care all data is set properly as + * well. + * @param + */ + void assignStore(StorageManagerIF*); +}; + + +#endif /* FRAMEWORK_STORAGEMANAGER_CONSTSTOREACCESSOR_H_ */ diff --git a/storagemanager/StorageAccessor.cpp b/storagemanager/StorageAccessor.cpp index c0c8126b..b827b9c0 100644 --- a/storagemanager/StorageAccessor.cpp +++ b/storagemanager/StorageAccessor.cpp @@ -1,96 +1,6 @@ #include #include - -ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): - storeId(storeId) {} - -ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId, - StorageManagerIF* store): - storeId(storeId), store(store) { - internalState = AccessState::ASSIGNED; -} - -ConstStorageAccessor::~ConstStorageAccessor() { - if(deleteData and store != nullptr) { - sif::debug << "deleting store data" << std::endl; - store->deleteData(storeId); - } -} - -ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other): - constDataPointer(other.constDataPointer), storeId(other.storeId), - size_(other.size_), store(other.store), deleteData(other.deleteData), - internalState(other.internalState) { - // This prevent premature deletion - other.store = nullptr; -} - -ConstStorageAccessor& ConstStorageAccessor::operator=( - ConstStorageAccessor&& other) { - constDataPointer = other.constDataPointer; - storeId = other.storeId; - store = other.store; - size_ = other.size_; - deleteData = other.deleteData; - this->store = other.store; - // This prevents premature deletion - other.store = nullptr; - return *this; -} - -const uint8_t* ConstStorageAccessor::data() const { - return constDataPointer; -} - -size_t ConstStorageAccessor::size() const { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - } - return size_; -} - -ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t *pointer, - size_t maxSize) { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - if(size_ > maxSize) { - sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - std::copy(constDataPointer, constDataPointer + size_, pointer); - return HasReturnvaluesIF::RETURN_OK; -} - -void ConstStorageAccessor::release() { - deleteData = false; -} - -store_address_t ConstStorageAccessor::getId() const { - return storeId; -} - -void ConstStorageAccessor::print() const { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return; - } - sif::info << "StorageAccessor: Printing data: ["; - for(uint16_t iPool = 0; iPool < size_; iPool++) { - sif::info << std::hex << (int)constDataPointer[iPool]; - if(iPool < size_ - 1){ - sif::info << " , "; - } - } - sif::info << " ] " << std::endl; -} - -void ConstStorageAccessor::assignStore(StorageManagerIF* store) { - internalState = AccessState::ASSIGNED; - this->store = store; -} - +#include StorageAccessor::StorageAccessor(store_address_t storeId): ConstStorageAccessor(storeId) { @@ -120,7 +30,8 @@ ReturnValue_t StorageAccessor::getDataCopy(uint8_t *pointer, size_t maxSize) { return HasReturnvaluesIF::RETURN_FAILED; } if(size_ > maxSize) { - sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; + sif::error << "StorageAccessor: Supplied buffer not large " + "enough" << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } std::copy(dataPointer, dataPointer + size_, pointer); @@ -141,7 +52,8 @@ ReturnValue_t StorageAccessor::write(uint8_t *data, size_t size, return HasReturnvaluesIF::RETURN_FAILED; } if(offset + size > size_) { - sif::error << "StorageAccessor: Data too large for pool entry!" << std::endl; + sif::error << "StorageAccessor: Data too large for pool " + "entry!" << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } std::copy(data, data + size, dataPointer + offset); diff --git a/storagemanager/StorageAccessor.h b/storagemanager/StorageAccessor.h index 57c9369c..bcefe24d 100644 --- a/storagemanager/StorageAccessor.h +++ b/storagemanager/StorageAccessor.h @@ -1,117 +1,10 @@ #ifndef FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ #define FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ -#include -#include +#include class StorageManagerIF; -/** - * @brief Helper classes to facilitate safe access to storages which is also - * conforming to RAII principles - * @details - * Accessor class which can be returned by pool manager or passed and set by - * pool managers to have safe access to the pool resources. - * - * These helper can be used together with the StorageManager classes to manage - * access to a storage. It can take care of thread-safety while also providing - * mechanisms to automatically clear storage data. - */ -class ConstStorageAccessor { - //! StorageManager classes have exclusive access to private variables. - template - friend class PoolManager; - template - friend class LocalPool; -public: - /** - * @brief Simple constructor which takes the store ID of the storage - * entry to access. - * @param storeId - */ - ConstStorageAccessor(store_address_t storeId); - ConstStorageAccessor(store_address_t storeId, StorageManagerIF* store); - - /** - * @brief The destructor in default configuration takes care of - * deleting the accessed pool entry and unlocking the mutex - */ - virtual ~ConstStorageAccessor(); - - /** - * @brief Returns a pointer to the read-only data - * @return - */ - const uint8_t* data() const; - - /** - * @brief Copies the read-only data to the supplied pointer - * @param pointer - */ - virtual ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize); - - /** - * @brief Calling this will prevent the Accessor from deleting the data - * when the destructor is called. - */ - void release(); - - /** - * Get the size of the data - * @return - */ - size_t size() const; - - /** - * Get the storage ID. - * @return - */ - store_address_t getId() const; - - void print() const; - - /** - * @brief Move ctor and move assignment allow returning accessors as - * a returnvalue. They prevent resource being free prematurely. - * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ - * move-constructors-and-move-assignment-operators-cpp.md - * @param - * @return - */ - ConstStorageAccessor& operator= (ConstStorageAccessor&&); - ConstStorageAccessor (ConstStorageAccessor&&); - - //! The copy ctor and copy assignemnt should be deleted implicitely - //! according to https://foonathan.net/2019/02/special-member-functions/ - //! but I still deleted them to make it more explicit. (remember rule of 5). - ConstStorageAccessor& operator= (ConstStorageAccessor&) = delete; - ConstStorageAccessor (ConstStorageAccessor&) = delete; -protected: - const uint8_t* constDataPointer = nullptr; - store_address_t storeId; - size_t size_ = 0; - //! Managing pool, has to assign itself. - StorageManagerIF* store = nullptr; - bool deleteData = true; - - enum class AccessState { - UNINIT, - ASSIGNED - }; - //! Internal state for safety reasons. - AccessState internalState = AccessState::UNINIT; - /** - * Used by the pool manager instances to assign themselves to the - * accessor. This is necessary to delete the data when the acessor - * exits the scope ! The internal state will be considered read - * when this function is called, so take care all data is set properly as - * well. - * @param - */ - void assignStore(StorageManagerIF*); -}; - - /** * @brief Child class for modifyable data. Also has a normal pointer member. */ From a589be7c746d9f44b3ef3b47fceaa2ae3cd8412e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 23 Jun 2020 11:06:54 +0200 Subject: [PATCH 143/653] took over imrpvements --- ...tStoreAccessor.cpp => ConstStorageAccessor.cpp} | 14 ++++---------- ...ConstStoreAccessor.h => ConstStorageAccessor.h} | 6 +++--- storagemanager/PoolManager.h | 3 +++ storagemanager/PoolManager.tpp | 6 +++--- storagemanager/StorageAccessor.h | 2 +- 5 files changed, 14 insertions(+), 17 deletions(-) rename storagemanager/{ConstStoreAccessor.cpp => ConstStorageAccessor.cpp} (87%) rename storagemanager/{ConstStoreAccessor.h => ConstStorageAccessor.h} (94%) diff --git a/storagemanager/ConstStoreAccessor.cpp b/storagemanager/ConstStorageAccessor.cpp similarity index 87% rename from storagemanager/ConstStoreAccessor.cpp rename to storagemanager/ConstStorageAccessor.cpp index 84f40053..0bfde58c 100644 --- a/storagemanager/ConstStoreAccessor.cpp +++ b/storagemanager/ConstStorageAccessor.cpp @@ -1,6 +1,7 @@ -#include #include +#include #include +#include ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): storeId(storeId) {} @@ -73,18 +74,11 @@ store_address_t ConstStorageAccessor::getId() const { } void ConstStorageAccessor::print() const { - if(internalState == AccessState::UNINIT) { + if(internalState == AccessState::UNINIT or constDataPointer == nullptr) { sif::warning << "StorageAccessor: Not initialized!" << std::endl; return; } - sif::info << "StorageAccessor: Printing data: ["; - for(uint16_t iPool = 0; iPool < size_; iPool++) { - sif::info << std::hex << (int)constDataPointer[iPool]; - if(iPool < size_ - 1){ - sif::info << " , "; - } - } - sif::info << " ] " << std::endl; + arrayprinter::print(constDataPointer, size_); } void ConstStorageAccessor::assignStore(StorageManagerIF* store) { diff --git a/storagemanager/ConstStoreAccessor.h b/storagemanager/ConstStorageAccessor.h similarity index 94% rename from storagemanager/ConstStoreAccessor.h rename to storagemanager/ConstStorageAccessor.h index 2420893c..cf8ca08f 100644 --- a/storagemanager/ConstStoreAccessor.h +++ b/storagemanager/ConstStorageAccessor.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_CONSTSTOREACCESSOR_H_ -#define FRAMEWORK_STORAGEMANAGER_CONSTSTOREACCESSOR_H_ +#ifndef FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ +#define FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ #include #include @@ -113,4 +113,4 @@ protected: }; -#endif /* FRAMEWORK_STORAGEMANAGER_CONSTSTOREACCESSOR_H_ */ +#endif /* FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ */ diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index 7c2e8a71..3c1c1217 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -29,6 +29,9 @@ public: store_address_t* storeId = nullptr) override; protected: + //! Default mutex timeout value to prevent permanent blocking. + static constexpr uint32_t mutexTimeout = 50; + ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault) override; diff --git a/storagemanager/PoolManager.tpp b/storagemanager/PoolManager.tpp index a364f5a2..4ca22b85 100644 --- a/storagemanager/PoolManager.tpp +++ b/storagemanager/PoolManager.tpp @@ -21,7 +21,7 @@ inline PoolManager::~PoolManager(void) { template inline ReturnValue_t PoolManager::reserveSpace( const uint32_t size, store_address_t* address, bool ignoreFault) { - MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); + MutexHelper mutexHelper(mutex, mutexTimeout); ReturnValue_t status = LocalPool::reserveSpace(size, address,ignoreFault); return status; @@ -33,7 +33,7 @@ inline ReturnValue_t PoolManager::deleteData( // debug << "PoolManager( " << translateObject(getObjectId()) << // " )::deleteData from store " << packet_id.pool_index << // ". id is "<< packet_id.packet_index << std::endl; - MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); + MutexHelper mutexHelper(mutex, mutexTimeout); ReturnValue_t status = LocalPool::deleteData(packet_id); return status; } @@ -41,7 +41,7 @@ inline ReturnValue_t PoolManager::deleteData( template inline ReturnValue_t PoolManager::deleteData(uint8_t* buffer, size_t size, store_address_t* storeId) { - MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); + MutexHelper mutexHelper(mutex, mutexTimeout); ReturnValue_t status = LocalPool::deleteData(buffer, size, storeId); return status; diff --git a/storagemanager/StorageAccessor.h b/storagemanager/StorageAccessor.h index bcefe24d..c5e38306 100644 --- a/storagemanager/StorageAccessor.h +++ b/storagemanager/StorageAccessor.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ #define FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ -#include +#include class StorageManagerIF; From f6d2549534e8c4baa59e718781d3384c1d7922eb Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 24 Jun 2020 11:35:07 +0200 Subject: [PATCH 144/653] requested changed implemented --- container/HybridIterator.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/container/HybridIterator.h b/container/HybridIterator.h index db1ce4bc..79f0485f 100644 --- a/container/HybridIterator.h +++ b/container/HybridIterator.h @@ -17,8 +17,8 @@ public: } HybridIterator(LinkedElement *start) : - LinkedElement::Iterator(start), value( - start->value), linked(true), end(NULL) { + LinkedElement::Iterator(start), value(start->value), + linked(true) { } @@ -64,11 +64,11 @@ public: return tmp; } - bool operator==(const HybridIterator& other) { + bool operator==(const HybridIterator& other) const { return value == other.value; } - bool operator!=(const HybridIterator& other) { + bool operator!=(const HybridIterator& other) const { return !(*this == other); } From a5a53e7f9b67bc6fd9e8df90f354a5502dace4df Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 24 Jun 2020 11:36:10 +0200 Subject: [PATCH 145/653] include guard updated --- container/HybridIterator.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/container/HybridIterator.h b/container/HybridIterator.h index 79f0485f..3dbd47a8 100644 --- a/container/HybridIterator.h +++ b/container/HybridIterator.h @@ -1,5 +1,5 @@ -#ifndef HYBRIDITERATOR_H_ -#define HYBRIDITERATOR_H_ +#ifndef FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ +#define FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ #include #include @@ -24,16 +24,16 @@ public: HybridIterator(typename ArrayList::Iterator start, typename ArrayList::Iterator end) : - ArrayList::Iterator(start), value(start.value), linked( - false), end(end.value) { + ArrayList::Iterator(start), value(start.value), + linked(false), end(end.value) { if (value == this->end) { value = NULL; } } HybridIterator(T *firstElement, T *lastElement) : - ArrayList::Iterator(firstElement), value(firstElement), linked( - false), end(++lastElement) { + ArrayList::Iterator(firstElement), value(firstElement), + linked(false), end(++lastElement) { if (value == end) { value = NULL; } @@ -42,17 +42,17 @@ public: HybridIterator& operator++() { if (linked) { LinkedElement::Iterator::operator++(); - if (LinkedElement::Iterator::value != NULL) { + if (LinkedElement::Iterator::value != nullptr) { value = LinkedElement::Iterator::value->value; } else { - value = NULL; + value = nullptr; } } else { ArrayList::Iterator::operator++(); value = ArrayList::Iterator::value; if (value == end) { - value = NULL; + value = nullptr; } } return *this; From f826ada774ed53d31899483b003162c10302527d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 24 Jun 2020 11:40:21 +0200 Subject: [PATCH 146/653] some more little changes for single linked list --- container/SinglyLinkedList.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/container/SinglyLinkedList.h b/container/SinglyLinkedList.h index 3c0078fc..a78a1467 100644 --- a/container/SinglyLinkedList.h +++ b/container/SinglyLinkedList.h @@ -88,14 +88,15 @@ public: ElementIterator begin() const { return ElementIterator::Iterator(start); } - typename ElementIterator::Iterator end() const { + + ElementIterator end() const { return ElementIterator::Iterator(); } - uint32_t getSize() const { - uint32_t size = 0; + size_t getSize() const { + size_t size = 0; LinkedElement *element = start; - while (element != NULL) { + while (element != nullptr) { size++; element = element->getNext(); } From 19cbac923f885f94f40876aa41e3f163874003e6 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 24 Jun 2020 12:06:08 +0200 Subject: [PATCH 147/653] typo fix --- osal/FreeRTOS/PeriodicTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osal/FreeRTOS/PeriodicTask.cpp b/osal/FreeRTOS/PeriodicTask.cpp index 170eb0a4..44a7b801 100644 --- a/osal/FreeRTOS/PeriodicTask.cpp +++ b/osal/FreeRTOS/PeriodicTask.cpp @@ -86,7 +86,7 @@ ReturnValue_t PeriodicTask::addComponent(object_id_t object, bool setTaskIF) { object); if (newObject == nullptr) { sif::error << "PeriodicTask::addComponent: Invalid object. Make sure" - "it implement ExecutableObjectIF" << std::endl; + "it implements ExecutableObjectIF!" << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } objectList.push_back(newObject); From 8a56964dab62de52a67563c5446fd7986100db06 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 24 Jun 2020 16:01:17 +0200 Subject: [PATCH 148/653] doc fix, various improvements --- tmtcservices/CommandingServiceBase.cpp | 140 +++++++++++++------------ tmtcservices/CommandingServiceBase.h | 53 ++++++---- 2 files changed, 102 insertions(+), 91 deletions(-) diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index 4c557f82..acf66389 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -80,39 +80,49 @@ void CommandingServiceBase::handleCommandQueue() { ReturnValue_t result = RETURN_FAILED; for (result = commandQueue->receiveMessage(&reply); result == RETURN_OK; result = commandQueue->receiveMessage(&reply)) { - handleCommandMessage(reply); + handleCommandMessage(&reply); } } -void CommandingServiceBase::handleCommandMessage(CommandMessage& reply) { +void CommandingServiceBase::handleCommandMessage(CommandMessage* reply) { bool isStep = false; CommandMessage nextCommand; - CommandMapIter iter; - if (reply.getSender() == MessageQueueIF::NO_QUEUE) { - handleUnrequestedReply(&reply); - return; - } - if ((iter = commandMap.find(reply.getSender())) == commandMap.end()) { - handleUnrequestedReply(&reply); + CommandMapIter iter = commandMap.find(reply->getSender()); + + // handle unrequested reply first + if (reply->getSender() == MessageQueueIF::NO_QUEUE or + iter == commandMap.end()) { + handleUnrequestedReply(reply); return; } nextCommand.setCommand(CommandMessage::CMD_NONE); + // Implemented by child class, specifies what to do with reply. - ReturnValue_t result = handleReply(&reply, iter->command, &iter->state, + ReturnValue_t result = handleReply(reply, iter->command, &iter->state, &nextCommand, iter->objectId, &isStep); + /* If the child implementation does not implement special handling for + * rejected replies (RETURN_FAILED is returned), a failure verification + * will be generated with the reason as the return code and the initial + * command as failure parameter 1 */ + if(reply->getCommand() == CommandMessage::REPLY_REJECTED and + result == RETURN_FAILED) { + result = reply->getReplyRejectedReason( + reinterpret_cast(&failureParameter1)); + } + switch (result) { case EXECUTION_COMPLETE: case RETURN_OK: case NO_STEP_MESSAGE: // handle result of reply handler implemented by developer. - handleReplyHandlerResult(result, iter, nextCommand, reply, isStep); + handleReplyHandlerResult(result, iter, &nextCommand, reply, isStep); break; case INVALID_REPLY: //might be just an unrequested reply at a bad moment - handleUnrequestedReply(&reply); + handleUnrequestedReply(reply); break; default: if (isStep) { @@ -129,24 +139,24 @@ void CommandingServiceBase::handleCommandMessage(CommandMessage& reply) { } failureParameter1 = 0; failureParameter2 = 0; - checkAndExecuteFifo(&iter); + checkAndExecuteFifo(iter); break; } } void CommandingServiceBase::handleReplyHandlerResult(ReturnValue_t result, - CommandMapIter iter, CommandMessage& nextCommand, CommandMessage& reply, - bool& isStep) { - iter->command = nextCommand.getCommand(); + CommandMapIter iter, CommandMessage* nextCommand, + CommandMessage* reply, bool& isStep) { + iter->command = nextCommand->getCommand(); // In case a new command is to be sent immediately, this is performed here. // If no new command is sent, only analyse reply result by initializing // sendResult as RETURN_OK ReturnValue_t sendResult = RETURN_OK; - if (nextCommand.getCommand() != CommandMessage::CMD_NONE) { - sendResult = commandQueue->sendMessage(reply.getSender(), - &nextCommand); + if (nextCommand->getCommand() != CommandMessage::CMD_NONE) { + sendResult = commandQueue->sendMessage(reply->getSender(), + nextCommand); } if (sendResult == RETURN_OK) { @@ -161,19 +171,19 @@ void CommandingServiceBase::handleReplyHandlerResult(ReturnValue_t result, TC_VERIFY::COMPLETION_SUCCESS, iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, iter->tcInfo.tcSequenceControl, 0); - checkAndExecuteFifo(&iter); + checkAndExecuteFifo(iter); } } else { if (isStep) { - nextCommand.clearCommandMessage(); + nextCommand->clear(); verificationReporter.sendFailureReport( TC_VERIFY::PROGRESS_FAILURE, iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, iter->tcInfo.tcSequenceControl, sendResult, ++iter->step, failureParameter1, failureParameter2); } else { - nextCommand.clearCommandMessage(); + nextCommand->clear(); verificationReporter.sendFailureReport( TC_VERIFY::COMPLETION_FAILURE, iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, @@ -182,7 +192,7 @@ void CommandingServiceBase::handleReplyHandlerResult(ReturnValue_t result, } failureParameter1 = 0; failureParameter2 = 0; - checkAndExecuteFifo(&iter); + checkAndExecuteFifo(iter); } } @@ -198,8 +208,8 @@ void CommandingServiceBase::handleRequestQueue() { address = message.getStorageId(); packet.setStoreAddress(address); - if ((packet.getSubService() == 0) - || (isValidSubservice(packet.getSubService()) != RETURN_OK)) { + if (packet.getSubService() == 0 + or isValidSubservice(packet.getSubService()) != RETURN_OK) { rejectPacket(TC_VERIFY::START_FAILURE, &packet, INVALID_SUBSERVICE); continue; } @@ -212,8 +222,7 @@ void CommandingServiceBase::handleRequestQueue() { } //Is a command already active for the target object? - typename FixedMap::Iterator iter; + CommandMapIter iter; iter = commandMap.find(queue); if (iter != commandMap.end()) { @@ -228,7 +237,7 @@ void CommandingServiceBase::handleRequestQueue() { if (result != RETURN_OK) { rejectPacket(TC_VERIFY::START_FAILURE, &packet, BUSY); } else { - startExecution(&packet, &iter); + startExecution(&packet, iter); } } @@ -281,46 +290,44 @@ ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice, } -void CommandingServiceBase::startExecution( - TcPacketStored *storedPacket, - typename FixedMap::Iterator *iter) { - ReturnValue_t result, sendResult = RETURN_OK; - CommandMessage message; - (*iter)->subservice = storedPacket->getSubService(); - result = prepareCommand(&message, (*iter)->subservice, - storedPacket->getApplicationData(), - storedPacket->getApplicationDataSize(), &(*iter)->state, - (*iter)->objectId); +void CommandingServiceBase::startExecution(TcPacketStored *storedPacket, + CommandMapIter iter) { + ReturnValue_t result = RETURN_OK; + CommandMessage command; + iter->subservice = storedPacket->getSubService(); + result = prepareCommand(&command, iter->subservice, + storedPacket->getApplicationData(), + storedPacket->getApplicationDataSize(), &iter->state, + iter->objectId); + ReturnValue_t sendResult = RETURN_OK; switch (result) { case RETURN_OK: - if (message.getCommand() != CommandMessage::CMD_NONE) { - sendResult = commandQueue->sendMessage((*iter).value->first, - &message); + if (command.getCommand() != CommandMessage::CMD_NONE) { + sendResult = commandQueue->sendMessage(iter.value->first, + &command); } if (sendResult == RETURN_OK) { - Clock::getUptime(&(*iter)->uptimeOfStart); - (*iter)->step = 0; -// (*iter)->state = 0; - (*iter)->subservice = storedPacket->getSubService(); - (*iter)->command = message.getCommand(); - (*iter)->tcInfo.ackFlags = storedPacket->getAcknowledgeFlags(); - (*iter)->tcInfo.tcPacketId = storedPacket->getPacketId(); - (*iter)->tcInfo.tcSequenceControl = + Clock::getUptime(&iter->uptimeOfStart); + iter->step = 0; + iter->subservice = storedPacket->getSubService(); + iter->command = command.getCommand(); + iter->tcInfo.ackFlags = storedPacket->getAcknowledgeFlags(); + iter->tcInfo.tcPacketId = storedPacket->getPacketId(); + iter->tcInfo.tcSequenceControl = storedPacket->getPacketSequenceControl(); acceptPacket(TC_VERIFY::START_SUCCESS, storedPacket); } else { - message.clearCommandMessage(); + command.clear(); rejectPacket(TC_VERIFY::START_FAILURE, storedPacket, sendResult); checkAndExecuteFifo(iter); } break; case EXECUTION_COMPLETE: - if (message.getCommand() != CommandMessage::CMD_NONE) { + if (command.getCommand() != CommandMessage::CMD_NONE) { //Fire-and-forget command. - sendResult = commandQueue->sendMessage((*iter).value->first, - &message); + sendResult = commandQueue->sendMessage(iter.value->first, + &command); } if (sendResult == RETURN_OK) { verificationReporter.sendSuccessReport(TC_VERIFY::START_SUCCESS, @@ -328,7 +335,7 @@ void CommandingServiceBase::startExecution( acceptPacket(TC_VERIFY::COMPLETION_SUCCESS, storedPacket); checkAndExecuteFifo(iter); } else { - message.clearCommandMessage(); + command.clear(); rejectPacket(TC_VERIFY::START_FAILURE, storedPacket, sendResult); checkAndExecuteFifo(iter); } @@ -355,12 +362,10 @@ void CommandingServiceBase::acceptPacket(uint8_t reportId, } -void CommandingServiceBase::checkAndExecuteFifo( - typename FixedMap::Iterator *iter) { +void CommandingServiceBase::checkAndExecuteFifo(CommandMapIter iter) { store_address_t address; - if ((*iter)->fifo.retrieve(&address) != RETURN_OK) { - commandMap.erase(iter); + if (iter->fifo.retrieve(&address) != RETURN_OK) { + commandMap.erase(&iter); } else { TcPacketStored newPacket(address); startExecution(&newPacket, iter); @@ -368,9 +373,8 @@ void CommandingServiceBase::checkAndExecuteFifo( } -void CommandingServiceBase::handleUnrequestedReply( - CommandMessage* reply) { - reply->clearCommandMessage(); +void CommandingServiceBase::handleUnrequestedReply(CommandMessage* reply) { + reply->clear(); } @@ -384,18 +388,18 @@ MessageQueueId_t CommandingServiceBase::getCommandQueue() { void CommandingServiceBase::checkTimeout() { uint32_t uptime; Clock::getUptime(&uptime); - typename FixedMap::Iterator iter; + CommandMapIter iter; for (iter = commandMap.begin(); iter != commandMap.end(); ++iter) { if ((iter->uptimeOfStart + (timeoutSeconds * 1000)) < uptime) { verificationReporter.sendFailureReport( TC_VERIFY::COMPLETION_FAILURE, iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, iter->tcInfo.tcSequenceControl, TIMEOUT); - checkAndExecuteFifo(&iter); + checkAndExecuteFifo(iter); } } } - - +void CommandingServiceBase::setTaskIF(PeriodicTaskIF* task_) { + executingTask = task_; +} diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index 9a68a2d3..277e5589 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -97,9 +97,7 @@ public: * Used to setup the reference of the task, that executes this component * @param task_ Pointer to the taskIF of this task */ - virtual void setTaskIF(PeriodicTaskIF* task_){ - executingTask = task_; - }; + virtual void setTaskIF(PeriodicTaskIF* task_); protected: /** @@ -141,15 +139,15 @@ protected: * @param objectId Target object ID * @return */ - virtual ReturnValue_t prepareCommand(CommandMessage *message, + virtual ReturnValue_t prepareCommand(CommandMessage* message, uint8_t subservice, const uint8_t *tcData, size_t tcDataLen, uint32_t *state, object_id_t objectId) = 0; /** * This function is implemented by child services to specify how replies - * to a command from another software component are handled + * to a command from another software component are handled. * @param reply - * This is the reply in form of a command message. + * This is the reply in form of a generic read-only command message. * @param previousCommand * Command_t of related command * @param state [out/in] @@ -163,19 +161,26 @@ protected: * - @c RETURN_OK, @c EXECUTION_COMPLETE or @c NO_STEP_MESSAGE to * generate TC verification success * - @c INVALID_REPLY calls handleUnrequestedReply - * - Anything else triggers a TC verification failure + * - Anything else triggers a TC verification failure. If RETURN_FAILED + * is returned and the command ID is CommandMessage::REPLY_REJECTED, + * a failure verification message with the reason as the error parameter + * and the initial command as failure parameter 1. */ - virtual ReturnValue_t handleReply(const CommandMessage *reply, + virtual ReturnValue_t handleReply(const CommandMessage* reply, Command_t previousCommand, uint32_t *state, - CommandMessage *optionalNextCommand, object_id_t objectId, + CommandMessage* optionalNextCommand, object_id_t objectId, bool *isStep) = 0; /** * This function can be overidden to handle unrequested reply, * when the reply sender ID is unknown or is not found is the command map. + * The default implementation will clear the command message and all + * its contents. * @param reply + * Reply which is non-const so the default implementation can clear the + * message. */ - virtual void handleUnrequestedReply(CommandMessage *reply); + virtual void handleUnrequestedReply(CommandMessage* reply); virtual void doPeriodicOperation(); @@ -195,6 +200,9 @@ protected: FIFO fifo; }; + using CommandMapIter = FixedMap::Iterator; + const uint16_t apid; const uint8_t service; @@ -263,21 +271,21 @@ protected: ReturnValue_t sendTmPacket(uint8_t subservice, SerializeIF* content, SerializeIF* header = nullptr); - void checkAndExecuteFifo( - typename FixedMap::Iterator *iter); + void checkAndExecuteFifo(CommandMapIter iter); private: - using CommandMapIter = FixedMap::Iterator; /** * This method handles internal execution of a command, - * once it has been started by @sa{startExecution()} in the Request Queue handler. - * 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. + * once it has been started by @sa{startExecution()} in the request + * queue handler. + * 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. Note that - * the static framework object ID @c VerificationReporter::messageReceiver needs to be set. + * 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 @@ -298,12 +306,11 @@ private: void acceptPacket(uint8_t reportId, TcPacketStored* packet); - void startExecution(TcPacketStored *storedPacket, - typename FixedMap::Iterator *iter); + void startExecution(TcPacketStored *storedPacket, CommandMapIter iter); - void handleCommandMessage(CommandMessage& reply); + void handleCommandMessage(CommandMessage* reply); void handleReplyHandlerResult(ReturnValue_t result, CommandMapIter iter, - CommandMessage& nextCommand,CommandMessage& reply, bool& isStep); + CommandMessage* nextCommand, CommandMessage* reply, bool& isStep); void checkTimeout(); }; From 644896245ff2eca019ebb0a5e9e0840f2b1dcc22 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 24 Jun 2020 16:03:54 +0200 Subject: [PATCH 149/653] better returnvalues for CSB init --- objectmanager/ObjectManagerIF.h | 3 ++- tmtcservices/CommandingServiceBase.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/objectmanager/ObjectManagerIF.h b/objectmanager/ObjectManagerIF.h index 90a1ce3b..dcef81cd 100644 --- a/objectmanager/ObjectManagerIF.h +++ b/objectmanager/ObjectManagerIF.h @@ -21,7 +21,8 @@ public: static constexpr uint8_t INTERFACE_ID = CLASS_ID::OBJECT_MANAGER_IF; static constexpr ReturnValue_t INSERTION_FAILED = MAKE_RETURN_CODE( 1 ); static constexpr ReturnValue_t NOT_FOUND = MAKE_RETURN_CODE( 2 ); - static constexpr ReturnValue_t CHILD_INIT_FAILED = MAKE_RETURN_CODE( 3 ); + + static constexpr ReturnValue_t CHILD_INIT_FAILED = MAKE_RETURN_CODE( 3 ); //!< Can be used if the initialization of a SystemObject failed. static constexpr ReturnValue_t INTERNAL_ERR_REPORTER_UNINIT = MAKE_RETURN_CODE( 4 ); protected: diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index acf66389..abf5b0ed 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -57,7 +57,7 @@ ReturnValue_t CommandingServiceBase::initialize() { PUSDistributorIF* distributor = objectManager->get( packetSource); if (packetForwarding == nullptr or distributor == nullptr) { - return RETURN_FAILED; + return ObjectManagerIF::CHILD_INIT_FAILED; } distributor->registerService(this); @@ -68,7 +68,7 @@ ReturnValue_t CommandingServiceBase::initialize() { TCStore = objectManager->get(objects::TC_STORE); if (IPCStore == nullptr or TCStore == nullptr) { - return RETURN_FAILED; + return ObjectManagerIF::CHILD_INIT_FAILED; } return RETURN_OK; From fc0d42e3e06e6d7c632f8a60ea0e5fe0e0972c7c Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 24 Jun 2020 16:07:02 +0200 Subject: [PATCH 150/653] error output for CSB init failure --- tmtcservices/CommandingServiceBase.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index abf5b0ed..f370cc6f 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -57,6 +57,8 @@ ReturnValue_t CommandingServiceBase::initialize() { PUSDistributorIF* distributor = objectManager->get( packetSource); if (packetForwarding == nullptr or distributor == nullptr) { + sif::error << "CommandingServiceBase::intialize: Packet source or " + "packet destination invalid!" << std::endl; return ObjectManagerIF::CHILD_INIT_FAILED; } @@ -68,6 +70,8 @@ ReturnValue_t CommandingServiceBase::initialize() { TCStore = objectManager->get(objects::TC_STORE); if (IPCStore == nullptr or TCStore == nullptr) { + sif::error << "CommandingServiceBase::intialize: IPC store or TC store " + "not initialized yet!" << std::endl; return ObjectManagerIF::CHILD_INIT_FAILED; } From ce3e4a1176afd5170fb9dce62c2737c88d7d9786 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 24 Jun 2020 16:24:16 +0200 Subject: [PATCH 151/653] added getter for reject reply --- ipc/CommandMessage.cpp | 11 +++++++++++ ipc/CommandMessage.h | 2 ++ tmtcservices/CommandingServiceBase.cpp | 12 ++++++------ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/ipc/CommandMessage.cpp b/ipc/CommandMessage.cpp index fa41c653..991c9df8 100644 --- a/ipc/CommandMessage.cpp +++ b/ipc/CommandMessage.cpp @@ -120,3 +120,14 @@ void CommandMessage::setReplyRejected(ReturnValue_t reason, setParameter(reason); setParameter2(initialCommand); } + +ReturnValue_t CommandMessage::getReplyRejectedReason( + Command_t *initialCommand) const { + ReturnValue_t reason = HasReturnvaluesIF::RETURN_FAILED; + std::memcpy(&reason, getData(), sizeof(reason)); + if(initialCommand != nullptr) { + std::memcpy(initialCommand, getData() + sizeof(reason), + sizeof(Command_t)); + } + return reason; +} diff --git a/ipc/CommandMessage.h b/ipc/CommandMessage.h index 2d966063..b800b9d2 100644 --- a/ipc/CommandMessage.h +++ b/ipc/CommandMessage.h @@ -124,6 +124,8 @@ public: */ void setToUnknownCommand(); void setReplyRejected(ReturnValue_t reason, Command_t initialCommand = CMD_NONE); + ReturnValue_t getReplyRejectedReason(Command_t *initialCommand) const; + size_t getMinimumMessageSize() const; }; diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index f370cc6f..e3ecada1 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -180,14 +180,14 @@ void CommandingServiceBase::handleReplyHandlerResult(ReturnValue_t result, } else { if (isStep) { - nextCommand->clear(); + nextCommand->clearCommandMessage(); verificationReporter.sendFailureReport( TC_VERIFY::PROGRESS_FAILURE, iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, iter->tcInfo.tcSequenceControl, sendResult, ++iter->step, failureParameter1, failureParameter2); } else { - nextCommand->clear(); + nextCommand->clearCommandMessage(); verificationReporter.sendFailureReport( TC_VERIFY::COMPLETION_FAILURE, iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, @@ -267,7 +267,7 @@ ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice, object_id_t objectId, const uint8_t *data, size_t dataLen) { uint8_t buffer[sizeof(object_id_t)]; uint8_t* pBuffer = buffer; - size_t size = 0; + uint32_t size = 0; SerializeAdapter::serialize(&objectId, &pBuffer, &size, sizeof(object_id_t), true); TmPacketStored tmPacketStored(this->apid, this->service, subservice, @@ -322,7 +322,7 @@ void CommandingServiceBase::startExecution(TcPacketStored *storedPacket, storedPacket->getPacketSequenceControl(); acceptPacket(TC_VERIFY::START_SUCCESS, storedPacket); } else { - command.clear(); + command.clearCommandMessage(); rejectPacket(TC_VERIFY::START_FAILURE, storedPacket, sendResult); checkAndExecuteFifo(iter); } @@ -339,7 +339,7 @@ void CommandingServiceBase::startExecution(TcPacketStored *storedPacket, acceptPacket(TC_VERIFY::COMPLETION_SUCCESS, storedPacket); checkAndExecuteFifo(iter); } else { - command.clear(); + command.clearCommandMessage(); rejectPacket(TC_VERIFY::START_FAILURE, storedPacket, sendResult); checkAndExecuteFifo(iter); } @@ -378,7 +378,7 @@ void CommandingServiceBase::checkAndExecuteFifo(CommandMapIter iter) { void CommandingServiceBase::handleUnrequestedReply(CommandMessage* reply) { - reply->clear(); + reply->clearCommandMessage(); } From 1ed5da3a122c98b01b9d59cac646bc9064cd33f5 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 24 Jun 2020 16:26:44 +0200 Subject: [PATCH 152/653] getter function bugfix --- ipc/CommandMessage.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ipc/CommandMessage.cpp b/ipc/CommandMessage.cpp index 991c9df8..679793e3 100644 --- a/ipc/CommandMessage.cpp +++ b/ipc/CommandMessage.cpp @@ -123,11 +123,9 @@ void CommandMessage::setReplyRejected(ReturnValue_t reason, ReturnValue_t CommandMessage::getReplyRejectedReason( Command_t *initialCommand) const { - ReturnValue_t reason = HasReturnvaluesIF::RETURN_FAILED; - std::memcpy(&reason, getData(), sizeof(reason)); + ReturnValue_t reason = getParameter(); if(initialCommand != nullptr) { - std::memcpy(initialCommand, getData() + sizeof(reason), - sizeof(Command_t)); + *initialCommand = getParameter2(); } return reason; } From d1b9ab51263e10f5486fe2e8f53afe8670a3087b Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 25 Jun 2020 17:17:24 +0200 Subject: [PATCH 153/653] added basic insertion operations --- container/SinglyLinkedList.h | 47 +++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/container/SinglyLinkedList.h b/container/SinglyLinkedList.h index a78a1467..618a21e1 100644 --- a/container/SinglyLinkedList.h +++ b/container/SinglyLinkedList.h @@ -58,7 +58,7 @@ public: this->next = next; } - virtual void setEnd() { + virtual void setLast() { this->next = nullptr; } @@ -89,10 +89,23 @@ public: return ElementIterator::Iterator(start); } + /** Returns iterator to nulltr */ ElementIterator end() const { return ElementIterator::Iterator(); } + /** + * Returns last element in singly linked list. + * @return + */ + ElementIterator back() const { + LinkedElement *element = start; + while (element != nullptr) { + element = element->getNext(); + } + return ElementIterator::Iterator(element); + } + size_t getSize() const { size_t size = 0; LinkedElement *element = start; @@ -102,15 +115,37 @@ public: } return size; } - void setStart(LinkedElement* setStart) { - start = setStart; + void setStart(LinkedElement* firstElement) { + start = firstElement; } - void setEnd(LinkedElement* setEnd) { - setEnd->setEnd(); + void setNext(LinkedElement* currentElement, + LinkedElement* nextElement) { + currentElement->setNext(nextElement); + } + + void setEnd(LinkedElement* lastElement) { + lastElement->setLast(); } - // SHOULDDO: Insertion operation ? + void insertElement(LinkedElement* element, size_t position) { + LinkedElement *currentElement = start; + for(size_t count = 0; count < position; count++) { + if(currentElement == nullptr) { + return; + } + currentElement = currentElement->getNext(); + } + LinkedElement* elementAfterCurrent = currentElement->next; + currentElement->setNext(element); + if(elementAfterCurrent != nullptr) { + element->setNext(elementAfterCurrent); + } + } + + void insertBack(LinkedElement* lastElement) { + back().value->setNext(lastElement); + } protected: LinkedElement *start = nullptr; From 053b47215786d38b0f604755e0b712300908296a Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 25 Jun 2020 18:09:32 +0200 Subject: [PATCH 154/653] Fixed spelling mistake in HealthHelper --- devicehandlers/ChildHandlerBase.cpp | 2 +- devicehandlers/DeviceHandlerBase.cpp | 2 +- devicehandlers/HealthDevice.cpp | 2 +- health/HealthHelper.cpp | 4 ++-- health/HealthHelper.h | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/devicehandlers/ChildHandlerBase.cpp b/devicehandlers/ChildHandlerBase.cpp index 50a5c07e..430b24e0 100644 --- a/devicehandlers/ChildHandlerBase.cpp +++ b/devicehandlers/ChildHandlerBase.cpp @@ -34,7 +34,7 @@ ReturnValue_t ChildHandlerBase::initialize() { parent->registerChild(getObjectId()); } - healthHelper.setParentQeueue(parentQueue); + healthHelper.setParentQueue(parentQueue); modeHelper.setParentQueue(parentQueue); diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 90875838..2e24e0d5 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -1072,7 +1072,7 @@ ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage( void DeviceHandlerBase::setParentQueue(MessageQueueId_t parentQueueId) { modeHelper.setParentQueue(parentQueueId); - healthHelper.setParentQeueue(parentQueueId); + healthHelper.setParentQueue(parentQueueId); } bool DeviceHandlerBase::isAwaitingReply() { diff --git a/devicehandlers/HealthDevice.cpp b/devicehandlers/HealthDevice.cpp index ea0b99ff..61a82421 100644 --- a/devicehandlers/HealthDevice.cpp +++ b/devicehandlers/HealthDevice.cpp @@ -38,7 +38,7 @@ MessageQueueId_t HealthDevice::getCommandQueue() const { } void HealthDevice::setParentQueue(MessageQueueId_t parentQueue) { - healthHelper.setParentQeueue(parentQueue); + healthHelper.setParentQueue(parentQueue); } bool HealthDevice::hasHealthChanged() { diff --git a/health/HealthHelper.cpp b/health/HealthHelper.cpp index ed97f3d3..7b8b3a53 100644 --- a/health/HealthHelper.cpp +++ b/health/HealthHelper.cpp @@ -29,11 +29,11 @@ HasHealthIF::HealthState HealthHelper::getHealth() { } ReturnValue_t HealthHelper::initialize(MessageQueueId_t parentQueue) { - setParentQeueue(parentQueue); + setParentQueue(parentQueue); return initialize(); } -void HealthHelper::setParentQeueue(MessageQueueId_t parentQueue) { +void HealthHelper::setParentQueue(MessageQueueId_t parentQueue) { this->parentQueue = parentQueue; } diff --git a/health/HealthHelper.h b/health/HealthHelper.h index a1ca2c52..471bc7e9 100644 --- a/health/HealthHelper.h +++ b/health/HealthHelper.h @@ -78,7 +78,7 @@ public: /** * @param parentQueue the Queue id of the parent object. Set to 0 if no parent present */ - void setParentQeueue(MessageQueueId_t parentQueue); + void setParentQueue(MessageQueueId_t parentQueue); /** * From bfd49caab4dd4432a575cc13738a818167d62c43 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 26 Jun 2020 12:52:03 +0200 Subject: [PATCH 155/653] fixed include guard comment --- container/HybridIterator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/HybridIterator.h b/container/HybridIterator.h index 3dbd47a8..f2fd6b28 100644 --- a/container/HybridIterator.h +++ b/container/HybridIterator.h @@ -87,4 +87,4 @@ private: T *end = nullptr; }; -#endif /* HYBRIDITERATOR_H_ */ +#endif /* FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ */ From 5400e38126d89730af33177f60963051659a985f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 29 Jun 2020 16:53:32 +0200 Subject: [PATCH 156/653] slight change --- tmtcservices/CommandingServiceBase.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index e3ecada1..d69a0f03 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -113,8 +113,8 @@ void CommandingServiceBase::handleCommandMessage(CommandMessage* reply) { * command as failure parameter 1 */ if(reply->getCommand() == CommandMessage::REPLY_REJECTED and result == RETURN_FAILED) { - result = reply->getReplyRejectedReason( - reinterpret_cast(&failureParameter1)); + result = reply->getReplyRejectedReason(); + failureParameter1 = iter->command; } switch (result) { From d311c499981bbd247466e1da6bf5f84999931bad Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 29 Jun 2020 16:57:00 +0200 Subject: [PATCH 157/653] setTaskIF implemented --- tmtcservices/PusServiceBase.cpp | 11 +++++++++++ tmtcservices/PusServiceBase.h | 17 +++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/tmtcservices/PusServiceBase.cpp b/tmtcservices/PusServiceBase.cpp index f5d1e30b..82e5ff5c 100644 --- a/tmtcservices/PusServiceBase.cpp +++ b/tmtcservices/PusServiceBase.cpp @@ -32,6 +32,10 @@ ReturnValue_t PusServiceBase::performOperation(uint8_t opCode) { return RETURN_OK; } +void PusServiceBase::setTaskIF(PeriodicTaskIF* taskHandle) { + this->taskHandle = taskHandle; +} + void PusServiceBase::handleRequestQueue() { TmTcMessage message; ReturnValue_t result = RETURN_FAILED; @@ -108,3 +112,10 @@ ReturnValue_t PusServiceBase::initialize() { return RETURN_FAILED; } } + +ReturnValue_t PusServiceBase::initializeAfterTaskCreation() { + // If task parameters, for example task frequency are required, this + // function should be overriden and the system object task IF can + // be used to get those parameters. + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/tmtcservices/PusServiceBase.h b/tmtcservices/PusServiceBase.h index 39600c41..6d3d9bac 100644 --- a/tmtcservices/PusServiceBase.h +++ b/tmtcservices/PusServiceBase.h @@ -96,11 +96,20 @@ public: * @return @c RETURN_OK if the periodic performService was successful. * @c RETURN_FAILED else. */ - ReturnValue_t performOperation(uint8_t opCode); - virtual uint16_t getIdentifier(); - MessageQueueId_t getRequestQueue(); - virtual ReturnValue_t initialize(); + ReturnValue_t performOperation(uint8_t opCode) override; + virtual uint16_t getIdentifier() override; + MessageQueueId_t getRequestQueue() override; + virtual ReturnValue_t initialize() override; + + virtual void setTaskIF(PeriodicTaskIF* taskHandle) override; + virtual ReturnValue_t initializeAfterTaskCreation() override; protected: + /** + * @brief Handle to the underlying task + * @details + * Will be set by setTaskIF(), which is called on task creation. + */ + PeriodicTaskIF* taskHandle = nullptr; /** * The APID of this instance of the Service. */ From 06b481b02f4a598dcea06572683608264c49a217 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Fri, 3 Jul 2020 12:44:08 +0200 Subject: [PATCH 158/653] Corrected filename of EndianConverter.h --- memory/MemoryHelper.cpp | 2 +- serialize/{EndianSwapper.h => EndianConverter.h} | 0 serialize/SerializeAdapter.h | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename serialize/{EndianSwapper.h => EndianConverter.h} (100%) diff --git a/memory/MemoryHelper.cpp b/memory/MemoryHelper.cpp index 132f4dc7..af56f2b8 100644 --- a/memory/MemoryHelper.cpp +++ b/memory/MemoryHelper.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include MemoryHelper::MemoryHelper(HasMemoryIF* workOnThis, MessageQueueIF* useThisQueue) : diff --git a/serialize/EndianSwapper.h b/serialize/EndianConverter.h similarity index 100% rename from serialize/EndianSwapper.h rename to serialize/EndianConverter.h diff --git a/serialize/SerializeAdapter.h b/serialize/SerializeAdapter.h index 73323c2a..ec727515 100644 --- a/serialize/SerializeAdapter.h +++ b/serialize/SerializeAdapter.h @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include From 89accf8940913213de1d5e067d42c1b2e09628e6 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Fri, 3 Jul 2020 15:46:00 +0200 Subject: [PATCH 159/653] Documented EndianConverter and changed length to size_t --- serialize/EndianConverter.h | 57 +++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/serialize/EndianConverter.h b/serialize/EndianConverter.h index e142c2a1..cd5d5497 100644 --- a/serialize/EndianConverter.h +++ b/serialize/EndianConverter.h @@ -5,12 +5,44 @@ #include #include +/** + * Helper class to convert variables or bitstreams between machine + * endian and either big or little endian. + * Machine endian is the endianness used by the machine running the + * program and is one of big or little endian. As this is portable + * code, it is not known at coding time which it is. At compile time + * it is however, which is why this is implemented using compiler + * macros and translates to a copy operation at runtime. + * + * This changes the layout of multi-byte variables in the machine's + * memory. In most cases, you should not need to use this class. + * Probably what you are looking for is the SerializeAdapter. + * If you still decide you need this class, please read and understand + * the code first. + * + * The order of the individual bytes of the multi-byte variable is + * reversed, the byte at the highest address is moved to the lowest + * address and vice versa, same for the bytes in between. + * + * Note that the conversion is also its inversion, that is converting + * from machine to a specified endianness is the same operation as + * converting from specified to machine (I looked it up, mathematicians + * would call it an involution): + * + * X == convertBigEndian(convertBigEndian(X)) + * + * Thus, there is only one function supplied to do the conversion. + */ class EndianConverter { private: EndianConverter() { } ; public: + /** + * Convert a typed variable between big endian and machine endian. + * Intended for plain old datatypes. + */ template static T convertBigEndian(T in) { #ifndef BYTE_ORDER_SYSTEM @@ -19,7 +51,7 @@ public: T tmp; uint8_t *pointerOut = (uint8_t*) &tmp; uint8_t *pointerIn = (uint8_t*) ∈ - for (uint8_t count = 0; count < sizeof(T); count++) { + for (size_t count = 0; count < sizeof(T); count++) { pointerOut[sizeof(T) - count - 1] = pointerIn[count]; } return tmp; @@ -29,12 +61,17 @@ public: #error Unknown Byte Order #endif } + + /** + * convert a bytestream representing a single variable between big endian + * and machine endian. + */ static void convertBigEndian(uint8_t *out, const uint8_t *in, - uint32_t size) { + size_t size) { #ifndef BYTE_ORDER_SYSTEM #error BYTE_ORDER_SYSTEM not defined #elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN - for (uint8_t count = 0; count < size; count++) { + for (size_t count = 0; count < size; count++) { out[size - count - 1] = in[count]; } return; @@ -44,6 +81,10 @@ public: #endif } + /** + * Convert a typed variable between little endian and machine endian. + * Intended for plain old datatypes. + */ template static T convertLittleEndian(T in) { #ifndef BYTE_ORDER_SYSTEM @@ -52,7 +93,7 @@ public: T tmp; uint8_t *pointerOut = (uint8_t *) &tmp; uint8_t *pointerIn = (uint8_t *) ∈ - for (uint8_t count = 0; count < sizeof(T); count++) { + for (size_t count = 0; count < sizeof(T); count++) { pointerOut[sizeof(T) - count - 1] = pointerIn[count]; } return tmp; @@ -62,12 +103,16 @@ public: #error Unknown Byte Order #endif } + /** + * convert a bytestream representing a single variable between little endian + * and machine endian. + */ static void convertLittleEndian(uint8_t *out, const uint8_t *in, - uint32_t size) { + size_t size) { #ifndef BYTE_ORDER_SYSTEM #error BYTE_ORDER_SYSTEM not defined #elif BYTE_ORDER_SYSTEM == BIG_ENDIAN - for (uint8_t count = 0; count < size; count++) { + for (size_t count = 0; count < size; count++) { out[size - count - 1] = in[count]; } return; From 45430e85861c9c14141d7f4841c69b34c051fce0 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Fri, 3 Jul 2020 15:47:05 +0200 Subject: [PATCH 160/653] Reworked PoolRawAccess to use EndianConverter instead of converting by itself --- datapool/PoolRawAccess.cpp | 116 ++++++++++++++++--------------------- datapool/PoolRawAccess.h | 18 +++--- 2 files changed, 59 insertions(+), 75 deletions(-) diff --git a/datapool/PoolRawAccess.cpp b/datapool/PoolRawAccess.cpp index 494aa567..e088e22f 100644 --- a/datapool/PoolRawAccess.cpp +++ b/datapool/PoolRawAccess.cpp @@ -2,12 +2,13 @@ #include #include #include -#include +#include PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry, - DataSetIF* data_set, ReadWriteMode_t setReadWriteMode) : - dataPoolId(set_id), arrayEntry(setArrayEntry), valid(false), type(Type::UNKNOWN_TYPE), typeSize( - 0), arraySize(0), sizeTillEnd(0), readWriteMode(setReadWriteMode) { + DataSetIF *data_set, ReadWriteMode_t 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); @@ -19,7 +20,7 @@ PoolRawAccess::~PoolRawAccess() { } ReturnValue_t PoolRawAccess::read() { - PoolEntryIF* read_out = ::dataPool.getRawData(dataPoolId); + PoolEntryIF *read_out = ::dataPool.getRawData(dataPoolId); if (read_out != NULL) { valid = read_out->getValid(); if (read_out->getSize() > arrayEntry) { @@ -29,7 +30,7 @@ ReturnValue_t PoolRawAccess::read() { if (typeSize <= sizeof(value)) { uint16_t arrayPosition = arrayEntry * typeSize; sizeTillEnd = read_out->getByteSize() - arrayPosition; - uint8_t* ptr = + uint8_t *ptr = &((uint8_t*) read_out->getRawData())[arrayPosition]; memcpy(value, ptr, typeSize); return HasReturnvaluesIF::RETURN_OK; @@ -42,8 +43,8 @@ ReturnValue_t PoolRawAccess::read() { } else { //Error entry does not exist. } - sif::error << "PoolRawAccess: read of DP Variable 0x" << std::hex << dataPoolId - << std::dec << " failed." << std::endl; + sif::error << "PoolRawAccess: read of DP Variable 0x" << std::hex + << dataPoolId << std::dec << " failed." << std::endl; valid = INVALID; typeSize = 0; sizeTillEnd = 0; @@ -52,11 +53,11 @@ ReturnValue_t PoolRawAccess::read() { } ReturnValue_t PoolRawAccess::commit() { - PoolEntryIF* write_back = ::dataPool.getRawData(dataPoolId); + PoolEntryIF *write_back = ::dataPool.getRawData(dataPoolId); if ((write_back != NULL) && (readWriteMode != VAR_READ)) { write_back->setValid(valid); uint8_t array_position = arrayEntry * typeSize; - uint8_t* ptr = &((uint8_t*) write_back->getRawData())[array_position]; + uint8_t *ptr = &((uint8_t*) write_back->getRawData())[array_position]; memcpy(ptr, value, typeSize); return HasReturnvaluesIF::RETURN_OK; } else { @@ -68,23 +69,17 @@ uint8_t* PoolRawAccess::getEntry() { return value; } -ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer, - uint32_t* writtenBytes, uint32_t maxSize) { - uint8_t* data_ptr = getEntry(); +ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t *buffer, + size_t *writtenBytes, size_t maxSize) { + uint8_t *data_ptr = getEntry(); // debug << "PoolRawAccess::getEntry: Array position: " << index * size_of_type << " Size of T: " << (int)size_of_type << " ByteSize: " << byte_size << " Position: " << *size << std::endl; - if (typeSize == 0) + if (typeSize == 0) { return DATA_POOL_ACCESS_FAILED; - if (typeSize > maxSize) - return INCORRECT_SIZE; -#ifndef BYTE_ORDER_SYSTEM -#error BYTE_ORDER_SYSTEM not defined -#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN - for (uint8_t count = 0; count < typeSize; count++) { - buffer[count] = data_ptr[typeSize - count - 1]; } -#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN - memcpy(buffer, data_ptr, typeSize); -#endif + if (typeSize > maxSize) { + return INCORRECT_SIZE; + } + EndianConverter::convertBigEndian(buffer, data_ptr, typeSize); *writtenBytes = typeSize; return HasReturnvaluesIF::RETURN_OK; } @@ -93,11 +88,11 @@ Type PoolRawAccess::getType() { return type; } -uint8_t PoolRawAccess::getSizeOfType() { +size_t PoolRawAccess::getSizeOfType() { return typeSize; } -uint8_t PoolRawAccess::getArraySize(){ +size_t PoolRawAccess::getArraySize() { return arraySize; } @@ -109,21 +104,14 @@ PoolVariableIF::ReadWriteMode_t PoolRawAccess::getReadWriteMode() const { return readWriteMode; } -ReturnValue_t PoolRawAccess::setEntryFromBigEndian(const uint8_t* buffer, - uint32_t setSize) { +ReturnValue_t PoolRawAccess::setEntryFromBigEndian(const uint8_t *buffer, + size_t setSize) { if (typeSize == setSize) { -#ifndef BYTE_ORDER_SYSTEM -#error BYTE_ORDER_SYSTEM not defined -#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN - for (uint8_t count = 0; count < typeSize; count++) { - value[count] = buffer[typeSize - count - 1]; - } -#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN - memcpy(value, buffer, typeSize); -#endif + EndianConverter::convertBigEndian(value, buffer, typeSize); return HasReturnvaluesIF::RETURN_OK; } else { - sif::error << "PoolRawAccess::setEntryFromBigEndian: Illegal sizes: Internal" + sif::error + << "PoolRawAccess::setEntryFromBigEndian: Illegal sizes: Internal" << (uint32_t) typeSize << ", Requested: " << setSize << std::endl; return INCORRECT_SIZE; @@ -141,27 +129,24 @@ void PoolRawAccess::setValid(uint8_t valid) { this->valid = valid; } -uint16_t PoolRawAccess::getSizeTillEnd() const { +size_t PoolRawAccess::getSizeTillEnd() const { return sizeTillEnd; } -ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, size_t* size, +ReturnValue_t PoolRawAccess::serialize(uint8_t **buffer, size_t *size, size_t maxSize, Endianness streamEndianness) const { - //TODO integer overflow if (typeSize + *size <= maxSize) { -#warning use endian swapper - if (1) { -#ifndef BYTE_ORDER_SYSTEM -#error BYTE_ORDER_SYSTEM not defined -#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN - for (uint8_t count = 0; count < typeSize; count++) { - (*buffer)[count] = value[typeSize - count - 1]; - } -#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN - memcpy(*buffer, value, typeSize); -#endif - } else { + switch (streamEndianness) { + case (Endianness::BIG): + EndianConverter::convertBigEndian(*buffer, value, typeSize); + break; + case (Endianness::LITTLE): + EndianConverter::convertLittleEndian(*buffer, value, typeSize); + break; + default: + case (Endianness::MACHINE): memcpy(*buffer, value, typeSize); + break; } *size += typeSize; (*buffer) += typeSize; @@ -175,24 +160,23 @@ size_t PoolRawAccess::getSerializedSize() const { return typeSize; } -ReturnValue_t PoolRawAccess::deSerialize(const uint8_t** buffer, size_t* size, +ReturnValue_t PoolRawAccess::deSerialize(const uint8_t **buffer, size_t *size, Endianness streamEndianness) { if (*size >= typeSize) { - *size -= typeSize; - if (1) { -#ifndef BYTE_ORDER_SYSTEM -#error BYTE_ORDER_SYSTEM not defined -#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN - for (uint8_t count = 0; count < typeSize; count++) { - value[count] = (*buffer)[typeSize - count - 1]; - } -#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN - memcpy(value, *buffer, typeSize); -#endif - } else { + switch (streamEndianness) { + case (Endianness::BIG): + EndianConverter::convertBigEndian(value, *buffer, typeSize); + break; + case (Endianness::LITTLE): + EndianConverter::convertLittleEndian(value, *buffer, typeSize); + break; + default: + case (Endianness::MACHINE): memcpy(value, *buffer, typeSize); + break; } + *size -= typeSize; *buffer += typeSize; return HasReturnvaluesIF::RETURN_OK; } else { diff --git a/datapool/PoolRawAccess.h b/datapool/PoolRawAccess.h index 8cc8f3f0..09d19afd 100644 --- a/datapool/PoolRawAccess.h +++ b/datapool/PoolRawAccess.h @@ -32,15 +32,15 @@ private: /** * \brief This value contains the size of the data pool entry in bytes. */ - uint8_t typeSize; + size_t typeSize; /** * The size of the DP array (single values return 1) */ - uint8_t arraySize; + size_t arraySize; /** * The size (in bytes) from the selected entry till the end of this DataPool variable. */ - uint16_t sizeTillEnd; + size_t sizeTillEnd; /** * \brief The information whether the class is read-write or read-only is stored here. */ @@ -97,8 +97,8 @@ public: * \return - \c RETURN_OK if entry could be acquired * - \c RETURN_FAILED else. */ - ReturnValue_t getEntryEndianSafe(uint8_t *buffer, uint32_t *size, - uint32_t maxSize); + ReturnValue_t getEntryEndianSafe(uint8_t *buffer, size_t *size, + size_t maxSize); /** * With this method, the content can be set from a big endian buffer safely. * @param buffer Pointer to the data to set @@ -107,7 +107,7 @@ public: * - \c RETURN_FAILED on failure */ ReturnValue_t setEntryFromBigEndian(const uint8_t *buffer, - uint32_t setSize); + size_t setSize); /** * \brief This operation returns the type of the entry currently stored. */ @@ -115,12 +115,12 @@ public: /** * \brief This operation returns the size of the entry currently stored. */ - uint8_t getSizeOfType(); + size_t getSizeOfType(); /** * * @return the size of the datapool array */ - uint8_t getArraySize(); + size_t getArraySize(); /** * \brief This operation returns the data pool id of the variable. */ @@ -138,7 +138,7 @@ public: /** * Getter for the remaining size. */ - uint16_t getSizeTillEnd() const; + size_t getSizeTillEnd() const; ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, Endianness streamEndianness) const override; From 6e799720868de42e59be07f850b78cc04fe1e422 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Fri, 3 Jul 2020 15:50:29 +0200 Subject: [PATCH 161/653] size_t for DataPoolAdmin --- datapool/DataPoolAdmin.cpp | 8 ++++---- datapool/DataPoolAdmin.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/datapool/DataPoolAdmin.cpp b/datapool/DataPoolAdmin.cpp index 3ac3ef6a..3ea266ea 100644 --- a/datapool/DataPoolAdmin.cpp +++ b/datapool/DataPoolAdmin.cpp @@ -26,7 +26,7 @@ MessageQueueId_t DataPoolAdmin::getCommandQueue() const { } ReturnValue_t DataPoolAdmin::executeAction(ActionId_t actionId, - MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size) { + MessageQueueId_t commandedBy, const uint8_t* data, size_t size) { if (actionId != SET_VALIDITY) { return INVALID_ACTION_ID; } @@ -91,7 +91,7 @@ void DataPoolAdmin::handleCommand() { } ReturnValue_t DataPoolAdmin::handleMemoryLoad(uint32_t address, - const uint8_t* data, uint32_t size, uint8_t** dataPointer) { + const uint8_t* data, size_t size, uint8_t** dataPointer) { uint32_t poolId = ::dataPool.PIDToDataPoolId(address); uint8_t arrayIndex = ::dataPool.PIDToArrayIndex(address); DataSet testSet; @@ -129,7 +129,7 @@ ReturnValue_t DataPoolAdmin::handleMemoryLoad(uint32_t address, return ACTIVITY_COMPLETED; } -ReturnValue_t DataPoolAdmin::handleMemoryDump(uint32_t address, uint32_t size, +ReturnValue_t DataPoolAdmin::handleMemoryDump(uint32_t address, size_t size, uint8_t** dataPointer, uint8_t* copyHere) { uint32_t poolId = ::dataPool.PIDToDataPoolId(address); uint8_t arrayIndex = ::dataPool.PIDToArrayIndex(address); @@ -151,7 +151,7 @@ ReturnValue_t DataPoolAdmin::handleMemoryDump(uint32_t address, uint32_t size, PoolVariableIF::VAR_READ); status = rawSet.read(); if (status == RETURN_OK) { - uint32_t temp = 0; + size_t temp = 0; status = variable.getEntryEndianSafe(ptrToCopy, &temp, size); if (status != RETURN_OK) { return RETURN_FAILED; diff --git a/datapool/DataPoolAdmin.h b/datapool/DataPoolAdmin.h index 448d78fb..1be920b5 100644 --- a/datapool/DataPoolAdmin.h +++ b/datapool/DataPoolAdmin.h @@ -29,12 +29,12 @@ public: 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, + size_t size, uint8_t** dataPointer); + ReturnValue_t handleMemoryDump(uint32_t address, size_t size, uint8_t** dataPointer, uint8_t* copyHere); ReturnValue_t executeAction(ActionId_t actionId, - MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size); + MessageQueueId_t commandedBy, const uint8_t* data, size_t size); //not implemented as ParameterHelper is no used ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, From 6a0a2675b1bba3f69e81224d935ac93166306c97 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 6 Jul 2020 12:36:01 +0200 Subject: [PATCH 162/653] typedef instead of auto used now --- osal/FreeRTOS/FixedTimeslotTask.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index 223cf4bd..c062101d 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -82,10 +82,10 @@ ReturnValue_t FixedTimeslotTask::checkSequence() const { void FixedTimeslotTask::taskFunctionality() { // A local iterator for the Polling Sequence Table is created to find the // start time for the first entry. - auto slotListIter = pst.current; + FixedSlotSequence::SlotListIter slotListIter = pst.current; //The start time for the first entry is read. - uint32_t intervalMs = (*slotListIter)->pollingTimeMs; + uint32_t intervalMs = slotListIter->pollingTimeMs; TickType_t interval = pdMS_TO_TICKS(intervalMs); TickType_t xLastWakeTime; From ec212d9fcf45410507110d5b87f00af71846d037 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 6 Jul 2020 13:26:58 +0200 Subject: [PATCH 163/653] new fifo init --- container/FIFO.h | 88 ++++++++---------------------------------- container/FIFOBase.h | 59 ++++++++++++++++++++++++++++ container/FIFOBase.tpp | 76 ++++++++++++++++++++++++++++++++++++ container/StaticFIFO.h | 23 +++++++++++ 4 files changed, 174 insertions(+), 72 deletions(-) create mode 100644 container/FIFOBase.h create mode 100644 container/FIFOBase.tpp create mode 100644 container/StaticFIFO.h diff --git a/container/FIFO.h b/container/FIFO.h index f70c78b0..217ddbca 100644 --- a/container/FIFO.h +++ b/container/FIFO.h @@ -1,82 +1,26 @@ -#ifndef FIFO_H_ -#define FIFO_H_ +#ifndef FRAMEWORK_CONTAINER_FIFO_H_ +#define FRAMEWORK_CONTAINER_FIFO_H_ -#include +#include +#include /** - * @brief Simple First-In-First-Out data structure + * @brief Simple First-In-First-Out data structure. The maximum size + * can be set in the constructor. THe public interface of + * FIFOBase exposes the user interface for the FIFO. * @tparam T Entry Type * @tparam capacity Maximum capacity */ -template -class FIFO { -private: - uint8_t readIndex, writeIndex, currentSize; - T data[capacity]; - - uint8_t next(uint8_t current) { - ++current; - if (current == capacity) { - current = 0; - } - return current; - } +template +class FIFO: public FIFOBase { public: - FIFO() : - readIndex(0), writeIndex(0), currentSize(0) { - } + FIFO(size_t maxCapacity): FIFOBase(values.data(), maxCapacity) { + values.reserve(maxCapacity); + values.resize(maxCapacity); + }; - bool empty() { - return (currentSize == 0); - } - - bool full() { - return (currentSize == capacity); - } - - uint8_t size(){ - return currentSize; - } - - ReturnValue_t insert(T value) { - if (full()) { - return FULL; - } else { - data[writeIndex] = value; - writeIndex = next(writeIndex); - ++currentSize; - return HasReturnvaluesIF::RETURN_OK; - } - } - - ReturnValue_t retrieve(T *value) { - if (empty()) { - return EMPTY; - } else { - *value = data[readIndex]; - readIndex = next(readIndex); - --currentSize; - return HasReturnvaluesIF::RETURN_OK; - } - } - - ReturnValue_t peek(T * value) { - if(empty()) { - return EMPTY; - } else { - *value = data[readIndex]; - return HasReturnvaluesIF::RETURN_OK; - } - } - - ReturnValue_t pop() { - T value; - return this->retrieve(&value); - } - - 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); +private: + std::vector values; }; -#endif /* FIFO_H_ */ +#endif /* FRAMEWORK_CONTAINER_FIFO_H_ */ diff --git a/container/FIFOBase.h b/container/FIFOBase.h new file mode 100644 index 00000000..c6a74d2f --- /dev/null +++ b/container/FIFOBase.h @@ -0,0 +1,59 @@ +#ifndef FRAMEWORK_CONTAINER_FIFOBASE_H_ +#define FRAMEWORK_CONTAINER_FIFOBASE_H_ + +#include +#include + +template +class FIFOBase { +public: + 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); + + + /** Default ctor, no input arguments required. */ + FIFOBase(T* values, const size_t maxCapacity); + + /** + * Insert value into FIFO + * @param value + * @return + */ + ReturnValue_t insert(T value); + /** + * Retrieve item from FIFO. This removes the item from the FIFO. + * @param value + * @return + */ + ReturnValue_t retrieve(T *value); + /** + * Retrieve item from FIFO without removing it from FIFO. + * @param value + * @return + */ + ReturnValue_t peek(T * value); + /** + * Remove item from FIFO. + * @return + */ + ReturnValue_t pop(); + + bool empty(); + bool full(); + size_t size(); + +private: + T* values; + size_t maxCapacity; + + size_t readIndex = 0; + size_t writeIndex = 0; + size_t currentSize = 0; + + size_t next(size_t current); +}; + +#include + +#endif /* FRAMEWORK_CONTAINER_FIFOBASE_H_ */ diff --git a/container/FIFOBase.tpp b/container/FIFOBase.tpp new file mode 100644 index 00000000..011ce6de --- /dev/null +++ b/container/FIFOBase.tpp @@ -0,0 +1,76 @@ +#ifndef FRAMEWORK_CONTAINER_FIFOBASE_TPP_ +#define FRAMEWORK_CONTAINER_FIFOBASE_TPP_ + +#ifndef FRAMEWORK_CONTAINER_FIFOBASE_H_ +#error Include FIFOBase.h before FIFOBase.tpp! +#endif + +template +inline FIFOBase::FIFOBase(T* values, const size_t maxCapacity): + values(values), maxCapacity(maxCapacity) {}; + +template +inline ReturnValue_t FIFOBase::insert(T value) { + if (full()) { + return FULL; + } else { + values[writeIndex] = value; + writeIndex = next(writeIndex); + ++currentSize; + return HasReturnvaluesIF::RETURN_OK; + } +}; + +template +inline ReturnValue_t FIFOBase::retrieve(T* value) { + if (empty()) { + return EMPTY; + } else { + *value = values[readIndex]; + readIndex = next(readIndex); + --currentSize; + return HasReturnvaluesIF::RETURN_OK; + } +}; + +template +inline ReturnValue_t FIFOBase::peek(T* value) { + if(empty()) { + return EMPTY; + } else { + *value = values[readIndex]; + return HasReturnvaluesIF::RETURN_OK; + } +}; + +template +inline ReturnValue_t FIFOBase::pop() { + T value; + return this->retrieve(&value); +}; + +template +inline bool FIFOBase::empty() { + return (currentSize == 0); +}; + +template +inline bool FIFOBase::full() { + return (currentSize == maxCapacity); +} + +template +inline size_t FIFOBase::size() { + return currentSize; +} + +template +inline size_t FIFOBase::next(size_t current) { + ++current; + if (current == maxCapacity) { + current = 0; + } + return current; +} + +#endif diff --git a/container/StaticFIFO.h b/container/StaticFIFO.h new file mode 100644 index 00000000..651c4989 --- /dev/null +++ b/container/StaticFIFO.h @@ -0,0 +1,23 @@ +#ifndef FRAMEWORK_CONTAINER_STATICFIFO_H_ +#define FRAMEWORK_CONTAINER_STATICFIFO_H_ + +#include +#include + +/** + * @brief Simple First-In-First-Out data structure with size fixed at + * compile time. The public interface of FIFOBase exposes + * the user interface for the FIFO. + * @tparam T Entry Type + * @tparam capacity Maximum capacity + */ +template +class StaticFIFO: public FIFOBase { +public: + StaticFIFO(): FIFOBase(values.data(), capacity) {}; + +private: + std::array values; +}; + +#endif /* FRAMEWORK_CONTAINERS_STATICFIFO_H_ */ From 991385de6576583e4a45aa8c059c23f964094434 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 6 Jul 2020 13:29:56 +0200 Subject: [PATCH 164/653] added missing include, CSB uses static fifo now --- container/StaticFIFO.h | 1 + tmtcservices/CommandingServiceBase.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/container/StaticFIFO.h b/container/StaticFIFO.h index 651c4989..780b0383 100644 --- a/container/StaticFIFO.h +++ b/container/StaticFIFO.h @@ -3,6 +3,7 @@ #include #include +#include /** * @brief Simple First-In-First-Out data structure with size fixed at diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index bf2e8242..b3132be5 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -2,7 +2,7 @@ #define COMMANDINGSERVICEBASE_H_ #include -#include +#include #include #include #include @@ -179,7 +179,7 @@ protected: uint32_t state; Command_t command; object_id_t objectId; - FIFO fifo; + StaticFIFO fifo; }; const uint16_t apid; From b699c8b2b3be6446502c107f893c8b53201f5bc9 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 6 Jul 2020 13:38:11 +0200 Subject: [PATCH 165/653] put FIFO in namespace, fixed doc --- container/FIFO.h | 4 ++++ container/FIFOBase.h | 8 ++++++-- container/StaticFIFO.h | 10 ++++++++-- tmtcservices/CommandingServiceBase.h | 2 +- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/container/FIFO.h b/container/FIFO.h index 217ddbca..801df6a2 100644 --- a/container/FIFO.h +++ b/container/FIFO.h @@ -4,6 +4,8 @@ #include #include +namespace fifo { + /** * @brief Simple First-In-First-Out data structure. The maximum size * can be set in the constructor. THe public interface of @@ -23,4 +25,6 @@ private: std::vector values; }; +} + #endif /* FRAMEWORK_CONTAINER_FIFO_H_ */ diff --git a/container/FIFOBase.h b/container/FIFOBase.h index c6a74d2f..ac5c6e2c 100644 --- a/container/FIFOBase.h +++ b/container/FIFOBase.h @@ -4,6 +4,8 @@ #include #include +namespace fsfw { + template class FIFOBase { public: @@ -11,8 +13,8 @@ public: static const ReturnValue_t FULL = MAKE_RETURN_CODE(1); static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(2); - - /** Default ctor, no input arguments required. */ + /** Default ctor, takes pointer to first entry of underlying container + * and maximum capacity */ FIFOBase(T* values, const size_t maxCapacity); /** @@ -56,4 +58,6 @@ private: #include +} + #endif /* FRAMEWORK_CONTAINER_FIFOBASE_H_ */ diff --git a/container/StaticFIFO.h b/container/StaticFIFO.h index 780b0383..f3128200 100644 --- a/container/StaticFIFO.h +++ b/container/StaticFIFO.h @@ -5,10 +5,14 @@ #include #include +namespace fsfw { + /** * @brief Simple First-In-First-Out data structure with size fixed at - * compile time. The public interface of FIFOBase exposes - * the user interface for the FIFO. + * compile time + * @details + * Performs no dynamic memory allocation. + * The public interface of FIFOBase exposes the user interface for the FIFO. * @tparam T Entry Type * @tparam capacity Maximum capacity */ @@ -21,4 +25,6 @@ private: std::array values; }; +} + #endif /* FRAMEWORK_CONTAINERS_STATICFIFO_H_ */ diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index b3132be5..a4343065 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -179,7 +179,7 @@ protected: uint32_t state; Command_t command; object_id_t objectId; - StaticFIFO fifo; + fsfw::StaticFIFO fifo; }; const uint16_t apid; From 8f6c3b50af92e9e5619a79e48414a8e252e29577 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 6 Jul 2020 13:40:13 +0200 Subject: [PATCH 166/653] namespace fix --- container/FIFO.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/container/FIFO.h b/container/FIFO.h index 801df6a2..7251321f 100644 --- a/container/FIFO.h +++ b/container/FIFO.h @@ -4,12 +4,15 @@ #include #include -namespace fifo { +namespace fsfw { /** * @brief Simple First-In-First-Out data structure. The maximum size - * can be set in the constructor. THe public interface of - * FIFOBase exposes the user interface for the FIFO. + * can be set in the constructor. + * @details + * The maximum capacity can be determined at run-time, so this container + * performs dynamic memory allocation! + * The public interface of FIFOBase exposes the user interface for the FIFO. * @tparam T Entry Type * @tparam capacity Maximum capacity */ From 2fccc4fef77537a62f39297f1c5bf39fbc9ea08f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 6 Jul 2020 23:08:31 +0200 Subject: [PATCH 167/653] getter function for capacity --- container/FIFO.h | 6 ++---- container/FIFOBase.h | 4 +++- container/FIFOBase.tpp | 5 +++++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/container/FIFO.h b/container/FIFO.h index 7251321f..19daaf1b 100644 --- a/container/FIFO.h +++ b/container/FIFO.h @@ -19,10 +19,8 @@ namespace fsfw { template class FIFO: public FIFOBase { public: - FIFO(size_t maxCapacity): FIFOBase(values.data(), maxCapacity) { - values.reserve(maxCapacity); - values.resize(maxCapacity); - }; + FIFO(size_t maxCapacity): FIFOBase(values.data(), maxCapacity), + values(maxCapacity) {}; private: std::vector values; diff --git a/container/FIFOBase.h b/container/FIFOBase.h index ac5c6e2c..6ed7d924 100644 --- a/container/FIFOBase.h +++ b/container/FIFOBase.h @@ -45,9 +45,11 @@ public: bool full(); size_t size(); + size_t getMaxCapacity() const; + private: T* values; - size_t maxCapacity; + size_t maxCapacity = 0; size_t readIndex = 0; size_t writeIndex = 0; diff --git a/container/FIFOBase.tpp b/container/FIFOBase.tpp index 011ce6de..48a060ff 100644 --- a/container/FIFOBase.tpp +++ b/container/FIFOBase.tpp @@ -73,4 +73,9 @@ inline size_t FIFOBase::next(size_t current) { return current; } +template +inline size_t FIFOBase::getMaxCapacity() const { + return maxCapacity; +} + #endif From 986bb154be701a7ce989ac4edd6a8a4f4a6965de Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 7 Jul 2020 13:24:04 +0200 Subject: [PATCH 168/653] hotfix: arrayprinter was renamed --- datapool/PoolEntry.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/datapool/PoolEntry.cpp b/datapool/PoolEntry.cpp index a87a6c4e..d535a72b 100644 --- a/datapool/PoolEntry.cpp +++ b/datapool/PoolEntry.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include template @@ -68,7 +68,7 @@ template void PoolEntry::print() { sif::debug << "Pool Entry Validity: " << (this->valid? " (valid) " : " (invalid) ") << std::endl; - printer::print(reinterpret_cast(address), length); + arrayprinter::print(reinterpret_cast(address), length); sif::debug << std::dec << std::endl; } From 5f76b03f3ab29b5f401124ad2a0a137a6828d285 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 7 Jul 2020 17:44:15 +0200 Subject: [PATCH 169/653] fifo tweaks --- container/DynamicFIFO.h | 27 +++++++++++++++++++++++++++ container/FIFO.h | 23 +++++++++-------------- container/FIFOBase.h | 4 ---- container/StaticFIFO.h | 30 ------------------------------ 4 files changed, 36 insertions(+), 48 deletions(-) create mode 100644 container/DynamicFIFO.h delete mode 100644 container/StaticFIFO.h diff --git a/container/DynamicFIFO.h b/container/DynamicFIFO.h new file mode 100644 index 00000000..3a5242c7 --- /dev/null +++ b/container/DynamicFIFO.h @@ -0,0 +1,27 @@ +#ifndef FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ +#define FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ + +#include +#include + +/** + * @brief Simple First-In-First-Out data structure. The maximum size + * can be set in the constructor. + * @details + * The maximum capacity can be determined at run-time, so this container + * performs dynamic memory allocation! + * The public interface of FIFOBase exposes the user interface for the FIFO. + * @tparam T Entry Type + * @tparam capacity Maximum capacity + */ +template +class DynamicFIFO: public FIFOBase { +public: + DynamicFIFO(size_t maxCapacity): FIFOBase(values.data(), maxCapacity), + values(maxCapacity) {}; + +private: + std::vector values; +}; + +#endif /* FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ */ diff --git a/container/FIFO.h b/container/FIFO.h index 19daaf1b..ecb218fd 100644 --- a/container/FIFO.h +++ b/container/FIFO.h @@ -1,31 +1,26 @@ #ifndef FRAMEWORK_CONTAINER_FIFO_H_ #define FRAMEWORK_CONTAINER_FIFO_H_ +#include #include -#include - -namespace fsfw { +#include /** - * @brief Simple First-In-First-Out data structure. The maximum size - * can be set in the constructor. + * @brief Simple First-In-First-Out data structure with size fixed at + * compile time * @details - * The maximum capacity can be determined at run-time, so this container - * performs dynamic memory allocation! + * Performs no dynamic memory allocation. * The public interface of FIFOBase exposes the user interface for the FIFO. * @tparam T Entry Type * @tparam capacity Maximum capacity */ -template +template class FIFO: public FIFOBase { public: - FIFO(size_t maxCapacity): FIFOBase(values.data(), maxCapacity), - values(maxCapacity) {}; + FIFO(): FIFOBase(values.data(), capacity) {}; private: - std::vector values; + std::array values; }; -} - -#endif /* FRAMEWORK_CONTAINER_FIFO_H_ */ +#endif /* FRAMEWORK_CONTAINERS_STATICFIFO_H_ */ diff --git a/container/FIFOBase.h b/container/FIFOBase.h index 6ed7d924..8bdb333f 100644 --- a/container/FIFOBase.h +++ b/container/FIFOBase.h @@ -4,8 +4,6 @@ #include #include -namespace fsfw { - template class FIFOBase { public: @@ -60,6 +58,4 @@ private: #include -} - #endif /* FRAMEWORK_CONTAINER_FIFOBASE_H_ */ diff --git a/container/StaticFIFO.h b/container/StaticFIFO.h deleted file mode 100644 index f3128200..00000000 --- a/container/StaticFIFO.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef FRAMEWORK_CONTAINER_STATICFIFO_H_ -#define FRAMEWORK_CONTAINER_STATICFIFO_H_ - -#include -#include -#include - -namespace fsfw { - -/** - * @brief Simple First-In-First-Out data structure with size fixed at - * compile time - * @details - * Performs no dynamic memory allocation. - * The public interface of FIFOBase exposes the user interface for the FIFO. - * @tparam T Entry Type - * @tparam capacity Maximum capacity - */ -template -class StaticFIFO: public FIFOBase { -public: - StaticFIFO(): FIFOBase(values.data(), capacity) {}; - -private: - std::array values; -}; - -} - -#endif /* FRAMEWORK_CONTAINERS_STATICFIFO_H_ */ From d795892d578772cc04ac159a228f9501ab39d8db Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 7 Jul 2020 17:54:09 +0200 Subject: [PATCH 170/653] csb fifo tweak --- tmtcservices/CommandingServiceBase.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index a4343065..e7702860 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -1,8 +1,8 @@ -#ifndef COMMANDINGSERVICEBASE_H_ -#define COMMANDINGSERVICEBASE_H_ +#ifndef FRAMEWORK_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ +#define FRAMEWORK_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ #include -#include +#include #include #include #include @@ -179,7 +179,7 @@ protected: uint32_t state; Command_t command; object_id_t objectId; - fsfw::StaticFIFO fifo; + FIFO fifo; }; const uint16_t apid; @@ -286,4 +286,4 @@ private: void checkTimeout(); }; -#endif /* COMMANDINGSERVICEBASE_H_ */ +#endif /* FRAMEWORK_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ */ From 65d71b1c65b2841a94d0fa1cb95b849afa2cff47 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 7 Jul 2020 18:11:36 +0200 Subject: [PATCH 171/653] added new ctor, non-allocating --- container/SimpleRingBuffer.cpp | 18 +++++++---- container/SimpleRingBuffer.h | 57 +++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/container/SimpleRingBuffer.cpp b/container/SimpleRingBuffer.cpp index 63dc3514..731c9dc9 100644 --- a/container/SimpleRingBuffer.cpp +++ b/container/SimpleRingBuffer.cpp @@ -1,18 +1,23 @@ #include -#include +#include -SimpleRingBuffer::SimpleRingBuffer(uint32_t size, bool overwriteOld) : - RingBufferBase<>(0, size, overwriteOld), buffer(NULL) { +SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld) : + RingBufferBase<>(0, size, overwriteOld) { buffer = new uint8_t[size]; } +SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size, + bool overwriteOld): + RingBufferBase<>(0, size, overwriteOld), buffer(buffer) {} + + SimpleRingBuffer::~SimpleRingBuffer() { delete[] buffer; } ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, uint32_t amount) { - if (availableWriteSpace() >= amount || overwriteOld) { + if (availableWriteSpace() >= amount or overwriteOld) { uint32_t amountTillWrap = writeTillWrap(); if (amountTillWrap >= amount) { memcpy(&buffer[write], data, amount); @@ -38,7 +43,7 @@ ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, uint32_t amount, return HasReturnvaluesIF::RETURN_FAILED; } } - if (trueAmount != NULL) { + if (trueAmount != nullptr) { *trueAmount = amount; } if (amountTillWrap >= amount) { @@ -60,9 +65,10 @@ ReturnValue_t SimpleRingBuffer::deleteData(uint32_t amount, return HasReturnvaluesIF::RETURN_FAILED; } } - if (trueAmount != NULL) { + if (trueAmount != nullptr) { *trueAmount = amount; } incrementRead(amount, READ_PTR); return HasReturnvaluesIF::RETURN_OK; } + diff --git a/container/SimpleRingBuffer.h b/container/SimpleRingBuffer.h index 6d7d67e1..30dd184c 100644 --- a/container/SimpleRingBuffer.h +++ b/container/SimpleRingBuffer.h @@ -2,19 +2,66 @@ #define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ #include -#include +#include +/** + * @brief Circular buffer implementation, useful for buffering + * into data streams. + * @details + * Note that the deleteData() has to be called to increment the read pointer. + * This class allocated dynamically, so + * @ingroup containers + */ class SimpleRingBuffer: public RingBufferBase<> { public: - SimpleRingBuffer(uint32_t size, bool overwriteOld); + /** + * This constructor allocates a new internal buffer with the supplied size. + * @param size + * @param overwriteOld + */ + SimpleRingBuffer(const size_t size, bool overwriteOld); + /** + * This constructor takes an external buffer with the specified size. + * @param buffer + * @param size + * @param overwriteOld + */ + SimpleRingBuffer(uint8_t* buffer, const size_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); - 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); + + /** + * 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 = nullptr); + + /** + * 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 = nullptr); private: // static const uint8_t TEMP_READ_PTR = 1; static const uint8_t READ_PTR = 0; - uint8_t* buffer; + uint8_t* buffer = nullptr; }; #endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */ From 133ed9586b2ecceccdf92316f25d7cbf2c551c0d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 9 Jul 2020 19:31:28 +0200 Subject: [PATCH 172/653] tmtc bridge improvements --- tmtcservices/TmTcBridge.cpp | 58 +++++++++++++++++++++++-------------- tmtcservices/TmTcBridge.h | 53 +++++++++++++++++---------------- 2 files changed, 63 insertions(+), 48 deletions(-) diff --git a/tmtcservices/TmTcBridge.cpp b/tmtcservices/TmTcBridge.cpp index f9a7d3bc..8c44f7de 100644 --- a/tmtcservices/TmTcBridge.cpp +++ b/tmtcservices/TmTcBridge.cpp @@ -5,11 +5,13 @@ #include #include -TmTcBridge::TmTcBridge(object_id_t objectId_, - object_id_t ccsdsPacketDistributor_): SystemObject(objectId_), - ccsdsPacketDistributor(ccsdsPacketDistributor_) +TmTcBridge::TmTcBridge(object_id_t objectId, object_id_t tcDestination, + object_id_t tmStoreId, object_id_t tcStoreId): + SystemObject(objectId),tmStoreId(tmStoreId), tcStoreId(tcStoreId), + tcDestination(tcDestination) + { - TmTcReceptionQueue = QueueFactory::instance()-> + tmTcReceptionQueue = QueueFactory::instance()-> createMessageQueue(TMTC_RECEPTION_QUEUE_DEPTH); } @@ -42,20 +44,27 @@ ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored( } ReturnValue_t TmTcBridge::initialize() { - tcStore = objectManager->get(objects::TC_STORE); - if (tcStore == NULL) { - return RETURN_FAILED; + tcStore = objectManager->get(tcStoreId); + if (tcStore == nullptr) { + sif::error << "TmTcBridge::initialize: TC store invalid. Make sure" + "it is created and set up properly." << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; } - tmStore = objectManager->get(objects::TM_STORE); - if (tmStore == NULL) { - return RETURN_FAILED; + tmStore = objectManager->get(tmStoreId); + if (tmStore == nullptr) { + sif::error << "TmTcBridge::initialize: TM store invalid. Make sure" + "it is created and set up properly." << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; } AcceptsTelecommandsIF* tcDistributor = - objectManager->get(ccsdsPacketDistributor); - if (tcDistributor == NULL) { - return RETURN_FAILED; + objectManager->get(tcDestination); + if (tcDistributor == nullptr) { + sif::error << "TmTcBridge::initialize: TC Distributor invalid" + << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; } - TmTcReceptionQueue->setDefaultDestination(tcDistributor->getRequestQueue()); + + tmTcReceptionQueue->setDefaultDestination(tcDistributor->getRequestQueue()); return RETURN_OK; } @@ -73,10 +82,7 @@ ReturnValue_t TmTcBridge::performOperation(uint8_t operationCode) { } ReturnValue_t TmTcBridge::handleTc() { - uint8_t * recvBuffer = nullptr; - size_t recvLen = 0; - ReturnValue_t result = receiveTc(&recvBuffer, &recvLen); - return result; + return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t TmTcBridge::handleTm() { @@ -97,8 +103,8 @@ ReturnValue_t TmTcBridge::handleTmQueue() { TmTcMessage message; const uint8_t* data = nullptr; size_t size = 0; - for (ReturnValue_t result = TmTcReceptionQueue->receiveMessage(&message); - result == RETURN_OK; result = TmTcReceptionQueue->receiveMessage(&message)) + for (ReturnValue_t result = tmTcReceptionQueue->receiveMessage(&message); + result == RETURN_OK; result = tmTcReceptionQueue->receiveMessage(&message)) { if(communicationLinkUp == false) { result = storeDownlinkData(&message); @@ -183,10 +189,20 @@ void TmTcBridge::registerCommDisconnect() { } MessageQueueId_t TmTcBridge::getReportReceptionQueue(uint8_t virtualChannel) { - return TmTcReceptionQueue->getId(); + return tmTcReceptionQueue->getId(); } void TmTcBridge::printData(uint8_t * data, size_t dataLen) { arrayprinter::print(data, dataLen); } + +uint16_t TmTcBridge::getIdentifier() { + // This is no PUS service, so we just return 0 + return 0; +} + +MessageQueueId_t TmTcBridge::getRequestQueue() { + // Default implementation: Relay TC messages to TC distributor directly. + return tmTcReceptionQueue->getDefaultDestination(); +} diff --git a/tmtcservices/TmTcBridge.h b/tmtcservices/TmTcBridge.h index 3e0432d8..3e3d1b71 100644 --- a/tmtcservices/TmTcBridge.h +++ b/tmtcservices/TmTcBridge.h @@ -1,16 +1,18 @@ #ifndef FRAMEWORK_TMTCSERVICES_TMTCBRIDGE_H_ #define FRAMEWORK_TMTCSERVICES_TMTCBRIDGE_H_ +#include #include #include #include #include -#include +#include -#include #include +#include class TmTcBridge : public AcceptsTelemetryIF, + public AcceptsTelecommandsIF, public ExecutableObjectIF, public HasReturnvaluesIF, public SystemObject { @@ -22,7 +24,8 @@ public: static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5; static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10; - TmTcBridge(object_id_t objectId_, object_id_t ccsdsPacketDistributor_); + TmTcBridge(object_id_t objectId, object_id_t tcDestination, + object_id_t tmStoreId, object_id_t tcStoreId); virtual ~TmTcBridge(); /** @@ -57,45 +60,41 @@ public: */ virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override; - /** - * Return TMTC Reception Queue - * @param virtualChannel - * @return - */ - MessageQueueId_t getReportReceptionQueue( + + /** AcceptsTelemetryIF override */ + virtual MessageQueueId_t getReportReceptionQueue( uint8_t virtualChannel = 0) override; + + /** AcceptsTelecommandsIF override */ + virtual uint16_t getIdentifier() override; + virtual MessageQueueId_t getRequestQueue() override; + protected: + //! Cached for initialize function. + object_id_t tmStoreId = objects::NO_OBJECT; + object_id_t tcStoreId = objects::NO_OBJECT; + object_id_t tcDestination = objects::NO_OBJECT; + //! Used to send and receive TMTC messages. //! TmTcMessage is used to transport messages between tasks. - MessageQueueIF* TmTcReceptionQueue = nullptr; - StorageManagerIF* tcStore = nullptr; + MessageQueueIF* tmTcReceptionQueue = nullptr; + StorageManagerIF* tmStore = nullptr; - object_id_t ccsdsPacketDistributor = 0; - //! Used to specify whether communication link is up - bool communicationLinkUp = false; + StorageManagerIF* tcStore = nullptr; + + //! Used to specify whether communication link is up by default. + bool communicationLinkUp = true; bool tmStored = false; /** * @brief Handle TC reception * @details * Default implementation provided, but is empty. - * Child handler should override this in most cases orsend TC to the - * TC distributor directly with the address of the reception queue by - * calling getReportRecptionQueue() + * In most cases, TC reception will be handled in a separate task anyway. * @return */ virtual ReturnValue_t handleTc(); - /** - * Implemented by child class. Perform receiving of Telecommand, - * for example by implementing specific drivers or wrappers, - * e.g. UART Communication or an ethernet stack - * @param recvBuffer [out] Received data - * @param size [out] Size of received data - * @return - */ - virtual ReturnValue_t receiveTc(uint8_t ** recvBuffer, size_t * size) = 0; - /** * Handle Telemetry. Default implementation provided. * Calls sendTm() From 90e299977bcb0d32672d520ecf94fee666913923 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 9 Jul 2020 19:41:16 +0200 Subject: [PATCH 173/653] minor formatting improvements --- tmtcservices/TmTcBridge.cpp | 27 +++++++++++++++------------ tmtcservices/TmTcBridge.h | 11 +++++++---- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/tmtcservices/TmTcBridge.cpp b/tmtcservices/TmTcBridge.cpp index 8c44f7de..b55803cb 100644 --- a/tmtcservices/TmTcBridge.cpp +++ b/tmtcservices/TmTcBridge.cpp @@ -24,8 +24,9 @@ ReturnValue_t TmTcBridge::setNumberOfSentPacketsPerCycle( return RETURN_OK; } else { - sif::warning << "TmTcBridge: Number of packets sent per cycle " - "exceeds limits. Keeping default value." << std::endl; + sif::warning << "TmTcBridge::setNumberOfSentPacketsPerCycle: Number of " + << "packets sent per cycle exceeds limits. " + << "Keeping default value." << std::endl; return RETURN_FAILED; } } @@ -37,8 +38,9 @@ ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored( return RETURN_OK; } else { - sif::warning << "TmTcBridge: Number of packets stored " - "exceeds limits. Keeping default value." << std::endl; + sif::warning << "TmTcBridge::setMaxNumberOfPacketsStored: Number of " + << "packets stored exceeds limits. " + << "Keeping default value." << std::endl; return RETURN_FAILED; } } @@ -72,11 +74,13 @@ ReturnValue_t TmTcBridge::performOperation(uint8_t operationCode) { ReturnValue_t result; result = handleTc(); if(result != RETURN_OK) { - sif::error << "TMTC Bridge: Error handling TCs" << std::endl; + sif::debug << "TmTcBridge::performOperation: " + << "Error handling TCs" << std::endl; } result = handleTm(); if (result != RETURN_OK) { - sif::error << "TMTC Bridge: Error handling TMs" << std::endl; + sif::debug << "TmTcBridge::performOperation: " + << "Error handling TMs" << std::endl; } return result; } @@ -88,7 +92,7 @@ ReturnValue_t TmTcBridge::handleTc() { ReturnValue_t TmTcBridge::handleTm() { ReturnValue_t result = handleTmQueue(); if(result != RETURN_OK) { - sif::error << "TMTC Bridge: Reading TM Queue failed" << std::endl; + sif::warning << "TmTcBridge: Reading TM Queue failed" << std::endl; return RETURN_FAILED; } @@ -118,7 +122,7 @@ ReturnValue_t TmTcBridge::handleTmQueue() { result = sendTm(data, size); if (result != RETURN_OK) { - sif::error << "TMTC Bridge: Could not send TM packet"<< std::endl; + sif::warning << "TmTcBridge: Could not send TM packet" << std::endl; tmStore->deleteData(message.getStorageId()); return result; @@ -129,13 +133,12 @@ ReturnValue_t TmTcBridge::handleTmQueue() { } ReturnValue_t TmTcBridge::storeDownlinkData(TmTcMessage *message) { - //debug << "TMTC Bridge: Comm Link down. " - // "Saving packet ID to be sent later\r\n" << std::flush; store_address_t storeId = 0; if(tmFifo.full()) { - sif::error << "TMTC Bridge: TM downlink max. number of stored packet IDs " - "reached! Overwriting old data" << std::endl; + sif::error << "TmTcBridge::storeDownlinkData: TM downlink max. number " + << "of stored packet IDs reached! " + << "Overwriting old data" << std::endl; tmFifo.retrieve(&storeId); tmStore->deleteData(storeId); } diff --git a/tmtcservices/TmTcBridge.h b/tmtcservices/TmTcBridge.h index 3e3d1b71..993cd5b9 100644 --- a/tmtcservices/TmTcBridge.h +++ b/tmtcservices/TmTcBridge.h @@ -76,13 +76,14 @@ protected: object_id_t tcDestination = objects::NO_OBJECT; //! Used to send and receive TMTC messages. - //! TmTcMessage is used to transport messages between tasks. + //! The TmTcMessage class is used to transport messages between tasks. MessageQueueIF* tmTcReceptionQueue = nullptr; StorageManagerIF* tmStore = nullptr; StorageManagerIF* tcStore = nullptr; - //! Used to specify whether communication link is up by default. + //! Used to specify whether communication link is up. Will be true + //! by default, so telemetry will be handled immediately. bool communicationLinkUp = true; bool tmStored = false; @@ -103,7 +104,8 @@ protected: virtual ReturnValue_t handleTm(); /** - * Read the TM Queue and send TM if necessary. Default implementation provided + * Read the TM Queue and send TM if necessary. + * Default implementation provided * @return */ virtual ReturnValue_t handleTmQueue(); @@ -116,7 +118,8 @@ protected: /** * Implemented by child class. Perform sending of Telemetry by implementing - * communication drivers or wrappers, e.g. UART communication or lwIP stack. + * communication drivers or wrappers, e.g. serial communication or a socket + * call. * @param data * @param dataLen * @return From 83484237ae67298190275965c64e83c4268fd4e1 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 9 Jul 2020 19:53:17 +0200 Subject: [PATCH 174/653] default argument for getter function --- ipc/CommandMessage.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ipc/CommandMessage.h b/ipc/CommandMessage.h index b800b9d2..b75d94b1 100644 --- a/ipc/CommandMessage.h +++ b/ipc/CommandMessage.h @@ -124,7 +124,8 @@ public: */ void setToUnknownCommand(); void setReplyRejected(ReturnValue_t reason, Command_t initialCommand = CMD_NONE); - ReturnValue_t getReplyRejectedReason(Command_t *initialCommand) const; + ReturnValue_t getReplyRejectedReason( + Command_t *initialCommand = nullptr) const; size_t getMinimumMessageSize() const; }; From d1e922eecf6b24bdd01286864a075b63080d4aa0 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 9 Jul 2020 20:08:40 +0200 Subject: [PATCH 175/653] new intiialize after task creation function --- tasks/ExecutableObjectIF.h | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/tasks/ExecutableObjectIF.h b/tasks/ExecutableObjectIF.h index 5c5955c1..d716cdfb 100644 --- a/tasks/ExecutableObjectIF.h +++ b/tasks/ExecutableObjectIF.h @@ -1,15 +1,5 @@ -/** - * @file ExecutableObjectIF.h - * - * @brief This file contains the definition for the ExecutableObjectIF interface. - * - * @author Bastian Baetz - * - * @date 12.03.2012 - */ - -#ifndef EXECUTABLEOBJECTIF_H_ -#define EXECUTABLEOBJECTIF_H_ +#ifndef FRAMEWORK_TASKS_EXECUTABLEOBJECTIF_H_ +#define FRAMEWORK_TASKS_EXECUTABLEOBJECTIF_H_ class PeriodicTaskIF; @@ -20,6 +10,7 @@ class PeriodicTaskIF; * @brief The interface provides a method to execute objects within a task. * @details The performOperation method, that is required by the interface is * executed cyclically within a task context. + * @author Bastian Baetz */ class ExecutableObjectIF { public: @@ -37,13 +28,26 @@ public: /** * @brief Function called during setup assignment of object to task - * @details Has to be called from the function that assigns the object to a task and - * enables the object implementation to overwrite this function and get a reference to the executing task + * @details + * Has to be called from the function that assigns the object to a task and + * enables the object implementation to overwrite this function and get + * a reference to the executing task * @param task_ Pointer to the taskIF of this task */ - virtual void setTaskIF(PeriodicTaskIF* task_) { + virtual void setTaskIF(PeriodicTaskIF* task_) {}; + /** + * This function should be called after the object was assigned to a + * specific task. + * + * Example: Can be used to get task execution frequency. + * The task is created after initialize() and the object ctors have been + * called so the execution frequency can't be cached in initialize() + * @return + */ + virtual ReturnValue_t initializeAfterTaskCreation() { + return HasReturnvaluesIF::RETURN_OK; } }; -#endif /* EXECUTABLEOBJECTIF_H_ */ +#endif /* FRAMEWORK_TASKS_EXECUTABLEOBJECTIF_H_ */ From 6b2b788308bef172e6a83c46a44ea20bf3106f41 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 10 Jul 2020 14:16:55 +0200 Subject: [PATCH 176/653] added new pus services --- framework.mk | 13 +- pus/CService200ModeCommanding.cpp | 119 +++++++++++++++++ pus/CService200ModeCommanding.h | 85 ++++++++++++ pus/Service1TelecommandVerification.cpp | 100 ++++++++++++++ pus/Service1TelecommandVerification.h | 94 +++++++++++++ pus/Service2DeviceAccess.cpp | 167 ++++++++++++++++++++++++ pus/Service2DeviceAccess.h | 92 +++++++++++++ pus/Service5EventReporting.cpp | 91 +++++++++++++ pus/Service5EventReporting.h | 86 ++++++++++++ pus/Service8FunctionManagement.cpp | 135 +++++++++++++++++++ pus/Service8FunctionManagement.h | 67 ++++++++++ pus/servicepackets/Service1Packets.h | 166 +++++++++++++++++++++++ pus/servicepackets/Service200Packets.h | 63 +++++++++ pus/servicepackets/Service2Packets.h | 76 +++++++++++ pus/servicepackets/Service5Packets.h | 76 +++++++++++ pus/servicepackets/Service8Packets.h | 136 +++++++++++++++++++ 16 files changed, 1562 insertions(+), 4 deletions(-) create mode 100644 pus/CService200ModeCommanding.cpp create mode 100644 pus/CService200ModeCommanding.h create mode 100644 pus/Service1TelecommandVerification.cpp create mode 100644 pus/Service1TelecommandVerification.h create mode 100644 pus/Service2DeviceAccess.cpp create mode 100644 pus/Service2DeviceAccess.h create mode 100644 pus/Service5EventReporting.cpp create mode 100644 pus/Service5EventReporting.h create mode 100644 pus/Service8FunctionManagement.cpp create mode 100644 pus/Service8FunctionManagement.h create mode 100644 pus/servicepackets/Service1Packets.h create mode 100644 pus/servicepackets/Service200Packets.h create mode 100644 pus/servicepackets/Service2Packets.h create mode 100644 pus/servicepackets/Service5Packets.h create mode 100644 pus/servicepackets/Service8Packets.h diff --git a/framework.mk b/framework.mk index a5a65364..5db96b5b 100644 --- a/framework.mk +++ b/framework.mk @@ -1,5 +1,5 @@ -# This file needs FRAMEWORK_PATH and API set correctly -# Valid API settings: rtems, linux, freeRTOS +# This file needs FRAMEWORK_PATH and OS_FSFW set correctly by another Makefile. +# Valid API settings: rtems, linux, freeRTOS, host CXXSRC += $(wildcard $(FRAMEWORK_PATH)/action/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/container/*.cpp) @@ -8,11 +8,13 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/controller/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/coordinates/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datalinklayer/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapool/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoolglob/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoollocal/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/housekeeping/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/devicehandlers/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/eventmatching/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/fdir/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/framework.mk/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/globalfunctions/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/globalfunctions/matching/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/globalfunctions/math/*.cpp) @@ -32,8 +34,10 @@ else ifeq ($(OS),linux) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/linux/*.cpp) else ifeq ($(OS),freeRTOS) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/FreeRTOS/*.cpp) +else ifeq ($(OS),host) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/host/*.cpp) else -$(error invalid OS specified, valid OS are rtems, linux, freeRTOS) +$(error invalid OS specified, valid OS are rtems, linux, freeRTOS, host) endif CXXSRC += $(wildcard $(FRAMEWORK_PATH)/parameters/*.cpp) @@ -54,3 +58,4 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/packetmatcher/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/pus/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcservices/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/pus/*.cpp) diff --git a/pus/CService200ModeCommanding.cpp b/pus/CService200ModeCommanding.cpp new file mode 100644 index 00000000..fd6da67e --- /dev/null +++ b/pus/CService200ModeCommanding.cpp @@ -0,0 +1,119 @@ +#include +#include + +#include +#include +#include +#include + +CService200ModeCommanding::CService200ModeCommanding(object_id_t objectId, + uint16_t apid, uint8_t serviceId): + CommandingServiceBase(objectId, apid, serviceId, + NUMBER_OF_PARALLEL_COMMANDS,COMMAND_TIMEOUT_SECONDS) {} + +CService200ModeCommanding::~CService200ModeCommanding() {} + +ReturnValue_t CService200ModeCommanding::isValidSubservice(uint8_t subservice) { + switch(subservice) { + case(Subservice::COMMAND_MODE_COMMAND): + case(Subservice::COMMAND_MODE_READ): + case(Subservice::COMMAND_MODE_ANNCOUNCE): + return RETURN_OK; + default: + return AcceptsTelecommandsIF::INVALID_SUBSERVICE; + } +} + + +ReturnValue_t CService200ModeCommanding::getMessageQueueAndObject( + uint8_t subservice, const uint8_t *tcData, size_t tcDataLen, + MessageQueueId_t *id, object_id_t *objectId) { + if(tcDataLen < sizeof(object_id_t)) { + return CommandingServiceBase::INVALID_TC; + } + SerializeAdapter::deSerialize(objectId, &tcData, &tcDataLen, + SerializeIF::Endianness::BIG); + + return checkInterfaceAndAcquireMessageQueue(id,objectId); +} + +ReturnValue_t CService200ModeCommanding::checkInterfaceAndAcquireMessageQueue( + MessageQueueId_t* messageQueueToSet, object_id_t* objectId) { + HasModesIF * destination = objectManager->get(*objectId); + if(destination == nullptr) { + return CommandingServiceBase::INVALID_OBJECT; + + } + + *messageQueueToSet = destination->getCommandQueue(); + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t CService200ModeCommanding::prepareCommand( + CommandMessage* message,uint8_t subservice, const uint8_t *tcData, + size_t tcDataLen, uint32_t *state, object_id_t objectId) { + ModePacket modeCommandPacket; + ReturnValue_t result = modeCommandPacket.deSerialize(&tcData, + &tcDataLen, SerializeIF::Endianness::BIG); + if (result != RETURN_OK) { + return result; + } + + ModeMessage::setModeMessage(dynamic_cast(message), + ModeMessage::CMD_MODE_COMMAND, modeCommandPacket.getMode(), + modeCommandPacket.getSubmode()); + return result; +} + + +ReturnValue_t CService200ModeCommanding::handleReply( + const CommandMessage* reply, Command_t previousCommand, + uint32_t *state, CommandMessage* optionalNextCommand, + object_id_t objectId, bool *isStep) { + Command_t replyId = reply->getCommand(); + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + switch(replyId) { + case(ModeMessage::REPLY_MODE_REPLY): { + result = prepareModeReply(reply, objectId); + break; + } + case(ModeMessage::REPLY_WRONG_MODE_REPLY): { + result = prepareWrongModeReply(reply, objectId); + break; + } + case(ModeMessage::REPLY_CANT_REACH_MODE): { + result = prepareCantReachModeReply(reply, objectId); + break; + } + case(ModeMessage::REPLY_MODE_INFO): + result = INVALID_REPLY; + break; + default: + result = RETURN_FAILED; + } + return result; +} + +ReturnValue_t CService200ModeCommanding::prepareModeReply( + const CommandMessage *reply, object_id_t objectId) { + ModePacket modeReplyPacket(objectId, + ModeMessage::getMode(reply), + ModeMessage::getSubmode(reply)); + return sendTmPacket(Subservice::REPLY_MODE_REPLY, &modeReplyPacket); +} + +ReturnValue_t CService200ModeCommanding::prepareWrongModeReply( + const CommandMessage *reply, object_id_t objectId) { + ModePacket wrongModeReply(objectId, ModeMessage::getMode(reply), + ModeMessage::getSubmode(reply)); + return sendTmPacket(Subservice::REPLY_WRONG_MODE_REPLY, &wrongModeReply); +} + +ReturnValue_t CService200ModeCommanding::prepareCantReachModeReply( + const CommandMessage *reply, object_id_t objectId) { + CantReachModePacket cantReachModePacket(objectId, + ModeMessage::getCantReachModeReason(reply)); + return sendTmPacket(Subservice::REPLY_CANT_REACH_MODE, + &cantReachModePacket); +} diff --git a/pus/CService200ModeCommanding.h b/pus/CService200ModeCommanding.h new file mode 100644 index 00000000..ede61a84 --- /dev/null +++ b/pus/CService200ModeCommanding.h @@ -0,0 +1,85 @@ +#ifndef FRAMEWORK_PUS_CSERVICE200MODECOMMANDING_H_ +#define FRAMEWORK_PUS_CSERVICE200MODECOMMANDING_H_ + +#include + +/** + * @brief Custom PUS service to set mode of all objects implementing HasModesIF + * + * Examples: Device Handlers, Assemblies or Subsystems. + * Full Documentation: ECSS-E-ST-70-41C or ECSS-E-70-41A + * Dissertation Baetz p. 115, 116, 165-167. + * + * This is a gateway service. It relays device commands using the software bus. + * @ingroup pus_services + */ +class CService200ModeCommanding: public CommandingServiceBase { +public: + static constexpr uint8_t NUMBER_OF_PARALLEL_COMMANDS = 4; + static constexpr uint16_t COMMAND_TIMEOUT_SECONDS = 60; + + CService200ModeCommanding(object_id_t objectId, + uint16_t apid, uint8_t serviceId); + virtual~ CService200ModeCommanding(); + +protected: + //! CommandingServiceBase (CSB) abstract functions. See CSB documentation. + ReturnValue_t isValidSubservice(uint8_t subservice) override; + ReturnValue_t getMessageQueueAndObject(uint8_t subservice, + const uint8_t *tcData, size_t tcDataLen, MessageQueueId_t *id, + object_id_t *objectId) override; + ReturnValue_t prepareCommand(CommandMessage* message, + uint8_t subservice, const uint8_t *tcData, size_t tcDataLen, + uint32_t *state, object_id_t objectId) override; + ReturnValue_t handleReply(const CommandMessage* reply, + Command_t previousCommand, uint32_t *state, + CommandMessage* optionalNextCommand, object_id_t objectId, + bool *isStep) override; + +private: + ReturnValue_t checkAndAcquireTargetID(object_id_t* objectIdToSet, + const uint8_t* tcData, uint32_t tcDataLen); + ReturnValue_t checkInterfaceAndAcquireMessageQueue( + MessageQueueId_t* MessageQueueToSet, object_id_t* objectId); + + ReturnValue_t prepareModeReply(const CommandMessage *reply, + object_id_t objectId); + ReturnValue_t prepareWrongModeReply(const CommandMessage *reply, + object_id_t objectId); + ReturnValue_t prepareCantReachModeReply(const CommandMessage *reply, + object_id_t objectId); + + enum Subservice { //!< [EXPORT] : [COMMENT] Mode Commanding Subservices + //!< [EXPORT] : [COMMAND] Command assembly, subsystem or device mode + COMMAND_MODE_COMMAND = 1, + //!< [EXPORT] : [COMMAND] Command to set the specified Mode, + //! regardless of external control flag + COMMAND_MODE_COMMAND_FORCED = 2, + //!< [EXPORT] : [COMMAND] Read the current mode and + //! reply with a REPLY_MODE_REPLY + COMMAND_MODE_READ = 3, + //!< [EXPORT] : [COMMAND] Trigger an ModeInfo Event. + //! This command does NOT have a reply + COMMAND_MODE_ANNCOUNCE = 4, + //!< [EXPORT] : [COMMAND] Trigger a ModeInfo Event and to send this + //! command to every child. This command does NOT have a reply. + COMMAND_MODE_ANNOUNCE_RECURSIVELY = 5, + //!< [EXPORT] : [REPLY] Reply to a CMD_MODE_COMMAND or CMD_MODE_READ + REPLY_MODE_REPLY = 6, + //!< [EXPORT] : [REPLY] Reply in case a mode command can't be executed. + REPLY_CANT_REACH_MODE = 7, + //!< [EXPORT] : [REPLY] Reply to a CMD_MODE_COMMAND, indicating that a + //! mode was commanded and a transition started but was aborted, + //! the parameters contain the mode that was reached + REPLY_WRONG_MODE_REPLY = 8 + }; + + enum modeParameters { + MODE_OFF = 0, + MODE_ON = 1, + MODE_NORMAL = 2, + MODE_RAW = 3 + }; +}; + +#endif /* FRAMEWORK_PUS_CSERVICE200MODECOMMANDING_H_ */ diff --git a/pus/Service1TelecommandVerification.cpp b/pus/Service1TelecommandVerification.cpp new file mode 100644 index 00000000..4ce2ce54 --- /dev/null +++ b/pus/Service1TelecommandVerification.cpp @@ -0,0 +1,100 @@ +#include +#include + +#include +#include +#include +#include +#include +#include + + +Service1TelecommandVerification::Service1TelecommandVerification( + object_id_t objectId, uint16_t apid, uint8_t serviceId, + object_id_t targetDestination): + SystemObject(objectId), apid(apid), serviceId(serviceId), + targetDestination(targetDestination) { + tmQueue = QueueFactory::instance()->createMessageQueue(); +} + +Service1TelecommandVerification::~Service1TelecommandVerification() {} + +MessageQueueId_t Service1TelecommandVerification::getVerificationQueue(){ + return tmQueue->getId(); +} + + +ReturnValue_t Service1TelecommandVerification::performOperation( + uint8_t operationCode){ + PusVerificationMessage message; + ReturnValue_t status = tmQueue->receiveMessage(&message); + while(status == HasReturnvaluesIF::RETURN_OK) { + status = sendVerificationReport(&message); + if(status != HasReturnvaluesIF::RETURN_OK) { + return status; + } + status = tmQueue->receiveMessage(&message); + } + if (status == MessageQueueIF::EMPTY) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return status; + } +} + + +ReturnValue_t Service1TelecommandVerification::sendVerificationReport( + PusVerificationMessage* message) { + ReturnValue_t result; + if(message->getReportId() % 2 == 0) { + result = generateFailureReport(message); + } else { + result = generateSuccessReport(message); + } + if(result != HasReturnvaluesIF::RETURN_OK){ + sif::error << "Service1TelecommandVerification::initialize: " + "Sending verification packet failed !" << std::endl; + } + return result; +} + +ReturnValue_t Service1TelecommandVerification::generateFailureReport( + PusVerificationMessage *message) { + FailureReport report( + message->getReportId(), message->getTcPacketId(), + message->getTcSequenceControl(), message->getStep(), + message->getErrorCode(), message->getParameter1(), + message->getParameter2()); + TmPacketStored tmPacket(apid, serviceId, message->getReportId(), + packetSubCounter++, &report); + ReturnValue_t result = tmPacket.sendPacket(tmQueue->getDefaultDestination(), + tmQueue->getId()); + return result; +} + +ReturnValue_t Service1TelecommandVerification::generateSuccessReport( + PusVerificationMessage *message) { + SuccessReport report(message->getReportId(),message->getTcPacketId(), + message->getTcSequenceControl(),message->getStep()); + TmPacketStored tmPacket(apid, serviceId, message->getReportId(), + packetSubCounter++, &report); + ReturnValue_t result = tmPacket.sendPacket(tmQueue->getDefaultDestination(), + tmQueue->getId()); + return result; +} + + +ReturnValue_t Service1TelecommandVerification::initialize() { + // Get target object for TC verification messages + AcceptsTelemetryIF* funnel = objectManager-> + get(targetDestination); + if(funnel == nullptr){ + sif::error << "Service1TelecommandVerification::initialize: Specified" + " TM funnel invalid. Make sure it is set up and implements" + " AcceptsTelemetryIF." << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + tmQueue->setDefaultDestination(funnel->getReportReceptionQueue()); + return SystemObject::initialize(); +} diff --git a/pus/Service1TelecommandVerification.h b/pus/Service1TelecommandVerification.h new file mode 100644 index 00000000..1d4b6719 --- /dev/null +++ b/pus/Service1TelecommandVerification.h @@ -0,0 +1,94 @@ +#ifndef MISSION_PUS_SERVICE1TELECOMMANDVERIFICATION_H_ +#define MISSION_PUS_SERVICE1TELECOMMANDVERIFICATION_H_ + +#include +#include +#include +#include +#include +#include + +/** + * @brief Verify TC acceptance, start, progress and execution. + * + * Full Documentation: ECSS-E70-41A p.51 + * + * The telecommand verification service provides the capability for + * explicit verification of each distinct stage of execution of a telecommand + * packet, from on-board acceptance through to completion of execution. + * + * Minimum capabilities of this service: + * + * - TM[1,1]: Telecommand Acceptance Report - Success. + * - TM[1,2]: Telecommand Acceptance Report - Failure. + * + * Additional capabilities of this service: + * + * - TM[1,3]: Telecommand Execution Started Report - Success (Req. 4). + * - TM[1,4]: Telecommand Execution Started Report - Failure (Req. 3). + * - TM[1,5]: Telecommand Execution Progress Report - Success (Req. 6). + * - TM[1,6]: Telecommand Execution Progress Report - Failure (Req. 5). + * - TM[1,7]: Telecommand Execution Completed Report - Success (Req. 8). + * - TM[1,8]: Telecommand Execution Completed Report - Failure (Req. 7). + * + * This Service is not inherited from PUSServiceBase unlike other PUS Services + * because all services implementing PUSServiceBase use this service to + * generate verification reports. + * @ingroup pus_services + */ +class Service1TelecommandVerification: public AcceptsVerifyMessageIF, + public SystemObject, + public ExecutableObjectIF, + public HasReturnvaluesIF { +public: + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_1; + + Service1TelecommandVerification(object_id_t objectId, + uint16_t apid, uint8_t serviceId, object_id_t targetDestination); + virtual ~Service1TelecommandVerification(); + + /** + * + * @return ID of Verification Queue + */ + virtual MessageQueueId_t getVerificationQueue(); + + /** + * Performs the service periodically as specified in init_mission(). + * Triggers the handlePacket function to send TC verification messages + * @param operationCode + * @return + */ + ReturnValue_t performOperation(uint8_t operationCode = 0) override; + + /** + * Initializes the destination for TC verification messages and initializes + * Service 1 as a system object + * @return + */ + ReturnValue_t initialize() override; +private: + uint16_t apid = 0; + uint8_t serviceId = 0; + + object_id_t targetDestination = objects::NO_OBJECT; + + ReturnValue_t sendVerificationReport(PusVerificationMessage* message); + ReturnValue_t generateFailureReport(PusVerificationMessage* message); + ReturnValue_t generateSuccessReport(PusVerificationMessage* message); + + uint16_t packetSubCounter = 0; + + MessageQueueIF* tmQueue = nullptr; + + enum class Subservice: uint8_t { + VERIFY_ACCEPTANCE_SUCCESS = 1, //!< [EXPORT] : [TM] + VERIFY_ACCEPTANCE_FAILED = 2, //!< [EXPORT] : [TM] + VERIFY_START_SUCCESS = 3, //!< [EXPORT] : [TM] + VERIFY_START_FAILED = 4, //!< [EXPORT] : [TM] + VERIFY_STEP_SUCCESS = 5, //!< [EXPORT] : [TM] + VERIFY_STEP_FAILED = 6 //!< [EXPORT] : [TM] + }; +}; + +#endif /* MISSION_PUS_SERVICE1TELECOMMANDVERIFICATION_H_ */ diff --git a/pus/Service2DeviceAccess.cpp b/pus/Service2DeviceAccess.cpp new file mode 100644 index 00000000..1d5f21eb --- /dev/null +++ b/pus/Service2DeviceAccess.cpp @@ -0,0 +1,167 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +Service2DeviceAccess::Service2DeviceAccess(object_id_t objectId, + uint16_t apid, uint8_t serviceId, uint8_t numberOfParallelCommands, + uint16_t commandTimeoutSeconds): + CommandingServiceBase(objectId, apid, serviceId, + numberOfParallelCommands, commandTimeoutSeconds) {} + +Service2DeviceAccess::~Service2DeviceAccess() {} + + +ReturnValue_t Service2DeviceAccess::isValidSubservice(uint8_t subservice) { + switch(static_cast(subservice)){ + case Subservice::RAW_COMMANDING: + case Subservice::TOGGLE_WIRETAPPING: + return HasReturnvaluesIF::RETURN_OK; + default: + sif::error << "Invalid Subservice" << std::endl; + return AcceptsTelecommandsIF::INVALID_SUBSERVICE; + } +} + +ReturnValue_t Service2DeviceAccess::getMessageQueueAndObject( + uint8_t subservice, const uint8_t* tcData, size_t tcDataLen, + MessageQueueId_t* id, object_id_t* objectId) { + if(tcDataLen < sizeof(object_id_t)) { + return CommandingServiceBase::INVALID_TC; + } + SerializeAdapter::deSerialize(objectId, &tcData, + &tcDataLen, SerializeIF::Endianness::BIG); + + ReturnValue_t result = checkInterfaceAndAcquireMessageQueue(id,objectId); + return result; +} + +ReturnValue_t Service2DeviceAccess::checkInterfaceAndAcquireMessageQueue( + MessageQueueId_t * messageQueueToSet, object_id_t *objectId) { + DeviceHandlerIF* possibleTarget = + objectManager->get(*objectId); + if(possibleTarget == nullptr) { + return CommandingServiceBase::INVALID_OBJECT; + } + *messageQueueToSet = possibleTarget->getCommandQueue(); + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t Service2DeviceAccess::prepareCommand(CommandMessage* message, + uint8_t subservice, const uint8_t* tcData, size_t tcDataLen, + uint32_t* state, object_id_t objectId) { + switch(static_cast(subservice)){ + case Subservice::RAW_COMMANDING: { + return prepareRawCommand(dynamic_cast(message), + tcData, tcDataLen); + } + break; + case Subservice::TOGGLE_WIRETAPPING: { + return prepareWiretappingCommand(dynamic_cast(message), + tcData, tcDataLen); + } + break; + default: + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +ReturnValue_t Service2DeviceAccess::prepareRawCommand( + CommandMessage* messageToSet, const uint8_t *tcData,size_t tcDataLen) { + RawCommand RawCommand(tcData,tcDataLen); + // store command into the Inter Process Communication Store + store_address_t storeAddress; + ReturnValue_t result = IPCStore->addData(&storeAddress, + RawCommand.getCommand(), RawCommand.getCommandSize()); + DeviceHandlerMessage::setDeviceHandlerRawCommandMessage(messageToSet, + storeAddress); + return result; +} + +ReturnValue_t Service2DeviceAccess::prepareWiretappingCommand( + CommandMessage *messageToSet, const uint8_t *tcData, + size_t tcDataLen) { + if(tcDataLen != WiretappingToggle::WIRETAPPING_COMMAND_SIZE) { + return CommandingServiceBase::INVALID_TC; + } + WiretappingToggle command; + ReturnValue_t result = command.deSerialize(&tcData, &tcDataLen, + SerializeIF::Endianness::BIG); + DeviceHandlerMessage::setDeviceHandlerWiretappingMessage(messageToSet, + command.getWiretappingMode()); + return result; +} + + +ReturnValue_t Service2DeviceAccess::handleReply(const CommandMessage* reply, + Command_t previousCommand, uint32_t* state, + CommandMessage* optionalNextCommand, object_id_t objectId, + bool* isStep) { + switch(reply->getCommand()) { + case CommandMessage::REPLY_COMMAND_OK: + return HasReturnvaluesIF::RETURN_OK; + case CommandMessage::REPLY_REJECTED: + return reply->getReplyRejectedReason(); + default: + return CommandingServiceBase::INVALID_REPLY; + } +} + +// All device handlers set service 2 as default raw receiver for wiretapping +// so we have to handle those unrequested messages. +void Service2DeviceAccess::handleUnrequestedReply(CommandMessage* reply) { + switch(reply->getCommand()) { + case DeviceHandlerMessage::REPLY_RAW_COMMAND: + sendWiretappingTm(reply, + static_cast(Subservice::WIRETAPPING_RAW_TC)); + break; + case DeviceHandlerMessage::REPLY_RAW_REPLY: + sendWiretappingTm(reply, + static_cast(Subservice::RAW_REPLY)); + break; + default: + sif::error << "Unknown message in Service2DeviceAccess::" + "handleUnrequestedReply with command ID " << + reply->getCommand() << std::endl; + break; + } + //Must be reached by all cases to clear message + reply->clear(); +} + +void Service2DeviceAccess::sendWiretappingTm(CommandMessage *reply, + uint8_t subservice) { + // Raw Wiretapping + // Get Address of Data from Message + store_address_t storeAddress = DeviceHandlerMessage::getStoreAddress(reply); + const uint8_t* data = nullptr; + size_t size = 0; + ReturnValue_t result = IPCStore->getData(storeAddress, &data, &size); + if(result != HasReturnvaluesIF::RETURN_OK){ + sif::error << "Service2DeviceAccess::sendWiretappingTm: Data Lost in " + "handleUnrequestedReply with failure ID "<< result + << std::endl; + return; + } + + // Init our dummy packet and correct endianness of object ID before + // sending it back. + WiretappingPacket TmPacket(DeviceHandlerMessage::getDeviceObjectId(reply), + data); + TmPacket.objectId = EndianConverter::convertBigEndian(TmPacket.objectId); + sendTmPacket(subservice, TmPacket.data,size, reinterpret_cast( + &TmPacket.objectId), sizeof(TmPacket.objectId)); +} + +MessageQueueId_t Service2DeviceAccess::getDeviceQueue() { + return commandQueue->getId(); +} + diff --git a/pus/Service2DeviceAccess.h b/pus/Service2DeviceAccess.h new file mode 100644 index 00000000..1a0bede0 --- /dev/null +++ b/pus/Service2DeviceAccess.h @@ -0,0 +1,92 @@ +#ifndef FRAMEWORK_PUS_SERVICE2DEVICEACCESS_H_ +#define FRAMEWORK_PUS_SERVICE2DEVICEACCESS_H_ + +#include +#include +#include + +/** + * @brief Raw Commanding and Wiretapping of devices. + * @details + * Full Documentation: ECSS-E-ST-70-41C or ECSS-E-70-41A + * Dissertation Baetz p. 115, 116, 165-167. + * + * This service provides the capability to communicate with devices in their + * native protocols with raw commands through the DeviceHandlerIF. + * + * This is a gateway service. It relays device commands to the software bus. + * This service is very closely tied to the CommandingServiceBase + * template class. + * + * There are 4 adaption points for component implementation through the + * CommandingServiceBase. + * + * This service employs custom subservices exclusively. This includes a + * wiretapping subservice to monitor all traffic between target devices and + * this service. + * + * - TC[2,128]: Raw Commanding + * - TC[2,129]: Toggle Wiretapping + * - TM[2,130]: Wiretapping Packet TM + * - TM[2,131]: Wiretapping Packet TC + * @ingroup pus_services + */ +class Service2DeviceAccess : public CommandingServiceBase, + public AcceptsDeviceResponsesIF +{ +public: + Service2DeviceAccess(object_id_t objectId, uint16_t apid, + uint8_t serviceId, uint8_t numberOfParallelCommands = 4, + uint16_t commandTimeoutSeconds = 60); + virtual ~Service2DeviceAccess(); + +protected: + //! CommandingServiceBase (CSB) abstract functions. See CSB documentation. + ReturnValue_t isValidSubservice(uint8_t subservice) override; + ReturnValue_t getMessageQueueAndObject(uint8_t subservice, + const uint8_t *tcData, size_t tcDataLen, MessageQueueId_t *id, + object_id_t *objectId) override; + ReturnValue_t prepareCommand(CommandMessage* message, uint8_t subservice, + const uint8_t *tcData, size_t tcDataLen, uint32_t *state, + object_id_t objectId) override; + ReturnValue_t handleReply(const CommandMessage* reply, + Command_t previousCommand, uint32_t *state, + CommandMessage* optionalNextCommand, object_id_t objectId, + bool *isStep) override; + + /** + * @brief Generates TM packets containing either the TC wiretapping + * packets or the TM wiretapping packets. + * Note that for service 2, all telemetry will be treated as an + * unrequested reply regardless of wiretapping mode. + * @param reply + */ + void handleUnrequestedReply(CommandMessage* reply) override; + + MessageQueueId_t getDeviceQueue() override; +private: + /** + * Generates TM packets for Wiretapping Service + * @param reply + * @param subservice + */ + void sendWiretappingTm(CommandMessage* reply,uint8_t subservice); + + ReturnValue_t checkInterfaceAndAcquireMessageQueue( + MessageQueueId_t* messageQueueToSet, object_id_t* objectId); + + ReturnValue_t prepareRawCommand(CommandMessage* messageToSet, + const uint8_t* tcData, size_t tcDataLen); + ReturnValue_t prepareWiretappingCommand(CommandMessage* messageToSet, + const uint8_t* tcData, size_t tcDataLen); + + enum class Subservice { + RAW_COMMANDING = 128, //!< [EXPORT] : [COMMAND] Command in device native protocol + TOGGLE_WIRETAPPING = 129, //!< [EXPORT] : [COMMAND] Toggle wiretapping of raw communication + RAW_REPLY = 130, //!< [EXPORT] : [REPLY] Includes wiretapping TM and normal TM raw replies from device + WIRETAPPING_RAW_TC = 131 //!< [EXPORT] : [REPLY] Wiretapping packets of commands built by device handler + }; +}; + + +#endif /* MISSION_PUS_DEVICE2DEVICECOMMANDING_H_ */ diff --git a/pus/Service5EventReporting.cpp b/pus/Service5EventReporting.cpp new file mode 100644 index 00000000..1dfbe229 --- /dev/null +++ b/pus/Service5EventReporting.cpp @@ -0,0 +1,91 @@ +#include +#include + +#include +#include +#include +#include + + +Service5EventReporting::Service5EventReporting(object_id_t objectId, + uint16_t apid, uint8_t serviceId, size_t maxNumberReportsPerCycle): + PusServiceBase(objectId, apid, serviceId), + maxNumberReportsPerCycle(maxNumberReportsPerCycle) { + eventQueue = QueueFactory::instance()->createMessageQueue(); +} + +Service5EventReporting::~Service5EventReporting(){} + +ReturnValue_t Service5EventReporting::performService() { + EventMessage message; + ReturnValue_t status = RETURN_OK; + for(uint8_t counter = 0; + counter < maxNumberReportsPerCycle; + counter++) + { + // Receive messages even if reporting is disabled for now. + status = eventQueue->receiveMessage(&message); + if(status == MessageQueueIF::EMPTY) { + return HasReturnvaluesIF::RETURN_OK; + } + + if(enableEventReport) { + status = generateEventReport(message); + if(status != HasReturnvaluesIF::RETURN_OK) { + return status; + } + } + } + sif::debug << "Service5EventReporting::generateEventReport:" + " Too many events" << std::endl; + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t Service5EventReporting::generateEventReport( + EventMessage message) +{ + EventReport report(message.getEventId(),message.getReporter(), + message.getParameter1(),message.getParameter2()); + TmPacketStored tmPacket(PusServiceBase::apid, PusServiceBase::serviceId, + message.getSeverity(), packetSubCounter++, &report); + ReturnValue_t result = tmPacket.sendPacket( + requestQueue->getDefaultDestination(),requestQueue->getId()); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::debug << "Service5EventReporting::generateEventReport:" + " Could not send TM packet" << std::endl; + } + return result; +} + +ReturnValue_t Service5EventReporting::handleRequest(uint8_t subservice) { + switch(subservice) { + case Subservice::ENABLE: { + enableEventReport = true; + return HasReturnvaluesIF::RETURN_OK; + } + case Subservice::DISABLE: { + enableEventReport = false; + return HasReturnvaluesIF::RETURN_OK; + } + default: + return AcceptsTelecommandsIF::INVALID_SUBSERVICE; + } +} + + +// In addition to the default PUSServiceBase initialization, this service needs +// to be registered to the event manager to listen for events. +ReturnValue_t Service5EventReporting::initialize() { + EventManagerIF* manager = objectManager->get( + objects::EVENT_MANAGER); + if (manager == NULL) { + return RETURN_FAILED; + } + // register Service 5 as listener for events + ReturnValue_t result = manager->registerListener(eventQueue->getId(),true); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return PusServiceBase::initialize(); +} diff --git a/pus/Service5EventReporting.h b/pus/Service5EventReporting.h new file mode 100644 index 00000000..79b7c5e7 --- /dev/null +++ b/pus/Service5EventReporting.h @@ -0,0 +1,86 @@ +#ifndef FRAMEWORK_PUS_SERVICE5EVENTREPORTING_H_ +#define FRAMEWORK_PUS_SERVICE5EVENTREPORTING_H_ + +#include +#include + +/** + * @brief Report on-board events like information or errors + * @details + * Full Documentation: ECSS-E70-41A p.79 + * Implements the PusServiceBase template class. + * Documentation: Dissertation Baetz p.135,136 + * + * This service provides for the reporting to the service user of information of + * operational significance. + * 1. reporting of failures or anomalies detected on-board; + * 2. reporting of autonomous on-board actions; + * 3. reporting of normal progress of operations and activities, e.g. + * detection of events which are not anomalous (such as payload events), + * reaching of predefined steps in an operation. Some reports can combine + * more than one of these events. + * + * Minimum capabilities of this service: + * + * - TM[5,1]: Normal/Progress Report + * - TM[5,2]: Error/Anomaly Report - Low Severity + * - TM[5,3]: Error/Anomaly Report - Medium Severity + * - TM[5,4]: Error/Anomaly Report - High Severity + * + * Events can be translated by using translator files located in + * /config/objects/ and /config/events/. Description to events can be added by + * adding a comment behind the event definition with [//!<] as leading string + * + * Additional capabilities of this service: + * + * - TC[5,5]: Enable Event Report Generation (Req. 6) + * - TC[5,6]: Disable Event Report Generation (Req. 5) + * @author R. Mueller + * @ingroup pus_services + */ +class Service5EventReporting: public PusServiceBase { +public: + + Service5EventReporting(object_id_t objectId, uint16_t apid, + uint8_t serviceId, size_t maxNumberReportsPerCycle = 10); + virtual ~Service5EventReporting(); + + /*** + * Check for events and generate event reports if required. + * @return + */ + ReturnValue_t performService() override; + + /*** + * Turn event generation on or off. + * @return + */ + ReturnValue_t handleRequest(uint8_t subservice) override; + + /** + * The default PusServiceBase initialize has been overridden but is still + * executed. Registers this service as a listener for events at the + * EventManager. + * @return + */ + ReturnValue_t initialize() override; + + enum Subservice: uint8_t { + NORMAL_REPORT = 1, //!< [EXPORT] : [REPLY] Generate normal report + ERROR_LOW_SEVERITY = 2, //!< [EXPORT] : [REPLY] Generate error report with low severity + ERROR_MED_SEVERITY = 3, //!< [EXPORT] : [REPLY] Generate error report with medium severity + ERROR_HIGH_SEVERITY = 4, //!< [EXPORT] : [REPLY] Generate error report with high severity + ENABLE = 5, //!< [EXPORT] : [COMMAND] Enable report generation + DISABLE = 6 //!< [EXPORT] : [COMMAND] Disable report generation + }; + +private: + uint16_t packetSubCounter = 0; + MessageQueueIF* eventQueue = nullptr; + bool enableEventReport = true; + const uint8_t maxNumberReportsPerCycle; + + ReturnValue_t generateEventReport(EventMessage message); +}; + +#endif /* MISSION_PUS_SERVICE5EVENTREPORTING_H_ */ diff --git a/pus/Service8FunctionManagement.cpp b/pus/Service8FunctionManagement.cpp new file mode 100644 index 00000000..812398b9 --- /dev/null +++ b/pus/Service8FunctionManagement.cpp @@ -0,0 +1,135 @@ +#include +#include + +#include +#include +#include +#include +#include + +Service8FunctionManagement::Service8FunctionManagement(object_id_t object_id, + uint16_t apid, uint8_t serviceId, uint8_t numParallelCommands, + uint16_t commandTimeoutSeconds): + CommandingServiceBase(object_id, apid, serviceId, numParallelCommands, + commandTimeoutSeconds) {} + +Service8FunctionManagement::~Service8FunctionManagement() {} + + +ReturnValue_t Service8FunctionManagement::isValidSubservice( + uint8_t subservice) { + switch(static_cast(subservice)) { + case Subservice::DIRECT_COMMANDING: + return HasReturnvaluesIF::RETURN_OK; + default: + return AcceptsTelecommandsIF::INVALID_SUBSERVICE; + } +} + +ReturnValue_t Service8FunctionManagement::getMessageQueueAndObject( + uint8_t subservice, const uint8_t* tcData, size_t tcDataLen, + MessageQueueId_t* id, object_id_t* objectId) { + if(tcDataLen < sizeof(object_id_t)) { + return CommandingServiceBase::INVALID_TC; + } + SerializeAdapter::deSerialize(objectId, &tcData, + &tcDataLen, SerializeIF::Endianness::BIG); + + return checkInterfaceAndAcquireMessageQueue(id,objectId); +} + +ReturnValue_t Service8FunctionManagement::checkInterfaceAndAcquireMessageQueue( + MessageQueueId_t* messageQueueToSet, object_id_t* objectId) { + // check HasActionIF property of target + HasActionsIF* possibleTarget = objectManager->get(*objectId); + if(possibleTarget == nullptr){ + return CommandingServiceBase::INVALID_OBJECT; + } + *messageQueueToSet = possibleTarget->getCommandQueue(); + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t Service8FunctionManagement::prepareCommand( + CommandMessage* message, uint8_t subservice, const uint8_t* tcData, + size_t tcDataLen, uint32_t* state, object_id_t objectId) { + return prepareDirectCommand(dynamic_cast(message), + tcData, tcDataLen); +} + +ReturnValue_t Service8FunctionManagement::prepareDirectCommand( + CommandMessage *message, const uint8_t *tcData, size_t tcDataLen) { + // Create direct command instance by extracting data from Telecommand + DirectCommand command(tcData,tcDataLen); + + // store additional parameters into the IPC Store + store_address_t parameterAddress; + ReturnValue_t result = IPCStore->addData(¶meterAddress, + command.getParameters(),command.getParametersSize()); + + // setCommand expects a Command Message, an Action ID and a store adress + // pointing to additional parameters + ActionMessage::setCommand(message,command.getActionId(),parameterAddress); + return result; +} + + +ReturnValue_t Service8FunctionManagement::handleReply( + const CommandMessage* reply, Command_t previousCommand, + uint32_t* state, CommandMessage* optionalNextCommand, + object_id_t objectId, bool* isStep) { + Command_t replyId = reply->getCommand(); + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + ActionId_t actionId = ActionMessage::getActionId(reply); + ReturnValue_t returnCode = ActionMessage::getReturnCode(reply); + + switch(replyId) { + case ActionMessage::COMPLETION_SUCCESS: { + DirectReply completionReply(objectId, actionId,returnCode); + result = CommandingServiceBase::EXECUTION_COMPLETE; + break; + } + case ActionMessage::STEP_SUCCESS: { + *isStep = true; + result = HasReturnvaluesIF::RETURN_OK; + break; + } + case ActionMessage::DATA_REPLY: { + result = handleDataReply(reply, objectId, actionId); + break; + } + case ActionMessage::STEP_FAILED: + *isStep = true; + /*No break, falls through*/ + case ActionMessage::COMPLETION_FAILED: + result = ActionMessage::getReturnCode(reply); + break; + default: + result = INVALID_REPLY; + } + return result; +} + +ReturnValue_t Service8FunctionManagement::handleDataReply( + const CommandMessage* reply, object_id_t objectId, + ActionId_t actionId) { + store_address_t storeId = ActionMessage::getStoreId(reply); + size_t size = 0; + const uint8_t * buffer = nullptr; + ReturnValue_t result = IPCStore->getData(storeId, &buffer, &size); + if(result != RETURN_OK) { + sif::error << "Service 8: Could not retrieve data for data reply" + << std::endl; + return result; + } + DataReply dataReply(objectId, actionId, buffer, size); + result = sendTmPacket(static_cast( + Subservice::DIRECT_COMMANDING_DATA_REPLY), &dataReply); + + auto deletionResult = IPCStore->deleteData(storeId); + if(deletionResult != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "Service8FunctionManagement::handleReply: Deletion" + << " of data in pool failed." << std::endl; + } + return result; +} diff --git a/pus/Service8FunctionManagement.h b/pus/Service8FunctionManagement.h new file mode 100644 index 00000000..e2c7a84f --- /dev/null +++ b/pus/Service8FunctionManagement.h @@ -0,0 +1,67 @@ +#ifndef FRAMEWORK_PUS_SERVICE8FUNCTIONMANAGEMENT_H_ +#define FRAMEWORK_PUS_SERVICE8FUNCTIONMANAGEMENT_H_ + +#include +#include + +/** + * @brief Functional commanding. + * Full Documentation: ECSS-E-ST-70-41C p.64, p. 451 + * Dissertation Baetz p. 115, 116, 165-167 + * + * This service provides the capability to perform functions of an + * application process and provides high-level commanding as opposed to the + * Raw Access provided by Service 2. Examples for these functions can include + * control and operation of payload or the AOCS subsystem. + * This service will be the primary means to control the spacecraft as it is + * considered safer than the Raw Access provided + * by Service 2 and is generally sufficient for most tasks. + * + * This is a gateway service. It relays device commands using the software bus. + * This service is very closely tied to the Commanding Service Base template + * class. There is constant interaction between this Service Base und a + * subclass like this service. + * + * Service Capability: + * - TC[8,128]: Direct Commanding + * - TM[8,130]: Direct Commanding Data Reply + * + * @ingroup pus_services + */ +class Service8FunctionManagement : public CommandingServiceBase +{ +public: + Service8FunctionManagement(object_id_t objectId, uint16_t apid, + uint8_t serviceId, uint8_t numParallelCommands = 4, + uint16_t commandTimeoutSeconds = 60); + virtual ~Service8FunctionManagement(); + +protected: + /* CSB abstract functions implementation . See CSB documentation. */ + ReturnValue_t isValidSubservice(uint8_t subservice) override; + ReturnValue_t getMessageQueueAndObject(uint8_t subservice, + const uint8_t *tcData, size_t tcDataLen, MessageQueueId_t *id, + object_id_t *objectId) override; + ReturnValue_t prepareCommand(CommandMessage* message, + uint8_t subservice, const uint8_t *tcData, size_t tcDataLen, + uint32_t *state, object_id_t objectId) override; + ReturnValue_t handleReply(const CommandMessage* reply, + Command_t previousCommand, uint32_t *state, + CommandMessage* optionalNextCommand, object_id_t objectId, + bool *isStep) override; + +private: + enum class Subservice { + DIRECT_COMMANDING = 128, //!< [EXPORT] : [COMMAND] Functional commanding + DIRECT_COMMANDING_DATA_REPLY = 130, //!< [EXPORT] : [REPLY] Data reply + }; + + ReturnValue_t checkInterfaceAndAcquireMessageQueue( + MessageQueueId_t* messageQueueToSet, object_id_t* objectId); + ReturnValue_t prepareDirectCommand(CommandMessage* message, + const uint8_t* tcData, size_t tcDataLen); + ReturnValue_t handleDataReply(const CommandMessage* reply, + object_id_t objectId, ActionId_t actionId); +}; + +#endif /* FRAMEWORK_PUS_SERVICE8FUNCTIONMANAGEMENT_H_ */ diff --git a/pus/servicepackets/Service1Packets.h b/pus/servicepackets/Service1Packets.h new file mode 100644 index 00000000..b01942c6 --- /dev/null +++ b/pus/servicepackets/Service1Packets.h @@ -0,0 +1,166 @@ +/** + * @defgroup spacepackets PUS Packet Definitions + * This group contains all implemented TM or TM packages that are sent to + * or sent by the OBC.They are exported later to display + * packet structures in Mission Information Base (MIB). + */ + +#ifndef MISSION_PUS_SERVICEPACKETS_SERVICE1PACKETS_H_ +#define MISSION_PUS_SERVICEPACKETS_SERVICE1PACKETS_H_ + +#include +#include + +/** + * @brief FailureReport class to serialize a failure report + * @brief Subservice 1, 3, 5, 7 + * @ingroup spacepackets + */ +class FailureReport: public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 1, 3, 5, 7 +public: + FailureReport(uint8_t failureSubtype_, uint16_t packetId_, + uint16_t packetSequenceControl_, uint8_t stepNumber_, + ReturnValue_t errorCode_, uint32_t errorParameter1_, + uint32_t errorParameter2_) : + packetId(packetId_), packetSequenceControl(packetSequenceControl_), + stepNumber(stepNumber_), errorCode(errorCode_), + errorParameter1(errorParameter1_), errorParameter2(errorParameter2_), + failureSubtype(failureSubtype_) {} + + /** + * This function is called by the FSFW when calling the tm packet send + * function and supplying the SerializeIF* as parameter + * @param buffer Object content is serialized into the buffer + * @param size + * @param max_size + * @param bigEndian + * @return + */ + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, SerializeIF::Endianness streamEndianness + ) const override { + ReturnValue_t result = SerializeAdapter::serialize(&packetId, buffer, + size, maxSize, streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = SerializeAdapter::serialize(&packetSequenceControl, buffer, + size, maxSize, streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + if (failureSubtype == TC_VERIFY::PROGRESS_FAILURE) { + result = SerializeAdapter::serialize(&stepNumber, buffer, size, + maxSize, streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + result = SerializeAdapter::serialize(&errorCode, buffer, size, + maxSize, streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = SerializeAdapter::serialize(&errorParameter1, buffer, size, + maxSize, streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + result = SerializeAdapter::serialize(&errorParameter2, buffer, size, + maxSize, streamEndianness); + return result; + } + + + virtual size_t getSerializedSize() const { + size_t size = 0; + size += SerializeAdapter::getSerializedSize(&packetId); + size += sizeof(packetSequenceControl); + if(failureSubtype==TC_VERIFY::PROGRESS_FAILURE){ + size += SerializeAdapter::getSerializedSize(&stepNumber); + } + size += SerializeAdapter::getSerializedSize(&errorCode); + size += SerializeAdapter::getSerializedSize(&errorParameter1); + size += SerializeAdapter::getSerializedSize(&errorParameter2); + return size; + } + + /** + * Deserialization is not allowed for a report. + * @param buffer + * @param size + * @param bigEndian + * @return + */ + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) override { + return HasReturnvaluesIF::RETURN_FAILED; + } +private: + uint16_t packetId; //!< [EXPORT] : [COMMENT] Packet ID of respective Telecommand + uint16_t packetSequenceControl; //!< [EXPORT] : [COMMENT] Packet SSC of respective Telecommand + uint8_t stepNumber; //!< [EXPORT] : [OPTIONAL][SUBSERVICE] 6 + ReturnValue_t errorCode; //!< [EXPORT] : [COMMENT] Error code which can be looked up in generated error code file + uint32_t errorParameter1; + uint32_t errorParameter2; + const uint8_t failureSubtype; //!< [EXPORT] : [IGNORE] +}; + +/** + * @brief Subservices 2, 4, 6, 8 + * @ingroup spacepackets + */ +class SuccessReport: public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 2, 4, 6, 8 +public: + SuccessReport(uint8_t subtype_, uint16_t packetId_, + uint16_t packetSequenceControl_,uint8_t stepNumber_) : + packetId(packetId_), packetSequenceControl(packetSequenceControl_), + stepNumber(stepNumber_), subtype(subtype_) {} + + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, SerializeIF::Endianness streamEndianness + ) const override { + ReturnValue_t result = SerializeAdapter::serialize(&packetId, buffer, + size, maxSize, streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = SerializeAdapter::serialize(&packetSequenceControl, buffer, + size, maxSize, streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + if (subtype == TC_VERIFY::PROGRESS_SUCCESS) { + result = SerializeAdapter::serialize(&stepNumber, buffer, size, + maxSize, streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + return result; + } + + virtual size_t getSerializedSize() const override { + size_t size = 0; + size += SerializeAdapter::getSerializedSize(&packetId); + size += sizeof(packetSequenceControl); + if(subtype == TC_VERIFY::PROGRESS_SUCCESS){ + size += SerializeAdapter::getSerializedSize(&stepNumber); + } + return size; + + } + + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) override { + return HasReturnvaluesIF::RETURN_FAILED; + } +private: + uint16_t packetId; //!< [EXPORT] : [COMMENT] Packet ID of respective Telecommand + uint16_t packetSequenceControl; //!< [EXPORT] : [COMMENT] Packet SSC of respective Telecommand + uint8_t stepNumber; //!< [EXPORT] : [OPTIONAL][SUBSERVICE] 6 + const uint8_t subtype; //!< [EXPORT] : [IGNORE] +}; + +#endif /* MISSION_PUS_SERVICEPACKETS_SERVICE1PACKETS_H_ */ diff --git a/pus/servicepackets/Service200Packets.h b/pus/servicepackets/Service200Packets.h new file mode 100644 index 00000000..1b5bf236 --- /dev/null +++ b/pus/servicepackets/Service200Packets.h @@ -0,0 +1,63 @@ +#ifndef FRAMEWORK_PUS_SERVICEPACKETS_SERVICE200PACKETS_H_ +#define FRAMEWORK_PUS_SERVICEPACKETS_SERVICE200PACKETS_H_ + +#include +#include +#include + +/** + * @brief Subservice 1, 2, 3, 4, 5 + * @ingroup spacepackets + */ +class ModePacket : public SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 1, 2, 6 +public: + + ModePacket() { + setLinks(); + } + + ModePacket(object_id_t objectId, Mode_t mode, Submode_t submode) : + objectId(objectId), mode(mode), submode(submode) { + setLinks(); + } + + Mode_t getMode() { + return mode.entry; + } + + Submode_t getSubmode() { + return submode.entry; + } + + // Forbid copying, pointers are used. + ModePacket(const ModePacket&) = delete; + ModePacket& operator=(const ModePacket&) = delete; +private: + + void setLinks() { + setStart(&objectId); + objectId.setNext(&mode); + mode.setNext(&submode); + } + SerializeElement objectId; //!< [EXPORT] : [COMMENT] Target or source object + SerializeElement mode; //!< [EXPORT] : [COMMENT] 0: MODE_OFF, 1: MODE_ON, 2: MODE_NORMAL, 3: MODE_RAW + SerializeElement submode; //!< [EXPORT] : [COMMENT] Usually 0, device specific submode possible +}; + +/** + * @brief Subservice 7 + * @ingroup spacepackets + */ +class CantReachModePacket: public SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 7 +public: + CantReachModePacket(object_id_t objectId, ReturnValue_t reason): + objectId(objectId), reason(reason) { + setStart(&this->objectId); + this->objectId.setNext(&this->reason); + } + + SerializeElement objectId; //!< [EXPORT] : [COMMENT] Reply source object + SerializeElement reason; //!< [EXPORT] : [COMMENT] Reason the mode could not be reached +}; + +#endif /* FRAMEWORK_PUS_SERVICEPACKETS_SERVICE200PACKETS_H_ */ diff --git a/pus/servicepackets/Service2Packets.h b/pus/servicepackets/Service2Packets.h new file mode 100644 index 00000000..f292611e --- /dev/null +++ b/pus/servicepackets/Service2Packets.h @@ -0,0 +1,76 @@ +#ifndef FRAMEWORK_PUS_SERVICEPACKETS_SERVICE2PACKETS_H_ +#define FRAMEWORK_PUS_SERVICEPACKETS_SERVICE2PACKETS_H_ + +#include +#include +#include +#include + +/** + * @brief Subservice 128 + * @ingroup spacepackets + */ +class RawCommand { //!< [EXPORT] : [SUBSERVICE] 128 +public: + RawCommand(const uint8_t* buffer, size_t size) { + // Deserialize Adapter to get correct endianness + SerializeAdapter::deSerialize(&objectId, &buffer, &size, + SerializeIF::Endianness::BIG); + commandBuffer = buffer; + // size is decremented by AutoSerializeAdapter, + // remaining size is data size + dataSize = size; + } + object_id_t getObjectId() const { + return objectId; + } + + const uint8_t* getCommand() { + return commandBuffer; + } + + size_t getCommandSize() const { + return dataSize; + } +private: + object_id_t objectId = 0; + const uint8_t* commandBuffer = nullptr; //!< [EXPORT] : [MAXSIZE] 256 Bytes + size_t dataSize = 0; //!< [EXPORT] : [IGNORE] +}; + + +/** + * @brief Subservice 129: Command packet to set wiretapping mode + * @ingroup spacepackets + */ +class WiretappingToggle: public SerialLinkedListAdapter{ //!< [EXPORT] : [SUBSERVICE] 129 +public: + static const size_t WIRETAPPING_COMMAND_SIZE = 5; + WiretappingToggle(){ + setStart(&objectId); + objectId.setNext(&wiretappingMode); + } + + uint8_t getWiretappingMode() const { + return wiretappingMode.entry; + } +private: + SerializeElement objectId; + SerializeElement wiretappingMode; //!< [EXPORT] : [INPUT] Mode 0: OFF, Mode 1: RAW +}; + + +/** + * @brief Subservices 130 and 131: TM packets + * @ingroup spacepackets + */ +class WiretappingPacket { //!< [EXPORT] : [SUBSERVICE] 130, 131 +public: + object_id_t objectId; //!< [EXPORT] : [COMMENT] Object ID of source object + const uint8_t* data; //!< [EXPORT] : [MAXSIZE] Raw Command Max. Size + WiretappingPacket(object_id_t objectId, const uint8_t* buffer): + objectId(objectId), data(buffer) { + } +}; + +#endif /* FRAMEWORK_PUS_SERVICEPACKETS_SERVICE2PACKETS_H_ */ diff --git a/pus/servicepackets/Service5Packets.h b/pus/servicepackets/Service5Packets.h new file mode 100644 index 00000000..14219c93 --- /dev/null +++ b/pus/servicepackets/Service5Packets.h @@ -0,0 +1,76 @@ +#ifndef MISSION_PUS_SERVICEPACKETS_SERVICE5PACKETS_H_ +#define MISSION_PUS_SERVICEPACKETS_SERVICE5PACKETS_H_ + +#include +#include + + +/** + * @brief Subservice 1, 2, 3, 4 + * Structure of Event Report. + * It consists of: + * 1. Report ID(RID). This is the Event ID in the FSFW + * 2. Object ID of the reporter (e.g. subsystem) + * 2. Parameter 1 + * 3. Parameter 2 + * + * @ingroup spacepackets + */ +class EventReport: public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 1, 2, 3, 4 +public: + + EventReport(EventId_t reportId_, object_id_t objectId_, uint32_t parameter1_, + uint32_t parameter2_): + reportId(reportId_),objectId(objectId_), parameter1(parameter1_), + parameter2(parameter2_) {} + + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, + SerializeIF::Endianness streamEndianness) const override + { + ReturnValue_t result = SerializeAdapter::serialize(&reportId, buffer, + size, maxSize, streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = SerializeAdapter::serialize(&objectId, buffer, size, + maxSize, streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = SerializeAdapter::serialize(¶meter1, buffer, size, + maxSize, streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = SerializeAdapter::serialize(¶meter2, buffer, size, + maxSize, streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return result; + } + + virtual size_t getSerializedSize() const override { + uint32_t size = 0; + size += SerializeAdapter::getSerializedSize(&reportId); + size += SerializeAdapter::getSerializedSize(&objectId); + size += SerializeAdapter::getSerializedSize(¶meter1); + size += SerializeAdapter::getSerializedSize(¶meter2); + return size; + + } + + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) override { + return HasReturnvaluesIF::RETURN_FAILED; + } +private: + EventId_t reportId; + object_id_t objectId; + uint32_t parameter1; + uint32_t parameter2; +}; + + +#endif /* MISSION_PUS_SERVICEPACKETS_SERVICE5PACKETS_H_ */ diff --git a/pus/servicepackets/Service8Packets.h b/pus/servicepackets/Service8Packets.h new file mode 100644 index 00000000..5ef91280 --- /dev/null +++ b/pus/servicepackets/Service8Packets.h @@ -0,0 +1,136 @@ +/** + * \file Service8Packets.h + * + * \brief Structure of a Direct Command. + * Normal reply (subservice 130) consists of + * 1. Target object ID + * 2. Action ID (taget device has specified functions with action IDs) + * 3. Return Code + * 4. Optional step number for step replies + * + * Data reply (subservice 132) consists of + * 1. Target Object ID + * 2. Action ID + * 3. Data + * + * \date 01.07.2019 + * \author R. Mueller + */ + +#ifndef FRAMEWORK_PUS_SERVICEPACKETS_SERVICE8PACKETS_H_ +#define FRAMEWORK_PUS_SERVICEPACKETS_SERVICE8PACKETS_H_ + +#include +#include +#include +#include +#include +#include + + +/** + * \brief Subservice 128 + * \ingroup spacepackets + */ +class DirectCommand: public SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 128 +public: + //typedef uint16_t typeOfMaxData; + //static const typeOfMaxData MAX_DATA = 256; + DirectCommand(const uint8_t* dataBuffer_, uint32_t size_) { + size_t size = sizeof(objectId); + SerializeAdapter::deSerialize(&objectId,&dataBuffer_,&size, + SerializeIF::Endianness::BIG); + size = sizeof(actionId); + SerializeAdapter::deSerialize(&actionId,&dataBuffer_,&size, + SerializeIF::Endianness::BIG); + parameterBuffer = dataBuffer_; + parametersSize = size_ - sizeof(objectId) - sizeof(actionId); + } + ActionId_t getActionId() const { + return actionId; + } + + object_id_t getObjectId() const { + return objectId; + } + + const uint8_t* getParameters() { + return parameterBuffer; + } + + uint32_t getParametersSize() const { + return parametersSize; + } + +private: + DirectCommand(const DirectCommand &command); + object_id_t objectId; + ActionId_t actionId; + uint32_t parametersSize; //!< [EXPORT] : [IGNORE] + const uint8_t * parameterBuffer; //!< [EXPORT] : [MAXSIZE] 65535 Bytes + +}; + + +/** + * \brief Subservice 130 + * \ingroup spacepackets + */ +class DataReply: public SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 130 +public: + typedef uint16_t typeOfMaxDataSize; + static const uint16_t MAX_DATA_LENGTH = sizeof(typeOfMaxDataSize); + DataReply(object_id_t objectId_, ActionId_t actionId_, + const uint8_t * replyDataBuffer_ = NULL, uint16_t replyDataSize_ = 0): + objectId(objectId_), actionId(actionId_), replyData(replyDataBuffer_,replyDataSize_){ + setLinks(); + } + +private: + DataReply(const DataReply &reply); + void setLinks() { + setStart(&objectId); + objectId.setNext(&actionId); + actionId.setNext(&replyData); + } + SerializeElement objectId; + SerializeElement actionId; + SerializeElement> replyData; +}; + + +/** + * \brief Subservice 132 + * \ingroup spacepackets + */ +class DirectReply: public SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 132 +public: + typedef uint16_t typeOfMaxDataSize; + static const uint16_t MAX_DATA_LENGTH = sizeof(typeOfMaxDataSize); + + DirectReply(object_id_t objectId_, ActionId_t actionId_, ReturnValue_t returnCode_, + bool isStep_ = false, uint8_t step_ = 0): + isStep(isStep_), objectId(objectId_), actionId(actionId_), + returnCode(returnCode_),step(step_) { + setLinks(); + } +private: + + void setLinks() { + setStart(&objectId); + objectId.setNext(&actionId); + actionId.setNext(&returnCode); + if(isStep) { + returnCode.setNext(&step); + } + } + bool isDataReply; //!< [EXPORT] : [IGNORE] + bool isStep; //!< [EXPORT] : [IGNORE] + SerializeElement objectId; //!< [EXPORT] : [IGNORE] + SerializeElement actionId; //!< [EXPORT] : [IGNORE] + SerializeElement returnCode; //!< [EXPORT] : [IGNORE] + SerializeElement step; //!< [EXPORT] : [OPTIONAL] [IGNORE] + +}; + +#endif /* FRAMEWORK_PUS_SERVICEPACKETS_SERVICE8PACKETS_H_ */ From 97b01f837ceaf876ec2939150c444c23e7d6040e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 10 Jul 2020 14:29:17 +0200 Subject: [PATCH 177/653] srv8 improvements --- pus/Service8FunctionManagement.cpp | 9 +++++- pus/servicepackets/Service8Packets.h | 41 ++++++++++++++-------------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/pus/Service8FunctionManagement.cpp b/pus/Service8FunctionManagement.cpp index 812398b9..50102b04 100644 --- a/pus/Service8FunctionManagement.cpp +++ b/pus/Service8FunctionManagement.cpp @@ -59,8 +59,15 @@ ReturnValue_t Service8FunctionManagement::prepareCommand( ReturnValue_t Service8FunctionManagement::prepareDirectCommand( CommandMessage *message, const uint8_t *tcData, size_t tcDataLen) { + if(tcDataLen < sizeof(object_id_t) + sizeof(ActionId_t)) { + sif::debug << "Service8FunctionManagement::prepareDirectCommand:" + << " TC size smaller thant minimum size of direct command." + << std::endl; + return CommandingServiceBase::INVALID_TC; + } + // Create direct command instance by extracting data from Telecommand - DirectCommand command(tcData,tcDataLen); + DirectCommand command(tcData, tcDataLen); // store additional parameters into the IPC Store store_address_t parameterAddress; diff --git a/pus/servicepackets/Service8Packets.h b/pus/servicepackets/Service8Packets.h index 5ef91280..86681c14 100644 --- a/pus/servicepackets/Service8Packets.h +++ b/pus/servicepackets/Service8Packets.h @@ -8,10 +8,7 @@ * 3. Return Code * 4. Optional step number for step replies * - * Data reply (subservice 132) consists of - * 1. Target Object ID - * 2. Action ID - * 3. Data + * * \date 01.07.2019 * \author R. Mueller @@ -29,23 +26,21 @@ /** - * \brief Subservice 128 - * \ingroup spacepackets + * @brief Subservice 128 + * @ingroup spacepackets */ class DirectCommand: public SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 128 public: - //typedef uint16_t typeOfMaxData; - //static const typeOfMaxData MAX_DATA = 256; - DirectCommand(const uint8_t* dataBuffer_, uint32_t size_) { - size_t size = sizeof(objectId); - SerializeAdapter::deSerialize(&objectId,&dataBuffer_,&size, + + DirectCommand(const uint8_t* tcData, size_t size) { + SerializeAdapter::deSerialize(&objectId, &tcData, &size, SerializeIF::Endianness::BIG); - size = sizeof(actionId); - SerializeAdapter::deSerialize(&actionId,&dataBuffer_,&size, + SerializeAdapter::deSerialize(&actionId, &tcData, &size, SerializeIF::Endianness::BIG); - parameterBuffer = dataBuffer_; - parametersSize = size_ - sizeof(objectId) - sizeof(actionId); + parameterBuffer = tcData; + parametersSize = size; } + ActionId_t getActionId() const { return actionId; } @@ -73,8 +68,12 @@ private: /** - * \brief Subservice 130 - * \ingroup spacepackets + * @brief Subservice 130 + * Data reply (subservice 130) consists of + * 1. Target Object ID + * 2. Action ID + * 3. Data + * @ingroup spacepackets */ class DataReply: public SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 130 public: @@ -100,8 +99,10 @@ private: /** - * \brief Subservice 132 - * \ingroup spacepackets + * @brief Subservice 132 + * @details + * Not used yet. Telecommand Verification takes care of this. + * @ingroup spacepackets */ class DirectReply: public SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 132 public: @@ -124,7 +125,7 @@ private: returnCode.setNext(&step); } } - bool isDataReply; //!< [EXPORT] : [IGNORE] + bool isStep; //!< [EXPORT] : [IGNORE] SerializeElement objectId; //!< [EXPORT] : [IGNORE] SerializeElement actionId; //!< [EXPORT] : [IGNORE] From 85d24b9dfef5b13b8ae5dd4ffd8eadf60c38fd8b Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 10 Jul 2020 14:31:58 +0200 Subject: [PATCH 178/653] removed file header comment --- pus/servicepackets/Service8Packets.h | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/pus/servicepackets/Service8Packets.h b/pus/servicepackets/Service8Packets.h index 86681c14..8ea0d108 100644 --- a/pus/servicepackets/Service8Packets.h +++ b/pus/servicepackets/Service8Packets.h @@ -1,19 +1,3 @@ -/** - * \file Service8Packets.h - * - * \brief Structure of a Direct Command. - * Normal reply (subservice 130) consists of - * 1. Target object ID - * 2. Action ID (taget device has specified functions with action IDs) - * 3. Return Code - * 4. Optional step number for step replies - * - - * - * \date 01.07.2019 - * \author R. Mueller - */ - #ifndef FRAMEWORK_PUS_SERVICEPACKETS_SERVICE8PACKETS_H_ #define FRAMEWORK_PUS_SERVICEPACKETS_SERVICE8PACKETS_H_ From 72c9ef1089ddc3108c999b9b5aec01bf8bb26376 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 13 Jul 2020 02:12:11 +0200 Subject: [PATCH 179/653] size_t replacement --- health/HealthTableIF.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/health/HealthTableIF.h b/health/HealthTableIF.h index 6fdfc2c0..a850a804 100644 --- a/health/HealthTableIF.h +++ b/health/HealthTableIF.h @@ -17,7 +17,7 @@ public: HasHealthIF::HealthState initilialState = HasHealthIF::HEALTHY) = 0; virtual uint32_t getPrintSize() = 0; - virtual void printAll(uint8_t *pointer, uint32_t maxSize) = 0; + virtual void printAll(uint8_t *pointer, size_t maxSize) = 0; protected: virtual ReturnValue_t iterate(std::pair *value, bool reset = false) = 0; From 3a2dc5eeb60d3b06d3e77a29b433482cb53f94f0 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 13 Jul 2020 13:33:12 +0200 Subject: [PATCH 180/653] new tmtc unix udp bridge --- osal/linux/TcUnixUdpPollingTask.cpp | 137 +++++++++++++++++++++++ osal/linux/TcUnixUdpPollingTask.h | 67 +++++++++++ osal/linux/TmTcUnixUdpBridge.cpp | 168 ++++++++++++++++++++++++++++ osal/linux/TmTcUnixUdpBridge.h | 48 ++++++++ 4 files changed, 420 insertions(+) create mode 100644 osal/linux/TcUnixUdpPollingTask.cpp create mode 100644 osal/linux/TcUnixUdpPollingTask.h create mode 100644 osal/linux/TmTcUnixUdpBridge.cpp create mode 100644 osal/linux/TmTcUnixUdpBridge.h diff --git a/osal/linux/TcUnixUdpPollingTask.cpp b/osal/linux/TcUnixUdpPollingTask.cpp new file mode 100644 index 00000000..8cf7b285 --- /dev/null +++ b/osal/linux/TcUnixUdpPollingTask.cpp @@ -0,0 +1,137 @@ +#include +#include + +TcUnixUdpPollingTask::TcUnixUdpPollingTask(object_id_t objectId, + object_id_t tmtcUnixUdpBridge, size_t frameSize, + double timeoutSeconds): SystemObject(objectId), + tmtcBridgeId(tmtcUnixUdpBridge) { + + if(frameSize > 0) { + this->frameSize = frameSize; + } + else { + this->frameSize = DEFAULT_MAX_FRAME_SIZE; + } + + // Set up reception buffer with specified frame size. + // For now, it is assumed that only one frame is held in the buffer! + receptionBuffer.reserve(this->frameSize); + receptionBuffer.resize(this->frameSize); + + if(timeoutSeconds == -1) { + receptionTimeout = DEFAULT_TIMEOUT; + } + else { + receptionTimeout = timevalOperations::toTimeval(timeoutSeconds); + } +} + +TcUnixUdpPollingTask::~TcUnixUdpPollingTask() {} + +ReturnValue_t TcUnixUdpPollingTask::performOperation(uint8_t opCode) { + // Poll for new UDP datagrams in permanent loop. + while(1) { + //! Sender Address is cached here. + struct sockaddr_in senderAddress; + socklen_t senderSockLen = 0; + ssize_t bytesReceived = recvfrom(serverUdpSocket, + receptionBuffer.data(), frameSize, receptionFlags, + reinterpret_cast(&senderAddress), &senderSockLen); + if(bytesReceived < 0) { + // handle error + sif::error << "TcSocketPollingTask::performOperation: Reception" + "error." << std::endl; + handleReadError(); + + continue; + } +// sif::debug << "TcSocketPollingTask::performOperation: " << bytesReceived +// << " bytes received" << std::endl; + + ReturnValue_t result = handleSuccessfullTcRead(bytesReceived); + if(result != HasReturnvaluesIF::RETURN_FAILED) { + + } + tmtcBridge->registerCommConnect(); + tmtcBridge->checkAndSetClientAddress(senderAddress); + } + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t TcUnixUdpPollingTask::handleSuccessfullTcRead(size_t bytesRead) { + store_address_t storeId; + ReturnValue_t result = tcStore->addData(&storeId, + receptionBuffer.data(), bytesRead); + // arrayprinter::print(receptionBuffer.data(), bytesRead); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "TcSerialPollingTask::transferPusToSoftwareBus: Data " + "storage failed" << std::endl; + sif::error << "Packet size: " << bytesRead << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + TmTcMessage message(storeId); + + result = MessageQueueSenderIF::sendMessage(targetTcDestination, &message); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "Serial Polling: Sending message to queue failed" + << std::endl; + tcStore->deleteData(storeId); + } + return result; +} + +ReturnValue_t TcUnixUdpPollingTask::initialize() { + tcStore = objectManager->get(objects::TC_STORE); + if (tcStore == nullptr) { + sif::error << "TcSerialPollingTask::initialize: TC Store uninitialized!" + << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + + tmtcBridge = objectManager->get(tmtcBridgeId); + if(tmtcBridge == nullptr) { + sif::error << "TcSocketPollingTask::TcSocketPollingTask: Invalid" + " TMTC bridge object!" << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + + serverUdpSocket = tmtcBridge->serverSocket; + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t TcUnixUdpPollingTask::initializeAfterTaskCreation() { + // Initialize the destination after task creation. This ensures + // that the destination will be set in the TMTC bridge. + targetTcDestination = tmtcBridge->getRequestQueue(); + return HasReturnvaluesIF::RETURN_OK; +} + +void TcUnixUdpPollingTask::setTimeout(double timeoutSeconds) { + timeval tval; + tval = timevalOperations::toTimeval(timeoutSeconds); + int result = setsockopt(serverUdpSocket, SOL_SOCKET, SO_RCVTIMEO, + &tval, sizeof(receptionTimeout)); + if(result == -1) { + sif::error << "TcSocketPollingTask::TcSocketPollingTask: Setting " + "receive timeout failed with " << strerror(errno) << std::endl; + } +} + +void TcUnixUdpPollingTask::handleReadError() { + switch(errno) { + case(EAGAIN): { + // todo: When working in timeout mode, this will occur more often + // and is not an error. + sif::error << "TcUnixUdpPollingTask::handleReadError: Timeout." + << std::endl; + break; + } + default: { + sif::error << "TcUnixUdpPollingTask::handleReadError: " + << strerror(errno) << std::endl; + } + } +} diff --git a/osal/linux/TcUnixUdpPollingTask.h b/osal/linux/TcUnixUdpPollingTask.h new file mode 100644 index 00000000..d8de1458 --- /dev/null +++ b/osal/linux/TcUnixUdpPollingTask.h @@ -0,0 +1,67 @@ +#ifndef FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ +#define FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ + +#include +#include +#include + +#include +#include + +/** + * @brief This class can be used to implement the polling of a Unix socket, + * using UDP for now. + * @details + * The task will be blocked while the specified number of bytes has not been + * received, so TC reception is handled inside a separate task. + * This class caches the IP address of the sender. It is assumed there + * is only one sender for now. + */ +class TcUnixUdpPollingTask: public SystemObject, + public ExecutableObjectIF { + friend class TmTcUnixUdpBridge; +public: + static constexpr size_t DEFAULT_MAX_FRAME_SIZE = 2048; + //! 0.5 default milliseconds timeout for now. + static constexpr timeval DEFAULT_TIMEOUT = {.tv_sec = 0, .tv_usec = 500}; + + TcUnixUdpPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge, + size_t frameSize = 0, double timeoutSeconds = -1); + virtual~ TcUnixUdpPollingTask(); + + /** + * Turn on optional timeout for UDP polling. In the default mode, + * the receive function will block until a packet is received. + * @param timeoutSeconds + */ + void setTimeout(double timeoutSeconds); + + virtual ReturnValue_t performOperation(uint8_t opCode) override; + virtual ReturnValue_t initialize() override; + virtual ReturnValue_t initializeAfterTaskCreation() override; + +protected: + StorageManagerIF* tcStore = nullptr; + +private: + //! TMTC bridge is cached. + object_id_t tmtcBridgeId = objects::NO_OBJECT; + TmTcUnixUdpBridge* tmtcBridge = nullptr; + MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE; + //! Reception flags: https://linux.die.net/man/2/recvfrom. + int receptionFlags = 0; + + //! Server socket, which is member of TMTC bridge and is assigned in + //! constructor + int serverUdpSocket = 0; + + std::vector receptionBuffer; + + size_t frameSize = 0; + timeval receptionTimeout; + + ReturnValue_t handleSuccessfullTcRead(size_t bytesRead); + void handleReadError(); +}; + +#endif /* FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ */ diff --git a/osal/linux/TmTcUnixUdpBridge.cpp b/osal/linux/TmTcUnixUdpBridge.cpp new file mode 100644 index 00000000..92fbbdfa --- /dev/null +++ b/osal/linux/TmTcUnixUdpBridge.cpp @@ -0,0 +1,168 @@ +#include +#include +#include + +#include +#include + +TmTcUnixUdpBridge::TmTcUnixUdpBridge(object_id_t objectId, + object_id_t tcDestination, object_id_t tmStoreId, object_id_t tcStoreId, + uint16_t serverPort, uint16_t clientPort): + TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) { + mutex = MutexFactory::instance()->createMutex(); + + uint16_t setServerPort = DEFAULT_UDP_SERVER_PORT; + if(serverPort != 0xFFFF) { + setServerPort = serverPort; + } + + uint16_t setClientPort = DEFAULT_UDP_CLIENT_PORT; + if(clientPort != 0xFFFF) { + setClientPort = clientPort; + } + + // Set up UDP socket: https://man7.org/linux/man-pages/man7/ip.7.html + //clientSocket = socket(AF_INET, SOCK_DGRAM, 0); + serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if(socket < 0) { + sif::error << "TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not open" + " UDP socket!" << std::endl; + handleSocketError(); + return; + } + + serverAddress.sin_family = AF_INET; + + // Accept packets from any interface. + //serverAddress.sin_addr.s_addr = inet_addr("127.73.73.0"); + serverAddress.sin_addr.s_addr = htonl(INADDR_ANY); + serverAddress.sin_port = htons(setServerPort); + serverAddressLen = sizeof(serverAddress); + setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &serverSocketOptions, + sizeof(serverSocketOptions)); + + clientAddress.sin_family = AF_INET; + clientAddress.sin_addr.s_addr = htonl(INADDR_ANY); + clientAddress.sin_port = htons(setClientPort); + clientAddressLen = sizeof(clientAddress); + + int result = bind(serverSocket, + reinterpret_cast(&serverAddress), + serverAddressLen); + if(result == -1) { + sif::error << "TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not bind " + "local port " << setServerPort << " to server socket!" + << std::endl; + handleBindError(); + return; + } +} + +TmTcUnixUdpBridge::~TmTcUnixUdpBridge() { +} + +ReturnValue_t TmTcUnixUdpBridge::sendTm(const uint8_t *data, size_t dataLen) { + int flags = 0; + + clientAddress.sin_addr.s_addr = htons(INADDR_ANY); + //clientAddress.sin_addr.s_addr = inet_addr("127.73.73.1"); + clientAddressLen = sizeof(serverAddress); + +// char ipAddress [15]; +// sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET, +// &clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; + + ssize_t bytesSent = sendto(serverSocket, data, dataLen, flags, + reinterpret_cast(&clientAddress), clientAddressLen); + if(bytesSent < 0) { + sif::error << "TmTcUnixUdpBridge::sendTm: Send operation failed." + << std::endl; + handleSendError(); + } +// sif::debug << "TmTcUnixUdpBridge::sendTm: " << bytesSent << " bytes were" +// " sent." << std::endl; + return HasReturnvaluesIF::RETURN_OK; +} + +void TmTcUnixUdpBridge::checkAndSetClientAddress(sockaddr_in newAddress) { + MutexHelper lock(mutex, 10); + +// char ipAddress [15]; +// sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET, +// &newAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; +// sif::debug << "IP Address Old: " << inet_ntop(AF_INET, +// &clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; + + // Set new IP address if it has changed. + if(clientAddress.sin_addr.s_addr != newAddress.sin_addr.s_addr) { + clientAddress.sin_addr.s_addr = newAddress.sin_addr.s_addr; + clientAddressLen = sizeof(clientAddress); + } +} + +void TmTcUnixUdpBridge::handleSocketError() { + + // See: https://man7.org/linux/man-pages/man2/socket.2.html + switch(errno) { + case(EACCES): + case(EINVAL): + case(EMFILE): + case(ENFILE): + case(EAFNOSUPPORT): + case(ENOBUFS): + case(ENOMEM): + case(EPROTONOSUPPORT): + sif::error << "TmTcUnixBridge::handleSocketError: Socket creation failed" + << " with " << strerror(errno) << std::endl; + break; + default: + sif::error << "TmTcUnixBridge::handleSocketError: Unknown error" + << std::endl; + break; + } +} + +void TmTcUnixUdpBridge::handleBindError() { + // See: https://man7.org/linux/man-pages/man2/bind.2.html + switch(errno) { + case(EACCES): { + /* + Ephermeral ports can be shown with following command: + sysctl -A | grep ip_local_port_range + */ + sif::error << "TmTcUnixBridge::handleBindError: Port access issue." + "Ports 1-1024 are reserved on UNIX systems and require root " + "rights while ephermeral ports should not be used as well." + << std::endl; + } + break; + case(EADDRINUSE): + case(EBADF): + case(EINVAL): + case(ENOTSOCK): + case(EADDRNOTAVAIL): + case(EFAULT): + case(ELOOP): + case(ENAMETOOLONG): + case(ENOENT): + case(ENOMEM): + case(ENOTDIR): + case(EROFS): { + sif::error << "TmTcUnixBridge::handleBindError: Socket creation failed" + << " with " << strerror(errno) << std::endl; + break; + } + default: + sif::error << "TmTcUnixBridge::handleBindError: Unknown error" + << std::endl; + break; + } +} + +void TmTcUnixUdpBridge::handleSendError() { + switch(errno) { + default: + sif::error << "Error: " << strerror(errno) << std::endl; + } +} + diff --git a/osal/linux/TmTcUnixUdpBridge.h b/osal/linux/TmTcUnixUdpBridge.h new file mode 100644 index 00000000..dbddc6c3 --- /dev/null +++ b/osal/linux/TmTcUnixUdpBridge.h @@ -0,0 +1,48 @@ +#ifndef FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ +#define FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ + +#include +#include +#include +#include +#include + +class TmTcUnixUdpBridge: public TmTcBridge { + friend class TcUnixUdpPollingTask; +public: + // The ports chosen here should not be used by any other process. + // List of used ports on Linux: /etc/services + static constexpr uint16_t DEFAULT_UDP_SERVER_PORT = 7301; + static constexpr uint16_t DEFAULT_UDP_CLIENT_PORT = 7302; + + TmTcUnixUdpBridge(object_id_t objectId, object_id_t tcDestination, + object_id_t tmStoreId, object_id_t tcStoreId, + uint16_t serverPort = 0xFFFF,uint16_t clientPort = 0xFFFF); + virtual~ TmTcUnixUdpBridge(); + + void checkAndSetClientAddress(sockaddr_in clientAddress); + +protected: + virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override; + +private: + int serverSocket = 0; + + const int serverSocketOptions = 0; + + struct sockaddr_in clientAddress; + socklen_t clientAddressLen = 0; + + struct sockaddr_in serverAddress; + socklen_t serverAddressLen = 0; + + //! Access to the client address is mutex protected as it is set + //! by another task. + MutexIF* mutex; + + void handleSocketError(); + void handleBindError(); + void handleSendError(); +}; + +#endif /* FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ */ From 14f86422e366390583a8070f685b390c2eccb04f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 13 Jul 2020 19:47:31 +0200 Subject: [PATCH 181/653] additional size_t replacement --- tmtcservices/CommandingServiceBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index 4277de6f..0c5f5eab 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -267,7 +267,7 @@ ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice, object_id_t objectId, const uint8_t *data, size_t dataLen) { uint8_t buffer[sizeof(object_id_t)]; uint8_t* pBuffer = buffer; - uint32_t size = 0; + size_t size = 0; SerializeAdapter::serialize(&objectId, &pBuffer, &size, sizeof(object_id_t), SerializeIF::Endianness::BIG); TmPacketStored tmPacketStored(this->apid, this->service, subservice, From d7e157d90817d26a1546d78fec56d658073465ad Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 13 Jul 2020 19:53:44 +0200 Subject: [PATCH 182/653] switch setLast and setEnd --- container/SinglyLinkedList.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/container/SinglyLinkedList.h b/container/SinglyLinkedList.h index 618a21e1..7d5fc4a9 100644 --- a/container/SinglyLinkedList.h +++ b/container/SinglyLinkedList.h @@ -58,7 +58,7 @@ public: this->next = next; } - virtual void setLast() { + virtual void setEnd() { this->next = nullptr; } @@ -124,8 +124,8 @@ public: currentElement->setNext(nextElement); } - void setEnd(LinkedElement* lastElement) { - lastElement->setLast(); + void setLast(LinkedElement* lastElement) { + lastElement->setEnd(); } void insertElement(LinkedElement* element, size_t position) { From ef2a44c683fe0d236dfa55ad935c09d8f7472f2e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 13 Jul 2020 22:15:38 +0200 Subject: [PATCH 183/653] added back inttypes.h for cleaner code --- timemanager/CCSDSTime.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/timemanager/CCSDSTime.cpp b/timemanager/CCSDSTime.cpp index 47cab911..71b2539d 100644 --- a/timemanager/CCSDSTime.cpp +++ b/timemanager/CCSDSTime.cpp @@ -205,9 +205,10 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* uint8_t hour; uint8_t minute; float second; - //try Code A (yyyy-mm-dd) - int count = sscanf((char *) from, "%4hi-%2hhi-%2hiT%2hhi:%2hhi:%fZ", &year, - &month, &day, &hour, &minute, &second); + //try Code A (yyyy-mm-dd) + int count = sscanf((char *) from, "%4" SCNu16 "-%2" SCNu8 "-%2" SCNu16 + "T%2" SCNu8 ":%2" SCNu8 ":%fZ", &year, &month, &day, + &hour, &minute, &second); if (count == 6) { to->year = year; to->month = month; @@ -219,9 +220,9 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* return RETURN_OK; } - //try Code B (yyyy-ddd) - count = sscanf((char *) from, "%4hi-%3hiT%2hhi:%2hhi:%fZ", &year, &day, - &hour, &minute, &second); + //try Code B (yyyy-ddd) + count = sscanf((char *) from, "%4" SCNu16 "-%3" SCNu16 "T%2" SCNu8 + ":%2" SCNu8 ":%fZ", &year, &day, &hour, &minute, &second); if (count == 5) { uint8_t tempDay; ReturnValue_t result = CCSDSTime::convertDaysOfYear(day, year, &month, From aca0c94c514a3cfb6401f291e1021b2fe6c662d5 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 16 Jul 2020 11:47:11 +0200 Subject: [PATCH 184/653] CSB new update init --- tmtcservices/CommandingServiceBase.cpp | 396 ++++++++++++++----------- tmtcservices/CommandingServiceBase.h | 256 ++++++++++------ 2 files changed, 379 insertions(+), 273 deletions(-) diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index aa41f334..4c9b5375 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -1,26 +1,35 @@ -/* - * CommandingServiceBase.cpp - * - * Created on: 28.08.2019 - * Author: gaisser - */ +#include +#include +#include #include +#include +#include +#include +#include + +object_id_t CommandingServiceBase::defaultPacketSource = objects::NO_OBJECT; +object_id_t CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT; CommandingServiceBase::CommandingServiceBase(object_id_t setObjectId, uint16_t apid, uint8_t service, uint8_t numberOfParallelCommands, - uint16_t commandTimeout_seconds, object_id_t setPacketSource, - object_id_t setPacketDestination, size_t queueDepth) : - SystemObject(setObjectId), apid(apid), service(service), timeout_seconds( - commandTimeout_seconds), tmPacketCounter(0), IPCStore(NULL), TCStore( - NULL), commandQueue(NULL), requestQueue(NULL), commandMap( - numberOfParallelCommands), failureParameter1(0), failureParameter2( - 0), packetSource(setPacketSource), packetDestination( - setPacketDestination),executingTask(NULL) { + uint16_t commandTimeoutSeconds, size_t queueDepth) : + SystemObject(setObjectId), apid(apid), service(service), + timeoutSeconds(commandTimeoutSeconds), + commandMap(numberOfParallelCommands) { commandQueue = QueueFactory::instance()->createMessageQueue(queueDepth); requestQueue = QueueFactory::instance()->createMessageQueue(queueDepth); } +void CommandingServiceBase::setPacketSource(object_id_t packetSource) { + this->packetSource = packetSource; +} + +void CommandingServiceBase::setPacketDestination( + object_id_t packetDestination) { + this->packetDestination = packetDestination; +} + CommandingServiceBase::~CommandingServiceBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); @@ -53,12 +62,22 @@ ReturnValue_t CommandingServiceBase::initialize() { return result; } + if(packetDestination == objects::NO_OBJECT) { + packetDestination = defaultPacketDestination; + } AcceptsTelemetryIF* packetForwarding = objectManager->get(packetDestination); + + if(packetSource == objects::NO_OBJECT) { + packetSource = defaultPacketSource; + } PUSDistributorIF* distributor = objectManager->get( packetSource); - if ((packetForwarding == NULL) && (distributor == NULL)) { - return RETURN_FAILED; + + if (packetForwarding == nullptr or distributor == nullptr) { + sif::error << "CommandingServiceBase::intialize: Packet source or " + "packet destination invalid!" << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; } distributor->registerService(this); @@ -68,8 +87,10 @@ ReturnValue_t CommandingServiceBase::initialize() { IPCStore = objectManager->get(objects::IPC_STORE); TCStore = objectManager->get(objects::TC_STORE); - if ((IPCStore == NULL) || (TCStore == NULL)) { - return RETURN_FAILED; + if (IPCStore == nullptr or TCStore == nullptr) { + sif::error << "CommandingServiceBase::intialize: IPC store or TC store " + "not initialized yet!" << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; } return RETURN_OK; @@ -77,97 +98,126 @@ ReturnValue_t CommandingServiceBase::initialize() { } void CommandingServiceBase::handleCommandQueue() { - CommandMessage reply, nextCommand; - ReturnValue_t result, sendResult = RETURN_OK; - bool isStep = false; + CommandMessage reply; + ReturnValue_t result = RETURN_FAILED; for (result = commandQueue->receiveMessage(&reply); result == RETURN_OK; result = commandQueue->receiveMessage(&reply)) { - isStep = false; - typename FixedMap::Iterator iter; - if (reply.getSender() == MessageQueueIF::NO_QUEUE) { - handleUnrequestedReply(&reply); - continue; - } - if ((iter = commandMap.find(reply.getSender())) == commandMap.end()) { - handleUnrequestedReply(&reply); - continue; - } - nextCommand.setCommand(CommandMessage::CMD_NONE); - result = handleReply(&reply, iter->command, &iter->state, &nextCommand, - iter->objectId, &isStep); - switch (result) { - case EXECUTION_COMPLETE: - case RETURN_OK: - case NO_STEP_MESSAGE: - iter->command = nextCommand.getCommand(); - if (nextCommand.getCommand() != CommandMessage::CMD_NONE) { - sendResult = commandQueue->sendMessage(reply.getSender(), - &nextCommand); - } - if (sendResult == RETURN_OK) { - if (isStep) { - if (result != NO_STEP_MESSAGE) { - verificationReporter.sendSuccessReport( - TC_VERIFY::PROGRESS_SUCCESS, - iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, - iter->tcInfo.tcSequenceControl, ++iter->step); - } - } else { - verificationReporter.sendSuccessReport( - TC_VERIFY::COMPLETION_SUCCESS, - iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, - iter->tcInfo.tcSequenceControl, 0); - checkAndExecuteFifo(&iter); - } - } else { - if (isStep) { - nextCommand.clearCommandMessage(); - verificationReporter.sendFailureReport( - TC_VERIFY::PROGRESS_FAILURE, iter->tcInfo.ackFlags, - iter->tcInfo.tcPacketId, - iter->tcInfo.tcSequenceControl, sendResult, - ++iter->step, failureParameter1, failureParameter2); - } else { - nextCommand.clearCommandMessage(); - verificationReporter.sendFailureReport( - TC_VERIFY::COMPLETION_FAILURE, - iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, - iter->tcInfo.tcSequenceControl, sendResult, 0, - failureParameter1, failureParameter2); - } - failureParameter1 = 0; - failureParameter2 = 0; - checkAndExecuteFifo(&iter); - } - break; - case INVALID_REPLY: - //might be just an unrequested reply at a bad moment - handleUnrequestedReply(&reply); - break; - default: - if (isStep) { - verificationReporter.sendFailureReport( - TC_VERIFY::PROGRESS_FAILURE, iter->tcInfo.ackFlags, - iter->tcInfo.tcPacketId, iter->tcInfo.tcSequenceControl, - result, ++iter->step, failureParameter1, - failureParameter2); - } else { - verificationReporter.sendFailureReport( - TC_VERIFY::COMPLETION_FAILURE, iter->tcInfo.ackFlags, - iter->tcInfo.tcPacketId, iter->tcInfo.tcSequenceControl, - result, 0, failureParameter1, failureParameter2); - } - failureParameter1 = 0; - failureParameter2 = 0; - checkAndExecuteFifo(&iter); - break; - } - + handleCommandMessage(&reply); } } +void CommandingServiceBase::handleCommandMessage(CommandMessage* reply) { + bool isStep = false; + CommandMessage nextCommand; + CommandMapIter iter = commandMap.find(reply->getSender()); + + // handle unrequested reply first + if (reply->getSender() == MessageQueueIF::NO_QUEUE or + iter == commandMap.end()) { + handleUnrequestedReply(reply); + return; + } + nextCommand.setCommand(CommandMessage::CMD_NONE); + + + // Implemented by child class, specifies what to do with reply. + ReturnValue_t result = handleReply(reply, iter->command, &iter->state, + &nextCommand, iter->objectId, &isStep); + + /* If the child implementation does not implement special handling for + * rejected replies (RETURN_FAILED is returned), a failure verification + * will be generated with the reason as the return code and the initial + * command as failure parameter 1 */ + if(reply->getCommand() == CommandMessage::REPLY_REJECTED and + result == RETURN_FAILED) { + result = reply->getReplyRejectedReason(); + failureParameter1 = iter->command; + } + + switch (result) { + case EXECUTION_COMPLETE: + case RETURN_OK: + case NO_STEP_MESSAGE: + // handle result of reply handler implemented by developer. + handleReplyHandlerResult(result, iter, &nextCommand, reply, isStep); + break; + case INVALID_REPLY: + //might be just an unrequested reply at a bad moment + handleUnrequestedReply(reply); + break; + default: + if (isStep) { + verificationReporter.sendFailureReport( + TC_VERIFY::PROGRESS_FAILURE, iter->tcInfo.ackFlags, + iter->tcInfo.tcPacketId, iter->tcInfo.tcSequenceControl, + result, ++iter->step, failureParameter1, + failureParameter2); + } else { + verificationReporter.sendFailureReport( + TC_VERIFY::COMPLETION_FAILURE, iter->tcInfo.ackFlags, + iter->tcInfo.tcPacketId, iter->tcInfo.tcSequenceControl, + result, 0, failureParameter1, failureParameter2); + } + failureParameter1 = 0; + failureParameter2 = 0; + checkAndExecuteFifo(iter); + break; + } + +} + +void CommandingServiceBase::handleReplyHandlerResult(ReturnValue_t result, + CommandMapIter iter, CommandMessage* nextCommand, + CommandMessage* reply, bool& isStep) { + iter->command = nextCommand->getCommand(); + + // In case a new command is to be sent immediately, this is performed here. + // If no new command is sent, only analyse reply result by initializing + // sendResult as RETURN_OK + ReturnValue_t sendResult = RETURN_OK; + if (nextCommand->getCommand() != CommandMessage::CMD_NONE) { + sendResult = commandQueue->sendMessage(reply->getSender(), + nextCommand); + } + + if (sendResult == RETURN_OK) { + if (isStep and result != NO_STEP_MESSAGE) { + verificationReporter.sendSuccessReport( + TC_VERIFY::PROGRESS_SUCCESS, + iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, + iter->tcInfo.tcSequenceControl, ++iter->step); + } + else { + verificationReporter.sendSuccessReport( + TC_VERIFY::COMPLETION_SUCCESS, + iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, + iter->tcInfo.tcSequenceControl, 0); + checkAndExecuteFifo(iter); + } + } + else { + if (isStep) { + nextCommand->clearCommandMessage(); + verificationReporter.sendFailureReport( + TC_VERIFY::PROGRESS_FAILURE, iter->tcInfo.ackFlags, + iter->tcInfo.tcPacketId, + iter->tcInfo.tcSequenceControl, sendResult, + ++iter->step, failureParameter1, failureParameter2); + } else { + nextCommand->clearCommandMessage(); + verificationReporter.sendFailureReport( + TC_VERIFY::COMPLETION_FAILURE, + iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, + iter->tcInfo.tcSequenceControl, sendResult, 0, + failureParameter1, failureParameter2); + } + failureParameter1 = 0; + failureParameter2 = 0; + checkAndExecuteFifo(iter); + } +} + void CommandingServiceBase::handleRequestQueue() { TmTcMessage message; ReturnValue_t result; @@ -180,8 +230,8 @@ void CommandingServiceBase::handleRequestQueue() { address = message.getStorageId(); packet.setStoreAddress(address); - if ((packet.getSubService() == 0) - || (isValidSubservice(packet.getSubService()) != RETURN_OK)) { + if (packet.getSubService() == 0 + or isValidSubservice(packet.getSubService()) != RETURN_OK) { rejectPacket(TC_VERIFY::START_FAILURE, &packet, INVALID_SUBSERVICE); continue; } @@ -194,8 +244,7 @@ void CommandingServiceBase::handleRequestQueue() { } //Is a command already active for the target object? - typename FixedMap::Iterator iter; + CommandMapIter iter; iter = commandMap.find(queue); if (iter != commandMap.end()) { @@ -210,7 +259,7 @@ void CommandingServiceBase::handleRequestQueue() { if (result != RETURN_OK) { rejectPacket(TC_VERIFY::START_FAILURE, &packet, BUSY); } else { - startExecution(&packet, &iter); + startExecution(&packet, iter); } } @@ -218,9 +267,9 @@ void CommandingServiceBase::handleRequestQueue() { } -void CommandingServiceBase::sendTmPacket(uint8_t subservice, - const uint8_t* data, uint32_t dataLen, const uint8_t* headerData, - uint32_t headerSize) { +ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice, + const uint8_t* data, size_t dataLen, const uint8_t* headerData, + size_t headerSize) { TmPacketStored tmPacketStored(this->apid, this->service, subservice, this->tmPacketCounter, data, dataLen, headerData, headerSize); ReturnValue_t result = tmPacketStored.sendPacket( @@ -228,79 +277,79 @@ void CommandingServiceBase::sendTmPacket(uint8_t subservice, if (result == HasReturnvaluesIF::RETURN_OK) { this->tmPacketCounter++; } + return result; } -void CommandingServiceBase::sendTmPacket(uint8_t subservice, - object_id_t objectId, const uint8_t *data, uint32_t dataLen) { - uint8_t buffer[sizeof(object_id_t)]; - uint8_t* pBuffer = buffer; - size_t size = 0; - SerializeAdapter::serialize(&objectId, &pBuffer, &size, - sizeof(object_id_t), SerializeIF::Endianness::BIG); - TmPacketStored tmPacketStored(this->apid, this->service, subservice, - this->tmPacketCounter, data, dataLen, buffer, size); - ReturnValue_t result = tmPacketStored.sendPacket( - requestQueue->getDefaultDestination(), requestQueue->getId()); - if (result == HasReturnvaluesIF::RETURN_OK) { - this->tmPacketCounter++; - } - +ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice, + object_id_t objectId, const uint8_t *data, size_t dataLen) { + uint8_t buffer[sizeof(object_id_t)]; + uint8_t* pBuffer = buffer; + size_t size = 0; + SerializeAdapter::serialize(&objectId, &pBuffer, &size, + sizeof(object_id_t), SerializeIF::Endianness::BIG); + TmPacketStored tmPacketStored(this->apid, this->service, subservice, + this->tmPacketCounter, data, dataLen, buffer, size); + ReturnValue_t result = tmPacketStored.sendPacket( + requestQueue->getDefaultDestination(), requestQueue->getId()); + if (result == HasReturnvaluesIF::RETURN_OK) { + this->tmPacketCounter++; + } + return result; } -void CommandingServiceBase::sendTmPacket(uint8_t subservice, - SerializeIF* content, SerializeIF* header) { - TmPacketStored tmPacketStored(this->apid, this->service, subservice, - this->tmPacketCounter, content, header); - ReturnValue_t result = tmPacketStored.sendPacket( - requestQueue->getDefaultDestination(), requestQueue->getId()); - if (result == HasReturnvaluesIF::RETURN_OK) { - this->tmPacketCounter++; - } +ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice, + SerializeIF* content, SerializeIF* header) { + TmPacketStored tmPacketStored(this->apid, this->service, subservice, + this->tmPacketCounter, content, header); + ReturnValue_t result = tmPacketStored.sendPacket( + requestQueue->getDefaultDestination(), requestQueue->getId()); + if (result == HasReturnvaluesIF::RETURN_OK) { + this->tmPacketCounter++; + } + return result; } -void CommandingServiceBase::startExecution( - TcPacketStored *storedPacket, - typename FixedMap::Iterator *iter) { - ReturnValue_t result, sendResult = RETURN_OK; - CommandMessage message; - (*iter)->subservice = storedPacket->getSubService(); - result = prepareCommand(&message, (*iter)->subservice, - storedPacket->getApplicationData(), - storedPacket->getApplicationDataSize(), &(*iter)->state, - (*iter)->objectId); +void CommandingServiceBase::startExecution(TcPacketStored *storedPacket, + CommandMapIter iter) { + ReturnValue_t result = RETURN_OK; + CommandMessage command; + iter->subservice = storedPacket->getSubService(); + result = prepareCommand(&command, iter->subservice, + storedPacket->getApplicationData(), + storedPacket->getApplicationDataSize(), &iter->state, + iter->objectId); + ReturnValue_t sendResult = RETURN_OK; switch (result) { case RETURN_OK: - if (message.getCommand() != CommandMessage::CMD_NONE) { - sendResult = commandQueue->sendMessage((*iter).value->first, - &message); + if (command.getCommand() != CommandMessage::CMD_NONE) { + sendResult = commandQueue->sendMessage(iter.value->first, + &command); } if (sendResult == RETURN_OK) { - Clock::getUptime(&(*iter)->uptimeOfStart); - (*iter)->step = 0; -// (*iter)->state = 0; - (*iter)->subservice = storedPacket->getSubService(); - (*iter)->command = message.getCommand(); - (*iter)->tcInfo.ackFlags = storedPacket->getAcknowledgeFlags(); - (*iter)->tcInfo.tcPacketId = storedPacket->getPacketId(); - (*iter)->tcInfo.tcSequenceControl = + Clock::getUptime(&iter->uptimeOfStart); + iter->step = 0; + iter->subservice = storedPacket->getSubService(); + iter->command = command.getCommand(); + iter->tcInfo.ackFlags = storedPacket->getAcknowledgeFlags(); + iter->tcInfo.tcPacketId = storedPacket->getPacketId(); + iter->tcInfo.tcSequenceControl = storedPacket->getPacketSequenceControl(); acceptPacket(TC_VERIFY::START_SUCCESS, storedPacket); } else { - message.clearCommandMessage(); + command.clearCommandMessage(); rejectPacket(TC_VERIFY::START_FAILURE, storedPacket, sendResult); checkAndExecuteFifo(iter); } break; case EXECUTION_COMPLETE: - if (message.getCommand() != CommandMessage::CMD_NONE) { + if (command.getCommand() != CommandMessage::CMD_NONE) { //Fire-and-forget command. - sendResult = commandQueue->sendMessage((*iter).value->first, - &message); + sendResult = commandQueue->sendMessage(iter.value->first, + &command); } if (sendResult == RETURN_OK) { verificationReporter.sendSuccessReport(TC_VERIFY::START_SUCCESS, @@ -308,7 +357,7 @@ void CommandingServiceBase::startExecution( acceptPacket(TC_VERIFY::COMPLETION_SUCCESS, storedPacket); checkAndExecuteFifo(iter); } else { - message.clearCommandMessage(); + command.clearCommandMessage(); rejectPacket(TC_VERIFY::START_FAILURE, storedPacket, sendResult); checkAndExecuteFifo(iter); } @@ -335,12 +384,10 @@ void CommandingServiceBase::acceptPacket(uint8_t reportId, } -void CommandingServiceBase::checkAndExecuteFifo( - typename FixedMap::Iterator *iter) { +void CommandingServiceBase::checkAndExecuteFifo(CommandMapIter iter) { store_address_t address; - if ((*iter)->fifo.retrieve(&address) != RETURN_OK) { - commandMap.erase(iter); + if (iter->fifo.retrieve(&address) != RETURN_OK) { + commandMap.erase(&iter); } else { TcPacketStored newPacket(address); startExecution(&newPacket, iter); @@ -348,8 +395,7 @@ void CommandingServiceBase::checkAndExecuteFifo( } -void CommandingServiceBase::handleUnrequestedReply( - CommandMessage* reply) { +void CommandingServiceBase::handleUnrequestedReply(CommandMessage* reply) { reply->clearCommandMessage(); } @@ -364,18 +410,18 @@ MessageQueueId_t CommandingServiceBase::getCommandQueue() { void CommandingServiceBase::checkTimeout() { uint32_t uptime; Clock::getUptime(&uptime); - typename FixedMap::Iterator iter; + CommandMapIter iter; for (iter = commandMap.begin(); iter != commandMap.end(); ++iter) { - if ((iter->uptimeOfStart + (timeout_seconds * 1000)) < uptime) { + if ((iter->uptimeOfStart + (timeoutSeconds * 1000)) < uptime) { verificationReporter.sendFailureReport( TC_VERIFY::COMPLETION_FAILURE, iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, iter->tcInfo.tcSequenceControl, TIMEOUT); - checkAndExecuteFifo(&iter); + checkAndExecuteFifo(iter); } } } - - +void CommandingServiceBase::setTaskIF(PeriodicTaskIF* task_) { + executingTask = task_; +} diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index bf2e8242..1bd18571 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -1,40 +1,43 @@ -#ifndef COMMANDINGSERVICEBASE_H_ -#define COMMANDINGSERVICEBASE_H_ +#ifndef FRAMEWORK_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ +#define FRAMEWORK_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ -#include -#include -#include -#include #include -#include #include #include -#include -#include -#include +#include #include -#include -#include + #include -#include -#include -#include +#include +#include +#include +#include + +class TcPacketStored; + +namespace Factory{ +void setStaticFrameworkObjectIds(); +} /** - * \brief This class is the basis for all PUS Services, which have to relay Telecommands to software bus. + * @brief This class is the basis for all PUS Services, which have to + * relay Telecommands to software bus. * - * It manages Telecommand reception and the generation of Verification Reports like PUSServiceBase. - * Every class that inherits from this abstract class has to implement four adaption points: + * It manages Telecommand reception and the generation of Verification Reports + * similar to PusServiceBase. This class is used if a telecommand can't be + * handled immediately and must be relayed to the internal software bus. * - isValidSubservice * - getMessageQueueAndObject * - prepareCommand * - handleReply - * \ingroup pus_services + * @author gaisser + * @ingroup pus_services */ class CommandingServiceBase: public SystemObject, public AcceptsTelecommandsIF, public ExecutableObjectIF, public HasReturnvaluesIF { + friend void (Factory::setStaticFrameworkObjectIds)(); public: static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_SERVICE_BASE; static const ReturnValue_t EXECUTION_COMPLETE = MAKE_RETURN_CODE(1); @@ -59,10 +62,24 @@ public: */ CommandingServiceBase(object_id_t setObjectId, uint16_t apid, uint8_t service, uint8_t numberOfParallelCommands, - uint16_t commandTimeout_seconds, object_id_t setPacketSource, - object_id_t setPacketDestination, size_t queueDepth = 20); + uint16_t commandTimeoutSeconds, size_t queueDepth = 20); virtual ~CommandingServiceBase(); + /** + * This setter can be used to set the packet source individually instead + * of using the default static framework ID set in the factory. + * This should be called at object initialization and not during run-time! + * @param packetSource + */ + void setPacketSource(object_id_t packetSource); + /** + * This setter can be used to set the packet destination individually + * instead of using the default static framework ID set in the factory. + * This should be called at object initialization and not during run-time! + * @param packetDestination + */ + void setPacketDestination(object_id_t packetDestination); + /*** * This is the periodically called function. * Handle request queue for external commands. @@ -91,82 +108,111 @@ public: */ virtual MessageQueueId_t getCommandQueue(); - virtual ReturnValue_t initialize(); + virtual ReturnValue_t initialize() override; /** * Implementation of ExecutableObjectIF function * * Used to setup the reference of the task, that executes this component - * @param task_ Pointer to the taskIF of this task + * @param task Pointer to the taskIF of this task */ - virtual void setTaskIF(PeriodicTaskIF* task_){ - executingTask = task_; - }; + virtual void setTaskIF(PeriodicTaskIF* task); protected: /** * Check the target subservice * @param subservice[in] - * @return -@c RETURN_OK on success - * -@c INVALID_SUBSERVICE if service is not known + * @return + * -@c RETURN_OK Subservice valid, continue message handling + * -@c INVALID_SUBSERVICE if service is not known, rejects packet. */ 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. + * 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 Object ID is extracted and stored here - * @return - @c RETURN_OK on success - * - @c RETURN_FAILED - * - @c CSB or implementation specific return codes + * @return + * - @c RETURN_OK Cotinue message handling + * - @c RETURN_FAILED Reject the packet and generates a start failure + * verification */ virtual ReturnValue_t getMessageQueueAndObject(uint8_t subservice, - const uint8_t *tcData, uint32_t tcDataLen, MessageQueueId_t *id, + const uint8_t *tcData, size_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 object. - * It contains all necessary information for the device to execute telecommands. - * @param message[out] message to be sent to the object - * @param subservice[in] Subservice of the current communication - * @param tcData Additional data of the command - * @param tcDataLen Length of the additional data - * @param state[out] Setable state of the communication + * 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 object. It contains all necessary information + * for the device to execute telecommands. + * @param message [out] message which can be set and is sent to the object + * @param subservice Subservice of the current communication + * @param tcData Application data of command + * @param tcDataLen Application data length + * @param state [out/in] Setable state of the communication. + * communication * @param objectId Target object ID - * @return - @c RETURN_OK on success - * - @c EXECUTION_COMPLETE if exectuin is finished - * - any other return code will be part of (1,4) start failure + * @return + * - @c RETURN_OK to generate a verification start message + * - @c EXECUTION_COMPELTE Fire-and-forget command. Generate a completion + * verification message. + * - @c Anything else rejects the packets and generates a start failure + * verification. */ - virtual ReturnValue_t prepareCommand(CommandMessage *message, - uint8_t subservice, const uint8_t *tcData, uint32_t tcDataLen, + virtual ReturnValue_t prepareCommand(CommandMessage* message, + uint8_t subservice, const uint8_t *tcData, size_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 Command_t of last command - * @param state state of the communication - * @param optionalNextCommand[out] An optional next command which can be set in this function + * This function is implemented by child services to specify how replies + * to a command from another software component are handled. + * @param reply + * This is the reply which can be accessed via the command message + * interface. The internal message pointer can be passed to different + * command message implementations (see CommandMessageIF) + * @param previousCommand + * Command_t of related command + * @param state [out/in] + * Additional parameter which can be used to pass state information. + * State of the communication + * @param optionalNextCommand [out] + * An optional next command which can be set in this function * @param objectId Source object ID * @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 + * @return + * - @c RETURN_OK, @c EXECUTION_COMPLETE or @c NO_STEP_MESSAGE to + * generate TC verification success + * - @c INVALID_REPLY Calls handleUnrequestedReply + * - Anything else triggers a TC verification failure. If RETURN_FAILED + * is returned and the command ID is CommandMessage::REPLY_REJECTED, + * a failure verification message with the reason as the error parameter + * and the initial command as failure parameter 1. */ - virtual ReturnValue_t handleReply(const CommandMessage *reply, + virtual ReturnValue_t handleReply(const CommandMessage* reply, Command_t previousCommand, uint32_t *state, - CommandMessage *optionalNextCommand, object_id_t objectId, + CommandMessage* optionalNextCommand, object_id_t objectId, bool *isStep) = 0; + /** + * This function can be overidden to handle unrequested reply, + * when the reply sender ID is unknown or is not found is the command map. + * The default implementation will clear the command message and all + * its contents. + * @param reply + * Reply which is non-const so the default implementation can clear the + * message. + */ + virtual void handleUnrequestedReply(CommandMessage* reply); + + virtual void doPeriodicOperation(); + + struct CommandInfo { struct tcInfo { uint8_t ackFlags; @@ -182,84 +228,92 @@ protected: FIFO fifo; }; + using CommandMapIter = FixedMap::Iterator; + const uint16_t apid; const uint8_t service; - const uint16_t timeout_seconds; + const uint16_t timeoutSeconds; - uint8_t tmPacketCounter; + uint8_t tmPacketCounter = 0; - StorageManagerIF *IPCStore; + StorageManagerIF *IPCStore = nullptr; - StorageManagerIF *TCStore; + StorageManagerIF *TCStore = nullptr; - MessageQueueIF* commandQueue; + MessageQueueIF* commandQueue = nullptr; - MessageQueueIF* requestQueue; + MessageQueueIF* requestQueue = nullptr; VerificationReporter verificationReporter; FixedMap commandMap; - uint32_t failureParameter1; //!< May be set be children to return a more precise failure condition. - uint32_t failureParameter2; //!< May be set be children to return a more precise failure condition. + /* May be set be children to return a more precise failure condition. */ + uint32_t failureParameter1 = 0; + uint32_t failureParameter2 = 0; - object_id_t packetSource; - - object_id_t packetDestination; + static object_id_t defaultPacketSource; + object_id_t packetSource = objects::NO_OBJECT; + static object_id_t defaultPacketDestination; + object_id_t packetDestination = objects::NO_OBJECT; /** - * Pointer to the task which executes this component, is invalid before setTaskIF was called. + * Pointer to the task which executes this component, + * is invalid before setTaskIF was called. */ - PeriodicTaskIF* executingTask; + PeriodicTaskIF* executingTask = nullptr; /** - * Send TM data from pointer to data. If a header is supplied it is added before data + * @brief Send TM data from pointer to data. + * If a header is supplied it is added before data * @param subservice Number of subservice * @param data Pointer to the data in the Packet * @param dataLen Lenght of data in the Packet * @param headerData HeaderData will be placed before data * @param headerSize Size of HeaderData */ - void sendTmPacket(uint8_t subservice, const uint8_t *data, uint32_t dataLen, - const uint8_t* headerData = NULL, uint32_t headerSize = 0); + ReturnValue_t sendTmPacket(uint8_t subservice, const uint8_t *data, + size_t dataLen, const uint8_t* headerData = nullptr, + size_t headerSize = 0); /** - * To send TM packets of objects that still need to be serialized and consist of an object ID with appended data + * @brief To send TM packets of objects that still need to be serialized + * and consist of an object ID with appended data. * @param subservice Number of subservice * @param objectId ObjectId is placed before data * @param data Data to append to the packet * @param dataLen Length of Data */ - void sendTmPacket(uint8_t subservice, object_id_t objectId, - const uint8_t *data, uint32_t dataLen); + ReturnValue_t sendTmPacket(uint8_t subservice, object_id_t objectId, + const uint8_t *data, size_t dataLen); /** - * To send packets has data which is in form of a SerializeIF or Adapters implementing it + * @brief To send packets which are contained inside a class implementing + * SerializeIF. * @param subservice Number of subservice * @param content This is a pointer to the serialized packet * @param header Serialize IF header which will be placed before content */ - void sendTmPacket(uint8_t subservice, SerializeIF* content, - SerializeIF* header = NULL); + ReturnValue_t sendTmPacket(uint8_t subservice, SerializeIF* content, + SerializeIF* header = nullptr); - virtual void handleUnrequestedReply(CommandMessage *reply); - - virtual void doPeriodicOperation(); - - void checkAndExecuteFifo( - typename FixedMap::Iterator *iter); + void checkAndExecuteFifo(CommandMapIter iter); private: /** * This method handles internal execution of a command, - * once it has been started by @sa{startExecution()} in the Request Queue handler. - * 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. + * once it has been started by @sa{startExecution()} in the request + * queue handler. + * 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. Note that - * the static framework object ID @c VerificationReporter::messageReceiver needs to be set. + * 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 @@ -268,10 +322,13 @@ private: void handleCommandQueue(); /** + * @brief Handler function for request queue + * @details * Sequence of request queue handling: * isValidSubservice -> getMessageQueueAndObject -> startExecution - * Generates Start Success Reports TM[1,3] in subfunction @sa{startExecution()} - * or Start Failure Report TM[1,4] by using the TC Verification Service + * Generates a Start Success Reports TM[1,3] in subfunction + * @sa{startExecution()} or a Start Failure Report TM[1,4] by using the + * TC Verification Service. */ void handleRequestQueue(); @@ -280,8 +337,11 @@ private: void acceptPacket(uint8_t reportId, TcPacketStored* packet); - void startExecution(TcPacketStored *storedPacket, - typename FixedMap::Iterator *iter); + void startExecution(TcPacketStored *storedPacket, CommandMapIter iter); + + void handleCommandMessage(CommandMessage* reply); + void handleReplyHandlerResult(ReturnValue_t result, CommandMapIter iter, + CommandMessage* nextCommand, CommandMessage* reply, bool& isStep); void checkTimeout(); }; From 646e86ea85d8bd29f89c2568efb42e2a49e497aa Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 16 Jul 2020 11:56:48 +0200 Subject: [PATCH 185/653] dhb update init --- devicehandlers/DeviceHandlerBase.cpp | 517 +++++++++++++++++---------- devicehandlers/DeviceHandlerBase.h | 310 +++++++++------- 2 files changed, 504 insertions(+), 323 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 872310a1..cc97cd42 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -4,55 +4,69 @@ #include #include -#include -#include +#include +#include #include #include +#include +#include #include #include #include #include -object_id_t DeviceHandlerBase::powerSwitcherId = 0; -object_id_t DeviceHandlerBase::rawDataReceiverId = 0; -object_id_t DeviceHandlerBase::defaultFDIRParentId = 0; +object_id_t DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT; +object_id_t DeviceHandlerBase::rawDataReceiverId = objects::NO_OBJECT; +object_id_t DeviceHandlerBase::defaultFdirParentId = objects::NO_OBJECT; +object_id_t DeviceHandlerBase::defaultHkDestination = objects::NO_OBJECT; DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF * comCookie, - uint8_t setDeviceSwitch, uint32_t thermalStatePoolId, - uint32_t thermalRequestPoolId, FailureIsolationBase* fdirInstance, - size_t cmdQueueSize) : + FailureIsolationBase* fdirInstance, size_t cmdQueueSize) : SystemObject(setObjectId), mode(MODE_OFF), submode(SUBMODE_NONE), wiretappingMode(OFF), storedRawData(StorageManagerIF::INVALID_ADDRESS), deviceCommunicationId(deviceCommunication), comCookie(comCookie), - deviceThermalStatePoolId(thermalStatePoolId), - deviceThermalRequestPoolId(thermalRequestPoolId), healthHelper(this,setObjectId), modeHelper(this), parameterHelper(this), + actionHelper(this, nullptr), hkManager(this, nullptr), childTransitionFailure(RETURN_OK), fdirInstance(fdirInstance), hkSwitcher(this), defaultFDIRUsed(fdirInstance == nullptr), - switchOffWasReported(false), actionHelper(this, nullptr), - childTransitionDelay(5000), - transitionSourceMode(_MODE_POWER_DOWN), transitionSourceSubMode( - SUBMODE_NONE), deviceSwitch(setDeviceSwitch) { + switchOffWasReported(false), childTransitionDelay(5000), + transitionSourceMode(_MODE_POWER_DOWN), + transitionSourceSubMode(SUBMODE_NONE) { commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize, - CommandMessage::MAX_MESSAGE_SIZE); + MessageQueueMessage::MAX_MESSAGE_SIZE); insertInCommandMap(RAW_COMMAND_ID); cookieInfo.state = COOKIE_UNUSED; cookieInfo.pendingCommand = deviceCommandMap.end(); if (comCookie == nullptr) { - sif::error << "DeviceHandlerBase: ObjectID 0x" << std::hex << - std::setw(8) << std::setfill('0') << this->getObjectId() << - std::dec << ": Do not pass nullptr as a cookie, consider " - << std::setfill(' ') << "passing a dummy cookie instead!" << - std::endl; + sif::error << "DeviceHandlerBase: ObjectID 0x" << std::hex + << std::setw(8) << std::setfill('0') << this->getObjectId() + << std::dec << ": Do not pass nullptr as a cookie, consider " + << std::setfill(' ') << "passing a dummy cookie instead!" + << std::endl; } if (this->fdirInstance == nullptr) { this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, - defaultFDIRParentId); + defaultFdirParentId); } } +void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) { + this->hkDestination = hkDestination; +} + +void DeviceHandlerBase::setThermalStateRequestPoolIds( + uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId) { + this->deviceThermalRequestPoolId = thermalStatePoolId; + this->deviceThermalRequestPoolId = thermalRequestPoolId; +} + + +void DeviceHandlerBase::setDeviceSwitch(uint8_t deviceSwitch) { + this->deviceSwitch = deviceSwitch; +} + DeviceHandlerBase::~DeviceHandlerBase() { delete comCookie; if (defaultFDIRUsed) { @@ -108,8 +122,12 @@ ReturnValue_t DeviceHandlerBase::initialize() { communicationInterface = objectManager->get( deviceCommunicationId); - if (communicationInterface == NULL) { - return RETURN_FAILED; + if (communicationInterface == nullptr) { + sif::error << "DeviceHandlerBase::initialize: Communication interface " + "invalid." << std::endl; + sif::error << "Make sure it is set up properly and implements" + " DeviceCommunicationIF" << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; } result = communicationInterface->initializeInterface(comCookie); @@ -118,27 +136,44 @@ ReturnValue_t DeviceHandlerBase::initialize() { } IPCStore = objectManager->get(objects::IPC_STORE); - if (IPCStore == NULL) { - return RETURN_FAILED; + if (IPCStore == nullptr) { + sif::error << "DeviceHandlerBase::initialize: IPC store not set up in " + "factory." << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; } - AcceptsDeviceResponsesIF *rawReceiver = objectManager->get< - AcceptsDeviceResponsesIF>(rawDataReceiverId); + if(rawDataReceiverId != objects::NO_OBJECT) { + AcceptsDeviceResponsesIF *rawReceiver = objectManager->get< + AcceptsDeviceResponsesIF>(rawDataReceiverId); - if (rawReceiver == NULL) { - return RETURN_FAILED; + if (rawReceiver == nullptr) { + sif::error << "DeviceHandlerBase::initialize: Raw receiver object " + "ID set but no valid object found." << std::endl; + sif::error << "Make sure the raw receiver object is set up properly" + " and implements AcceptsDeviceResponsesIF" << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + defaultRawReceiver = rawReceiver->getDeviceQueue(); } - defaultRawReceiver = rawReceiver->getDeviceQueue(); - - powerSwitcher = objectManager->get(powerSwitcherId); - if (powerSwitcher == NULL) { - return RETURN_FAILED; + if(powerSwitcherId != objects::NO_OBJECT) { + powerSwitcher = objectManager->get(powerSwitcherId); + if (powerSwitcher == nullptr) { + sif::error << "DeviceHandlerBase::initialize: Power switcher " + << "object ID set but no valid object found." << std::endl; + sif::error << "Make sure the raw receiver object is set up properly" + << " and implements PowerSwitchIF" << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; + } } result = healthHelper.initialize(); - if (result != RETURN_OK) { - return result; + if (result == RETURN_OK) { + healthHelperActive = true; + } + else { + sif::warning << "DeviceHandlerBase::initialize: Health Helper " + "initialization failure." << std::endl; } result = modeHelper.initialize(); @@ -164,11 +199,20 @@ ReturnValue_t DeviceHandlerBase::initialize() { return result; } + if(hkDestination == objects::NO_OBJECT) { + hkDestination = defaultHkDestination; + } + + result = hkManager.initialize(commandQueue, hkDestination); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + fillCommandAndReplyMap(); //Set temperature target state to NON_OP. - DataSet mySet; - PoolVariable thermalRequest(deviceThermalRequestPoolId, &mySet, + GlobDataSet mySet; + gp_uint8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_WRITE); mySet.read(); thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; @@ -200,43 +244,50 @@ void DeviceHandlerBase::readCommandQueue() { return; } - CommandMessage message; - ReturnValue_t result = commandQueue->receiveMessage(&message); + CommandMessage command; + ReturnValue_t result = commandQueue->receiveMessage(&command); if (result != RETURN_OK) { return; } - result = healthHelper.handleHealthCommand(&message); + if(healthHelperActive) { + result = healthHelper.handleHealthCommand(&command); + if (result == RETURN_OK) { + return; + } + } + + result = modeHelper.handleModeCommand(&command); if (result == RETURN_OK) { return; } - result = modeHelper.handleModeCommand(&message); + result = actionHelper.handleActionMessage(&command); if (result == RETURN_OK) { return; } - result = actionHelper.handleActionMessage(&message); + result = parameterHelper.handleParameterMessage(&command); if (result == RETURN_OK) { return; } - result = parameterHelper.handleParameterMessage(&message); + result = hkManager.handleHousekeepingMessage(&command); if (result == RETURN_OK) { return; } - result = handleDeviceHandlerMessage(&message); + result = handleDeviceHandlerMessage(&command); if (result == RETURN_OK) { return; } - result = letChildHandleMessage(&message); + result = letChildHandleMessage(&command); if (result == RETURN_OK) { return; } - replyReturnvalueToCommand(CommandMessage::UNKNOW_COMMAND); + replyReturnvalueToCommand(CommandMessage::UNKNOWN_COMMAND); } @@ -273,7 +324,8 @@ void DeviceHandlerBase::doStateMachine() { case _MODE_WAIT_ON: { uint32_t currentUptime; Clock::getUptime(¤tUptime); - if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) { + if (powerSwitcher != nullptr and currentUptime - timeoutStart >= + powerSwitcher->getSwitchDelayMs()) { triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0); setMode(_MODE_POWER_DOWN); @@ -293,6 +345,12 @@ void DeviceHandlerBase::doStateMachine() { case _MODE_WAIT_OFF: { uint32_t currentUptime; Clock::getUptime(¤tUptime); + + if(powerSwitcher == nullptr) { + setMode(MODE_OFF); + break; + } + if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) { triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0); @@ -343,9 +401,10 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode, } } -ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, - uint16_t maxDelayCycles, size_t replyLen, bool periodic, - bool hasDifferentReplyId, DeviceCommandId_t replyId) { +ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap( + DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, + size_t replyLen, bool periodic, bool hasDifferentReplyId, + DeviceCommandId_t replyId) { //No need to check, as we may try to insert multiple times. insertInCommandMap(deviceCommand); if (hasDifferentReplyId) { @@ -371,7 +430,8 @@ ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId, } } -ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceCommand) { +ReturnValue_t DeviceHandlerBase::insertInCommandMap( + DeviceCommandId_t deviceCommand) { DeviceCommandInfo info; info.expectedReplies = 0; info.isExecuting = false; @@ -419,7 +479,7 @@ void DeviceHandlerBase::setTransition(Mode_t modeTo, Submode_t submodeTo) { transitionSourceSubMode = submode; childTransitionFailure = CHILD_TIMEOUT; -//transitionTargetMode is set by setMode + // transitionTargetMode is set by setMode setMode((modeTo | TRANSITION_MODE_CHILD_ACTION_MASK), submodeTo); } @@ -436,8 +496,8 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) { Clock::getUptime(&timeoutStart); if (mode == MODE_OFF) { - DataSet mySet; - PoolVariable thermalRequest(deviceThermalRequestPoolId, &mySet, + GlobDataSet mySet; + gp_uint8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { @@ -578,11 +638,8 @@ void DeviceHandlerBase::doSendRead() { } void DeviceHandlerBase::doGetRead() { - size_t receivedDataLen; - uint8_t *receivedData; - DeviceCommandId_t foundId = 0xFFFFFFFF; - size_t foundLen = 0; - ReturnValue_t result; + size_t receivedDataLen = 0; + uint8_t *receivedData = nullptr; if (cookieInfo.state != COOKIE_READ_SENT) { cookieInfo.state = COOKIE_UNUSED; @@ -591,8 +648,8 @@ void DeviceHandlerBase::doGetRead() { cookieInfo.state = COOKIE_UNUSED; - result = communicationInterface->readReceivedMessage(comCookie, - &receivedData, &receivedDataLen); + ReturnValue_t result = communicationInterface->readReceivedMessage( + comCookie, &receivedData, &receivedDataLen); if (result != RETURN_OK) { triggerEvent(DEVICE_REQUESTING_REPLY_FAILED, result); @@ -608,51 +665,101 @@ void DeviceHandlerBase::doGetRead() { replyRawData(receivedData, receivedDataLen, requestedRawTraffic); } - if (mode == MODE_RAW) { + if (mode == MODE_RAW and defaultRawReceiver != MessageQueueIF::NO_QUEUE) { 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). - uint32_t remainingLength = receivedDataLen; - for (uint32_t count = 0; count < receivedDataLen; count++) { - result = scanForReply(receivedData, remainingLength, &foundId, - &foundLen); - switch (result) { - case RETURN_OK: - handleReply(receivedData, foundId, foundLen); - break; - case APERIODIC_REPLY: { - result = interpretDeviceReply(foundId, receivedData); - if (result != RETURN_OK) { - replyRawReplyIfnotWiretapped(receivedData, foundLen); - triggerEvent(DEVICE_INTERPRETING_REPLY_FAILED, result, - foundId); - } - } - break; - case IGNORE_REPLY_DATA: - break; - case IGNORE_FULL_PACKET: - return; - default: - //We need to wait for timeout.. don't know what command failed and who sent it. + } + else { + parseReply(receivedData, receivedDataLen); + } +} + +void DeviceHandlerBase::parseReply(const uint8_t* receivedData, + size_t receivedDataLen) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + DeviceCommandId_t foundId = 0xFFFFFFFF; + size_t foundLen = 0; + // 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. + uint32_t remainingLength = receivedDataLen; + for (uint32_t count = 0; count < receivedDataLen; count++) { + result = scanForReply(receivedData, remainingLength, &foundId, + &foundLen); + switch (result) { + case RETURN_OK: + handleReply(receivedData, foundId, foundLen); + break; + case APERIODIC_REPLY: { + result = interpretDeviceReply(foundId, receivedData); + if (result != RETURN_OK) { replyRawReplyIfnotWiretapped(receivedData, foundLen); - triggerEvent(DEVICE_READING_REPLY_FAILED, result, foundLen); - break; - } - receivedData += foundLen; - if (remainingLength > foundLen) { - remainingLength -= foundLen; - } else { - return; + triggerEvent(DEVICE_INTERPRETING_REPLY_FAILED, result, + foundId); } } + break; + case IGNORE_REPLY_DATA: + break; + case IGNORE_FULL_PACKET: + return; + 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; + } + receivedData += foundLen; + if (remainingLength > foundLen) { + remainingLength -= foundLen; + } else { + return; + } + } +} +void DeviceHandlerBase::handleReply(const uint8_t* receivedData, + DeviceCommandId_t foundId, uint32_t foundLen) { + ReturnValue_t result; + DeviceReplyMap::iterator iter = deviceReplyMap.find(foundId); + + if (iter == deviceReplyMap.end()) { + replyRawReplyIfnotWiretapped(receivedData, foundLen); + triggerEvent(DEVICE_UNKNOWN_REPLY, foundId); + return; + } + + DeviceReplyInfo *info = &(iter->second); + + if (info->delayCycles != 0) { + + if (info->periodic != false) { + info->delayCycles = info->maxDelayCycles; + } + else { + info->delayCycles = 0; + } + + 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 + // replies may still come in. + if (mode != _MODE_WAIT_OFF) { + triggerEvent(DEVICE_UNREQUESTED_REPLY, foundId); + } } } ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, - uint8_t * *data, uint32_t * len) { + uint8_t** data, uint32_t * len) { size_t lenTmp; if (IPCStore == nullptr) { @@ -675,7 +782,7 @@ ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len, MessageQueueId_t sendTo, bool isCommand) { - if (IPCStore == NULL || len == 0) { + if (IPCStore == nullptr or len == 0 or sendTo == MessageQueueIF::NO_QUEUE) { return; } store_address_t address; @@ -686,18 +793,17 @@ void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len, return; } - CommandMessage message; + CommandMessage command; - DeviceHandlerMessage::setDeviceHandlerRawReplyMessage(&message, + DeviceHandlerMessage::setDeviceHandlerRawReplyMessage(&command, getObjectId(), address, isCommand); -// this->DeviceHandlerCommand = CommandMessage::CMD_NONE; - - result = commandQueue->sendMessage(sendTo, &message); + result = commandQueue->sendMessage(sendTo, &command); if (result != RETURN_OK) { IPCStore->deleteData(address); - //Silently discard data, this indicates heavy TM traffic which should not be increased by additional events. + // Silently discard data, this indicates heavy TM traffic which + // should not be increased by additional events. } } @@ -726,57 +832,6 @@ MessageQueueId_t DeviceHandlerBase::getCommandQueue() const { return commandQueue->getId(); } -void DeviceHandlerBase::handleReply(const uint8_t* receivedData, - DeviceCommandId_t foundId, uint32_t foundLen) { - ReturnValue_t result; - DeviceReplyMap::iterator iter = deviceReplyMap.find(foundId); - - if (iter == deviceReplyMap.end()) { - replyRawReplyIfnotWiretapped(receivedData, foundLen); - triggerEvent(DEVICE_UNKNOWN_REPLY, foundId); - return; - } - - DeviceReplyInfo *info = &(iter->second); - - if (info->delayCycles != 0) { - - if (info->periodic) { - info->delayCycles = info->maxDelayCycles; - } else { - info->delayCycles = 0; - } - 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 replies may still come in. - if (mode != _MODE_WAIT_OFF) { - triggerEvent(DEVICE_UNREQUESTED_REPLY, foundId); - } - } -} - -//ReturnValue_t DeviceHandlerBase::switchCookieChannel(object_id_t newChannelId) { -// DeviceCommunicationIF *newCommunication = objectManager->get< -// DeviceCommunicationIF>(newChannelId); -// -// if (newCommunication != NULL) { -// ReturnValue_t result = newCommunication->reOpen(cookie, ioBoardAddress, -// maxDeviceReplyLen); -// if (result != RETURN_OK) { -// return result; -// } -// return RETURN_OK; -// } -// return RETURN_FAILED; -//} - void DeviceHandlerBase::buildRawDeviceCommand(CommandMessage* commandMessage) { storedRawData = DeviceHandlerMessage::getStoreAddress(commandMessage); ReturnValue_t result = getStorageData(storedRawData, &rawPacket, @@ -793,6 +848,9 @@ void DeviceHandlerBase::buildRawDeviceCommand(CommandMessage* commandMessage) { } void DeviceHandlerBase::commandSwitch(ReturnValue_t onOff) { + if(powerSwitcher == nullptr) { + return; + } const uint8_t *switches; uint8_t numberOfSwitches = 0; ReturnValue_t result = getSwitches(&switches, &numberOfSwitches); @@ -807,9 +865,7 @@ void DeviceHandlerBase::commandSwitch(ReturnValue_t onOff) { ReturnValue_t DeviceHandlerBase::getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches) { - *switches = &deviceSwitch; - *numberOfSwitches = 1; - return RETURN_OK; + return DeviceHandlerBase::NO_SWITCH; } void DeviceHandlerBase::modeChanged(void) { @@ -845,6 +901,9 @@ uint32_t DeviceHandlerBase::getTransitionDelayMs(Mode_t modeFrom, } ReturnValue_t DeviceHandlerBase::getStateOfSwitches(void) { + if(powerSwitcher == nullptr) { + return NO_SWITCH; + } uint8_t numberOfSwitches = 0; const uint8_t *switches; @@ -894,10 +953,10 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, if ((commandedMode == MODE_ON) && (mode == MODE_OFF) && (deviceThermalStatePoolId != PoolVariableIF::NO_PARAMETER)) { - DataSet mySet; - PoolVariable thermalState(deviceThermalStatePoolId, &mySet, + GlobDataSet mySet; + gp_uint8_t thermalState(deviceThermalStatePoolId, &mySet, PoolVariableIF::VAR_READ); - PoolVariable thermalRequest(deviceThermalRequestPoolId, &mySet, + gp_uint8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_READ); mySet.read(); if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { @@ -924,8 +983,8 @@ void DeviceHandlerBase::startTransition(Mode_t commandedMode, childTransitionDelay = getTransitionDelayMs(_MODE_START_UP, MODE_ON); triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode); - DataSet mySet; - PoolVariable thermalRequest(deviceThermalRequestPoolId, + GlobDataSet mySet; + gp_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { @@ -973,7 +1032,9 @@ void DeviceHandlerBase::getMode(Mode_t* mode, Submode_t* submode) { } void DeviceHandlerBase::setToExternalControl() { - healthHelper.setHealth(EXTERNAL_CONTROL); + if(healthHelperActive) { + healthHelper.setHealth(EXTERNAL_CONTROL); + } } void DeviceHandlerBase::announceMode(bool recursive) { @@ -993,11 +1054,24 @@ void DeviceHandlerBase::missedReply(DeviceCommandId_t id) { } HasHealthIF::HealthState DeviceHandlerBase::getHealth() { - return healthHelper.getHealth(); + if(healthHelperActive) { + return healthHelper.getHealth(); + } + else { + sif::warning << "DeviceHandlerBase::getHealth: Health helper not active" + << std::endl; + return HasHealthIF::HEALTHY; + } } ReturnValue_t DeviceHandlerBase::setHealth(HealthState health) { - healthHelper.setHealth(health); + if(healthHelperActive) { + healthHelper.setHealth(health); + } + else { + sif::warning << "DeviceHandlerBase::getHealth: Health helper not active" + << std::endl; + } return HasReturnvaluesIF::RETURN_OK; } @@ -1085,7 +1159,7 @@ ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage( void DeviceHandlerBase::setParentQueue(MessageQueueId_t parentQueueId) { modeHelper.setParentQueue(parentQueueId); - healthHelper.setParentQueue(parentQueueId); + healthHelper.setParentQeueue(parentQueueId); } bool DeviceHandlerBase::isAwaitingReply() { @@ -1111,37 +1185,49 @@ void DeviceHandlerBase::handleDeviceTM(SerializeIF* data, return; } DeviceTmReportingWrapper wrapper(getObjectId(), replyId, data); - if (iter->second.command != deviceCommandMap.end()) {//replies to a command + //replies to a command + if (iter->second.command != deviceCommandMap.end()) + { 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 && (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 + else if (forceDirectTm and (defaultRawReceiver != queueId) and + (defaultRawReceiver != MessageQueueIF::NO_QUEUE)) + { + // 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); + true); } } -//Try to cast to DataSet and commit data. + //unrequested/aperiodic replies + else + { + if (wiretappingMode == TM) { + actionHelper.reportData(requestedRawTraffic, replyId, &wrapper); + } + else if (forceDirectTm and defaultRawReceiver != + MessageQueueIF::NO_QUEUE) + { + // 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 GlobDataSet and commit data. if (!neverInDataPool) { - DataSet* dataSet = dynamic_cast(data); + GlobDataSet* dataSet = dynamic_cast(data); if (dataSet != NULL) { dataSet->commit(PoolVariableIF::VALID); } @@ -1149,7 +1235,7 @@ void DeviceHandlerBase::handleDeviceTM(SerializeIF* data, } ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId, - MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size) { + MessageQueueId_t commandedBy, const uint8_t* data, size_t size) { ReturnValue_t result = acceptExternalDeviceCommands(); if (result != HasReturnvaluesIF::RETURN_OK) { return result; @@ -1178,18 +1264,23 @@ void DeviceHandlerBase::buildInternalCommand(void) { if (mode == MODE_NORMAL) { result = buildNormalDeviceCommand(&deviceCommandId); if (result == BUSY) { + //so we can track misconfigurations sif::debug << std::hex << getObjectId() - << ": DHB::buildInternalCommand busy" << std::endl; //so we can track misconfigurations + << ": DHB::buildInternalCommand: Busy" << std::endl; result = NOTHING_TO_SEND; //no need to report this } - } else if (mode == MODE_RAW) { + } + else if (mode == MODE_RAW) { result = buildChildRawCommand(); deviceCommandId = RAW_COMMAND_ID; - } else if (mode & TRANSITION_MODE_CHILD_ACTION_MASK) { + } + else if (mode & TRANSITION_MODE_CHILD_ACTION_MASK) { result = buildTransitionDeviceCommand(&deviceCommandId); - } else { + } + else { return; } + if (result == NOTHING_TO_SEND) { return; } @@ -1281,11 +1372,53 @@ void DeviceHandlerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) { } void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_){ - executingTask = task_; + executingTask = task_; } // Default implementations empty. void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t objectId, uint32_t parameter) {} -void DeviceHandlerBase::performOperationHook() {} +void DeviceHandlerBase::performOperationHook() { +} + +ReturnValue_t DeviceHandlerBase::initializePoolEntries( + LocalDataPool &localDataPoolMap) { + return RETURN_OK; +} + +LocalDataPoolManager* DeviceHandlerBase::getHkManagerHandle() { + return &hkManager; +} + +ReturnValue_t DeviceHandlerBase::addDataSet(sid_t sid) { + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t DeviceHandlerBase::removeDataSet(sid_t sid) { + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t DeviceHandlerBase::changeCollectionInterval(sid_t sid, + dur_seconds_t newInterval) { + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() { + // In this function, the task handle should be valid if the task + // was implemented correctly. We still check to be 1000 % sure :-) + if(executingTask != nullptr) { + pstIntervalMs = executingTask->getPeriodMs(); + } + return HasReturnvaluesIF::RETURN_OK; +} + +DataSetIF* DeviceHandlerBase::getDataSetHandle(sid_t sid) { + auto iter = deviceReplyMap.find(sid.ownerSetId); + if(iter != deviceReplyMap.end()) { + return iter->second.dataSet; + } + else { + return nullptr; + } +} diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 435f8e06..61fb701d 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -1,5 +1,5 @@ -#ifndef DEVICEHANDLERBASE_H_ -#define DEVICEHANDLERBASE_H_ +#ifndef FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ +#define FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ #include #include @@ -11,13 +11,15 @@ #include #include #include +#include #include #include #include #include +#include +#include #include - #include namespace Factory{ @@ -46,14 +48,16 @@ class StorageManagerIF; * 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. NOTE: RMAP is a standard which is used for FLP. + * a default implementation is provided. + * NOTE: RMAP is a 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. * - * 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). + * 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). * The following abstract methods must be implemented by a device handler: * 1. doStartUp() * 2. doShutDown() @@ -82,7 +86,8 @@ class DeviceHandlerBase: public DeviceHandlerIF, public HasModesIF, public HasHealthIF, public HasActionsIF, - public ReceivesParameterMessagesIF { + public ReceivesParameterMessagesIF, + public HasLocalDataPoolIF { friend void (Factory::setStaticFrameworkObjectIds)(); public: /** @@ -100,12 +105,14 @@ public: * @param cmdQueueSize */ DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, - CookieIF * comCookie, uint8_t setDeviceSwitch, - uint32_t thermalStatePoolId = PoolVariableIF::NO_PARAMETER, - uint32_t thermalRequestPoolId = PoolVariableIF::NO_PARAMETER, - FailureIsolationBase* fdirInstance = nullptr, + CookieIF * comCookie, FailureIsolationBase* fdirInstance = nullptr, size_t cmdQueueSize = 20); + void setDeviceSwitch(uint8_t deviceSwitch); + void setHkDestination(object_id_t hkDestination); + void setThermalStateRequestPoolIds(uint32_t thermalStatePoolId, + uint32_t thermalRequestPoolId); + /** * @brief This function is the device handler base core component and is * called periodically. @@ -150,11 +157,9 @@ public: * @return */ virtual ReturnValue_t initialize(); - - /** - * Destructor. - */ + /** Destructor. */ virtual ~DeviceHandlerBase(); + protected: /** * @brief This is used to let the child class handle the transition from @@ -232,8 +237,9 @@ protected: * Build the device command to send for a transitional mode. * * This is only called in @c _MODE_TO_NORMAL, @c _MODE_TO_ON, @c _MODE_TO_RAW, - * @c _MODE_START_UP and @c _MODE_TO_POWER_DOWN. So it is used by doStartUp() - * and doShutDown() as well as doTransition() + * @c _MODE_START_UP and @c _MODE_SHUT_DOWN. So it is used by doStartUp() + * and doShutDown() as well as doTransition(), by setting those + * modes in the respective functions. * * A good idea is to implement a flag indicating a command has to be built * and a variable containing the command number to be built @@ -321,12 +327,11 @@ protected: * - @c RETURN_FAILED when the reply could not be interpreted, * e.g. logical errors or range violations occurred */ - virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) = 0; /** - * @brief fill the #deviceCommandMap + * @brief fill the #DeviceCommandMap and #DeviceReplyMap * called by the initialize() of the base class * @details * This is used to let the base class know which replies are expected. @@ -470,6 +475,23 @@ protected: virtual ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches); + /** + * This function is used to initialize the local housekeeping pool + * entries. The default implementation leaves the pool empty. + * @param localDataPoolMap + * @return + */ + virtual ReturnValue_t initializePoolEntries( + LocalDataPool& localDataPoolMap) override; + + /** Get the HK manager object handle */ + virtual LocalDataPoolManager* getHkManagerHandle() override; + + virtual ReturnValue_t addDataSet(sid_t sid) override; + virtual ReturnValue_t removeDataSet(sid_t sid) override; + virtual ReturnValue_t changeCollectionInterval(sid_t sid, + dur_seconds_t newInterval) override; + /** * @brief Hook function for child handlers which is called once per * performOperation(). Default implementation is empty. @@ -484,7 +506,7 @@ public: /** @brief Implementation required for HasActionIF */ ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, - uint32_t size) override; + size_t size) override; Mode_t getTransitionSourceMode() const; Submode_t getTransitionSourceSubMode() const; @@ -493,7 +515,7 @@ public: ReturnValue_t setHealth(HealthState health); virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, ParameterWrapper *parameterWrapper, - const ParameterWrapper *newValues, uint16_t startAtIndex); + const ParameterWrapper *newValues, uint16_t startAtIndex) override; /** * Implementation of ExecutableObjectIF function * @@ -505,7 +527,7 @@ public: protected: /** - * The Returnvalues ID of this class, required by HasReturnvaluesIF + * The Returnvalues id of this class, required by HasReturnvaluesIF */ static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE; @@ -527,114 +549,141 @@ 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. - */ + /** Pointer to the raw packet that will be sent.*/ uint8_t *rawPacket = nullptr; - /** - * Size of the #rawPacket. - */ + /** Size of the #rawPacket. */ uint32_t rawPacketLen = 0; /** * The mode the device handler is currently in. - * * This should never be changed directly but only with setMode() */ Mode_t mode; - /** * The submode the device handler is currently in. - * * This should never be changed directly but only with setMode() */ Submode_t submode; - /** - * This is the counter value from performOperation(). - */ + /** This is the counter value from performOperation(). */ uint8_t pstStep = 0; + uint32_t pstIntervalMs = 0; /** - * wiretapping flag: + * Wiretapping flag: * - * indicates either that all raw messages to and from the device should be sent to #theOneWhoWantsToReadRawTraffic - * or that all device TM should be downlinked to #theOneWhoWantsToReadRawTraffic + * indicates either that all raw messages to and from the device should be + * sent to #defaultRawReceiver + * or that all device TM should be downlinked to #defaultRawReceiver. */ enum WiretappingMode { OFF = 0, RAW = 1, TM = 2 } wiretappingMode; - /** - * A message queue that accepts raw replies + * @brief A message queue that accepts 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 + * Statically initialized in initialize() to a configurable object. + * Used when there is no method of finding a recipient, ie raw mode and + * reporting erroneous replies */ - MessageQueueId_t defaultRawReceiver = 0; - + MessageQueueId_t defaultRawReceiver = MessageQueueIF::NO_QUEUE; store_address_t storedRawData; /** - * the message queue which wants to read all raw traffic - * - * if #isWiretappingActive all raw communication from and to the device will be sent to this queue + * @brief The message queue which wants to read all raw traffic + * If #isWiretappingActive all raw communication from and to the device + * will be sent to this queue */ MessageQueueId_t requestedRawTraffic = 0; - /** - * the object used to set power switches - */ - PowerSwitchIF *powerSwitcher = nullptr; - /** * Pointer to the IPCStore. - * * This caches the pointer received from the objectManager in the constructor. */ StorageManagerIF *IPCStore = nullptr; - - /** - * cached for init - */ + /** The comIF object ID is cached for the intialize() function */ object_id_t deviceCommunicationId; - - /** - * Communication object used for device communication - */ + /** Communication object used for device communication */ DeviceCommunicationIF * communicationInterface = nullptr; - - /** - * Cookie used for communication - */ + /** Cookie used for communication */ CookieIF * comCookie; + /** Health helper for HasHealthIF */ + HealthHelper healthHelper; + bool healthHelperActive = false; + /** Mode helper for HasModesIF */ + ModeHelper modeHelper; + /** Parameter helper for ReceivesParameterMessagesIF */ + ParameterHelper parameterHelper; + /** Action helper for HasActionsIF */ + ActionHelper actionHelper; + /** Housekeeping Manager */ + LocalDataPoolManager hkManager; + + /** + * @brief Information about commands + */ struct DeviceCommandInfo { - bool isExecuting; //!< Indicates if the command is already executing. - uint8_t expectedReplies; //!< Dynamic value to indicate how many replies are expected. Inititated with 0. - MessageQueueId_t sendReplyTo; //!< if this is != NO_COMMANDER, DHB was commanded externally and shall report everything to commander. + //! Indicates if the command is already executing. + bool isExecuting; + //! Dynamic value to indicate how many replies are expected. + //! Inititated with 0. + uint8_t expectedReplies; + //! if this is != NO_COMMANDER, DHB was commanded externally and shall + //! report everything to commander. + MessageQueueId_t sendReplyTo; }; using DeviceCommandMap = std::map ; + /** + * Information about commands + */ + DeviceCommandMap deviceCommandMap; /** * @brief Information about expected replies - * - * This is used to keep track of pending replies + * This is used to keep track of pending replies. */ struct DeviceReplyInfo { - uint16_t maxDelayCycles; //!< The maximum number of cycles the handler should wait for a reply to this command. - uint16_t delayCycles; //!< The currently remaining cycles the handler should wait for a reply, 0 means there is no reply expected + //! The maximum number of cycles the handler should wait for a reply + //! to this command. + uint16_t maxDelayCycles; + //! The currently remaining cycles the handler should wait for a reply, + //! 0 means there is no reply expected + uint16_t delayCycles; size_t replyLen = 0; //!< Expected size of the reply. - bool 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. + //! if this is !=0, the delayCycles will not be reset to 0 but to + //! maxDelayCycles + bool periodic = false; + //! The dataset used to access housekeeping data related to the + //! respective device reply. Will point to a dataset held by + //! the child handler (if one is specified) + DataSetIF* dataSet = nullptr; + float collectionInterval = 0.0; + uint32_t intervalCounter = 0; + //! The command that expects this reply. + DeviceCommandMap::iterator command; }; using DeviceReplyMap = std::map ; using DeviceReplyIter = DeviceReplyMap::iterator; - /** - * The MessageQueue used to receive device handler commands and to send replies. + * This map is used to check and track correct reception of all replies. + * + * It has multiple use: + * - It stores the information on pending replies. If a command is sent, + * the DeviceCommandInfo.count is incremented. + * - It is used to time-out missing replies. If a command is sent, the + * DeviceCommandInfo.DelayCycles is set to MaxDelayCycles. + * - It is queried to check if a reply from the device can be interpreted. + * scanForReply() returns the id of the command a reply was found for. + * The reply is ignored in the following cases: + * - No entry for the returned id was found + * - The deviceReplyInfo.delayCycles is == 0 */ + DeviceReplyMap deviceReplyMap; + + //! The MessageQueue used to receive device handler commands + //! and to send replies. MessageQueueIF* commandQueue = nullptr; /** @@ -642,23 +691,14 @@ protected: * * can be set to PoolVariableIF::NO_PARAMETER to deactivate thermal checking */ - uint32_t deviceThermalStatePoolId; + uint32_t deviceThermalStatePoolId = PoolVariableIF::NO_PARAMETER; /** * this is the datapool variable with the thermal request of the device * * can be set to PoolVariableIF::NO_PARAMETER to deactivate thermal checking */ - uint32_t deviceThermalRequestPoolId; - - /** - * Taking care of the health - */ - HealthHelper healthHelper; - - ModeHelper modeHelper; - - ParameterHelper parameterHelper; + uint32_t deviceThermalRequestPoolId = PoolVariableIF::NO_PARAMETER; /** * Optional Error code @@ -676,13 +716,15 @@ protected: bool switchOffWasReported; //!< Indicates if SWITCH_WENT_OFF was already thrown. - PeriodicTaskIF* executingTask = nullptr;//!< Pointer to the task which executes this component, is invalid before setTaskIF was called. + //! Pointer to the task which executes this component, is invalid + //! before setTaskIF was called. + PeriodicTaskIF* executingTask = nullptr; 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. + static object_id_t defaultFdirParentId; //!< Object which may be the root cause of an identified fault. /** * Helper function to report a missed reply * @@ -730,28 +772,40 @@ protected: /** * Do the transition to the main modes (MODE_ON, MODE_NORMAL and MODE_RAW). * - * If the transition is complete, the mode should be set to the target mode, which can be deduced from the current mode which is + * If the transition is complete, the mode should be set to the target mode, + * which can be deduced from the current mode which is * [_MODE_TO_ON, _MODE_TO_NORMAL, _MODE_TO_RAW] * - * The intended target submode is already set. The origin submode can be read in subModeFrom. + * The intended target submode is already set. + * The origin submode can be read in subModeFrom. * - * If the transition can not be completed, the child class can try to reach an working mode by setting the mode either directly - * or setting the mode to an transitional mode (TO_ON, TO_NORMAL, TO_RAW) if the device needs to be reconfigured. + * If the transition can not be completed, the child class can try to reach + * an working mode by setting the mode either directly + * or setting the mode to an transitional mode (TO_ON, TO_NORMAL, TO_RAW) + * if the device needs to be reconfigured. * - * If nothing works, the child class can wait for the timeout and the base class will reset the mode to the mode where the transition + * If nothing works, the child class can wait for the timeout and the base + * class will reset the mode to the mode where the transition * originated from (the child should report the reason for the failed transition). * - * The intended way to send commands is to set a flag (enum) indicating which command is to be sent here - * and then to check in buildTransitionCommand() for the flag. This flag can also be used by doStartUp() and - * doShutDown() to get a nice and clean implementation of buildTransitionCommand() without switching through modes. + * The intended way to send commands is to set a flag (enum) indicating + * which command is to be sent here and then to check in + * buildTransitionCommand() for the flag. This flag can also be used by + * doStartUp() and doShutDown() to get a nice and clean implementation of + * buildTransitionCommand() without switching through modes. * - * When the the condition for the completion of the transition is met, the mode can be set, for example in the parseReply() function. + * When the the condition for the completion of the transition is met, the + * mode can be set, for example in the scanForReply() function. * - * The default implementation goes into the target mode; + * The default implementation goes into the target mode directly. * - * #transitionFailure can be set to a failure code indicating the reason for a failed transition + * #transitionFailure can be set to a failure code indicating the reason + * for a failed transition * - * @param modeFrom the mode the transition originated from: [MODE_ON, MODE_NORMAL, MODE_RAW and _MODE_POWER_DOWN (if the mode changed from _MODE_START_UP to _MODE_TO_ON)] + * @param modeFrom + * The mode the transition originated from: + * [MODE_ON, MODE_NORMAL, MODE_RAW and _MODE_POWER_DOWN (if the mode changed + * from _MODE_START_UP to _MODE_TO_ON)] * @param subModeFrom the subMode of modeFrom */ virtual void doTransition(Mode_t modeFrom, Submode_t subModeFrom); @@ -953,24 +1007,11 @@ protected: bool commandIsExecuting(DeviceCommandId_t commandId); /** - * This map is used to check and track correct reception of all replies. + * set all switches returned by getSwitches() * - * It has multiple use: - * - it stores the information on pending replies. If a command is sent, the DeviceCommandInfo.count is incremented. - * - it is used to time-out missing replies. If a command is sent, the DeviceCommandInfo.DelayCycles is set to MaxDelayCycles. - * - it is queried to check if a reply from the device can be interpreted. scanForReply() returns the id of the command a reply was found for. - * The reply is ignored in the following cases: - * - No entry for the returned id was found - * - The deviceReplyInfo.delayCycles is == 0 + * @param onOff on == @c SWITCH_ON; off != @c SWITCH_ON */ - DeviceReplyMap deviceReplyMap; - - /** - * Information about commands - */ - DeviceCommandMap deviceCommandMap; - - ActionHelper actionHelper; + void commandSwitch(ReturnValue_t onOff); private: /** @@ -997,15 +1038,21 @@ private: }; /** - * Info about the #cookie - * + * @brief Info about the #cookie * Used to track the state of the communication */ CookieInfo cookieInfo; + /** the object used to set power switches */ + PowerSwitchIF *powerSwitcher = nullptr; + + /** Cached for initialize() */ + static object_id_t defaultHkDestination; + /** HK destination can also be set individually */ + object_id_t hkDestination = objects::NO_OBJECT; + /** - * Used for timing out mode transitions. - * + * @brief Used for timing out mode transitions. * Set when setMode() is called. */ uint32_t timeoutStart = 0; @@ -1016,11 +1063,12 @@ private: uint32_t childTransitionDelay; /** - * The mode the current transition originated from + * @brief The mode the current transition originated from * * This is private so the child can not change it and fuck up the timeouts * - * IMPORTANT: This is not valid during _MODE_SHUT_DOWN and _MODE_START_UP!! (it is _MODE_POWER_DOWN during this modes) + * IMPORTANT: This is not valid during _MODE_SHUT_DOWN and _MODE_START_UP!! + * (it is _MODE_POWER_DOWN during this modes) * * is element of [MODE_ON, MODE_NORMAL, MODE_RAW] */ @@ -1036,7 +1084,7 @@ private: * * for devices using two switches override getSwitches() */ - const uint8_t deviceSwitch; + uint8_t deviceSwitch; /** * read the command queue @@ -1135,12 +1183,6 @@ private: ReturnValue_t getStorageData(store_address_t storageAddress, uint8_t **data, uint32_t *len); - /** - * set all switches returned by getSwitches() - * - * @param onOff on == @c SWITCH_ON; off != @c SWITCH_ON - */ - void commandSwitch(ReturnValue_t onOff); /** * @param modeTo either @c MODE_ON, MODE_NORMAL or MODE_RAW NOTHING ELSE!!! @@ -1165,7 +1207,13 @@ private: ReturnValue_t switchCookieChannel(object_id_t newChannelId); ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message); + + virtual ReturnValue_t initializeAfterTaskCreation() override; + DataSetIF* getDataSetHandle(sid_t sid) override; + + void parseReply(const uint8_t* receivedData, + size_t receivedDataLen); }; -#endif /* DEVICEHANDLERBASE_H_ */ +#endif /* FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */ From 307c954007f8526d8459146e7cbd6317b365433d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 16 Jul 2020 12:49:53 +0200 Subject: [PATCH 186/653] fixed CommandMessageTypo and integrated HasActionsIF interface changes --- action/ActionHelper.cpp | 15 ++++---- action/ActionHelper.h | 2 +- action/HasActionsIF.h | 54 ++++++++++++++++------------ devicehandlers/DeviceHandlerBase.cpp | 4 +-- devicehandlers/DeviceHandlerBase.h | 2 +- ipc/CommandMessage.cpp | 2 +- ipc/CommandMessage.h | 2 +- subsystem/SubsystemBase.cpp | 2 +- tmstorage/TmStoreMessage.cpp | 2 +- 9 files changed, 49 insertions(+), 36 deletions(-) diff --git a/action/ActionHelper.cpp b/action/ActionHelper.cpp index bcb302cd..dc6bd498 100644 --- a/action/ActionHelper.cpp +++ b/action/ActionHelper.cpp @@ -1,9 +1,9 @@ #include #include #include + ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue) : - owner(setOwner), queueToUse(useThisQueue), ipcStore( - NULL) { + owner(setOwner), queueToUse(useThisQueue), ipcStore(nullptr) { } ActionHelper::~ActionHelper() { @@ -16,16 +16,18 @@ ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) { ActionMessage::getStoreId(command)); return HasReturnvaluesIF::RETURN_OK; } else { - return CommandMessage::UNKNOW_COMMAND; + return CommandMessage::UNKNOWN_COMMAND; } } ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) { ipcStore = objectManager->get(objects::IPC_STORE); - if (ipcStore == NULL) { + if (ipcStore == nullptr) { return HasReturnvaluesIF::RETURN_FAILED; } - setQueueToUse(queueToUse_); + if(queueToUse_ != nullptr) { + setQueueToUse(queueToUse_); + } return HasReturnvaluesIF::RETURN_OK; } @@ -67,7 +69,8 @@ void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t act } } -ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data, bool hideSender) { +ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, + ActionId_t replyId, SerializeIF* data, bool hideSender) { CommandMessage reply; store_address_t storeAddress; uint8_t *dataPtr; diff --git a/action/ActionHelper.h b/action/ActionHelper.h index 6ba6dd89..3d8351d6 100644 --- a/action/ActionHelper.h +++ b/action/ActionHelper.h @@ -38,7 +38,7 @@ public: * @param queueToUse_ Pointer to the messageQueue to be used * @return Returns RETURN_OK if successful */ - ReturnValue_t initialize(MessageQueueIF* queueToUse_); + ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr); /** * Function to be called from the owner to send a step message. Success or failure will be determined by the result value. * diff --git a/action/HasActionsIF.h b/action/HasActionsIF.h index f30fcb45..008d9eaf 100644 --- a/action/HasActionsIF.h +++ b/action/HasActionsIF.h @@ -1,5 +1,5 @@ -#ifndef HASACTIONSIF_H_ -#define HASACTIONSIF_H_ +#ifndef FRAMEWORK_ACTION_HASACTIONSIF_H_ +#define FRAMEWORK_ACTION_HASACTIONSIF_H_ #include #include @@ -7,27 +7,35 @@ #include #include /** - * \brief Interface for component which uses actions + * @brief + * Interface for component which uses actions * - * 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. + * @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. * - * The HasActionsIF allows components to define such actions and make them available - * for other components to use. Implementing the interface is straightforward: There’s a - * single executeAction call, which provides an identifier for the action to execute, as well - * as arbitrary parameters for input. Aside from direct, software-based - * actions, it is used in device handler components as an interface to forward commands to - * devices. - * Implementing components of the interface are supposed to check identifier (ID) and - * 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. + * The HasActionsIF allows components to define such actions and make them + * available for other components to use. Implementing the interface is + * straightforward: There’s a single executeAction call, which provides an + * identifier for the action to execute, as well as arbitrary parameters for + * input. + * Aside from direct, software-based actions, it is used in device handler + * components as an interface to forward commands to devices. + * Implementing components of the interface are supposed to check identifier + * (ID) and 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: 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 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); static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4); @@ -39,12 +47,14 @@ public: virtual MessageQueueId_t getCommandQueue() const = 0; /** * Execute or initialize the execution of a certain function. - * Returning #EXECUTION_FINISHED or a failure code, nothing else needs to be done. - * When needing more steps, return RETURN_OK and issue steps and completion manually. One "step failed" or completion report must - * be issued! + * Returning #EXECUTION_FINISHED or a failure code, nothing else needs to + * be done. When needing more steps, return RETURN_OK and issue steps and + * completion manually. + * One "step failed" or completion report must be issued! */ - virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size) = 0; + virtual ReturnValue_t executeAction(ActionId_t actionId, + MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0; }; -#endif /* HASACTIONSIF_H_ */ +#endif /* FRAMEWORK_ACTION_HASACTIONSIF_H_ */ diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 872310a1..79b504b5 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -236,7 +236,7 @@ void DeviceHandlerBase::readCommandQueue() { return; } - replyReturnvalueToCommand(CommandMessage::UNKNOW_COMMAND); + replyReturnvalueToCommand(CommandMessage::UNKNOWN_COMMAND); } @@ -1149,7 +1149,7 @@ void DeviceHandlerBase::handleDeviceTM(SerializeIF* data, } ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId, - MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size) { + MessageQueueId_t commandedBy, const uint8_t* data, size_t size) { ReturnValue_t result = acceptExternalDeviceCommands(); if (result != HasReturnvaluesIF::RETURN_OK) { return result; diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 435f8e06..e79d5d5c 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -484,7 +484,7 @@ public: /** @brief Implementation required for HasActionIF */ ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, - uint32_t size) override; + size_t size) override; Mode_t getTransitionSourceMode() const; Submode_t getTransitionSourceSubMode() const; diff --git a/ipc/CommandMessage.cpp b/ipc/CommandMessage.cpp index fa41c653..ce72786b 100644 --- a/ipc/CommandMessage.cpp +++ b/ipc/CommandMessage.cpp @@ -111,7 +111,7 @@ size_t CommandMessage::getMinimumMessageSize() const { void CommandMessage::setToUnknownCommand() { Command_t initialCommand = getCommand(); clearCommandMessage(); - setReplyRejected(UNKNOW_COMMAND, initialCommand); + setReplyRejected(UNKNOWN_COMMAND, initialCommand); } void CommandMessage::setReplyRejected(ReturnValue_t reason, diff --git a/ipc/CommandMessage.h b/ipc/CommandMessage.h index 2d966063..c3ed2016 100644 --- a/ipc/CommandMessage.h +++ b/ipc/CommandMessage.h @@ -20,7 +20,7 @@ typedef ReturnValue_t Command_t; class CommandMessage : public MessageQueueMessage { public: static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE; - static const ReturnValue_t UNKNOW_COMMAND = MAKE_RETURN_CODE(0x01); + static const ReturnValue_t UNKNOWN_COMMAND = MAKE_RETURN_CODE(0x01); static const uint8_t MESSAGE_ID = MESSAGE_TYPE::COMMAND; diff --git a/subsystem/SubsystemBase.cpp b/subsystem/SubsystemBase.cpp index 6df0b64f..cceb2d41 100644 --- a/subsystem/SubsystemBase.cpp +++ b/subsystem/SubsystemBase.cpp @@ -329,7 +329,7 @@ void SubsystemBase::checkCommandQueue() { result = handleCommandMessage(&message); if (result != RETURN_OK) { CommandMessage reply; - reply.setReplyRejected(CommandMessage::UNKNOW_COMMAND, + reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND, message.getCommand()); replyToCommand(&reply); } diff --git a/tmstorage/TmStoreMessage.cpp b/tmstorage/TmStoreMessage.cpp index 4509ba91..e908b923 100644 --- a/tmstorage/TmStoreMessage.cpp +++ b/tmstorage/TmStoreMessage.cpp @@ -74,7 +74,7 @@ void TmStoreMessage::clear(CommandMessage* cmd) { case DELETE_STORE_CONTENT_BLOCKS: case DOWNLINK_STORE_CONTENT_BLOCKS: case REPORT_INDEX_REQUEST: - cmd->setCommand(UNKNOW_COMMAND); + cmd->setCommand(UNKNOWN_COMMAND); cmd->setParameter(0); cmd->setParameter2(0); break; From 36f7cf2caf2c1c1a4153389a9f3598fdf85fa5fa Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 16 Jul 2020 12:54:30 +0200 Subject: [PATCH 187/653] updated DHB changes --- devicehandlers/DeviceHandlerBase.cpp | 55 +++++----------------------- devicehandlers/DeviceHandlerBase.h | 14 ------- 2 files changed, 9 insertions(+), 60 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index cc97cd42..282f20b2 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -63,10 +63,6 @@ void DeviceHandlerBase::setThermalStateRequestPoolIds( } -void DeviceHandlerBase::setDeviceSwitch(uint8_t deviceSwitch) { - this->deviceSwitch = deviceSwitch; -} - DeviceHandlerBase::~DeviceHandlerBase() { delete comCookie; if (defaultFDIRUsed) { @@ -168,12 +164,8 @@ ReturnValue_t DeviceHandlerBase::initialize() { } result = healthHelper.initialize(); - if (result == RETURN_OK) { - healthHelperActive = true; - } - else { - sif::warning << "DeviceHandlerBase::initialize: Health Helper " - "initialization failure." << std::endl; + if (result != RETURN_OK) { + return result; } result = modeHelper.initialize(); @@ -250,11 +242,9 @@ void DeviceHandlerBase::readCommandQueue() { return; } - if(healthHelperActive) { - result = healthHelper.handleHealthCommand(&command); - if (result == RETURN_OK) { - return; - } + result = healthHelper.handleHealthCommand(&command); + if (result == RETURN_OK) { + return; } result = modeHelper.handleModeCommand(&command); @@ -1032,9 +1022,7 @@ void DeviceHandlerBase::getMode(Mode_t* mode, Submode_t* submode) { } void DeviceHandlerBase::setToExternalControl() { - if(healthHelperActive) { - healthHelper.setHealth(EXTERNAL_CONTROL); - } + healthHelper.setHealth(EXTERNAL_CONTROL); } void DeviceHandlerBase::announceMode(bool recursive) { @@ -1054,25 +1042,12 @@ void DeviceHandlerBase::missedReply(DeviceCommandId_t id) { } HasHealthIF::HealthState DeviceHandlerBase::getHealth() { - if(healthHelperActive) { - return healthHelper.getHealth(); - } - else { - sif::warning << "DeviceHandlerBase::getHealth: Health helper not active" - << std::endl; - return HasHealthIF::HEALTHY; - } + return healthHelper.getHealth(); } ReturnValue_t DeviceHandlerBase::setHealth(HealthState health) { - if(healthHelperActive) { - healthHelper.setHealth(health); - } - else { - sif::warning << "DeviceHandlerBase::getHealth: Health helper not active" - << std::endl; - } - return HasReturnvaluesIF::RETURN_OK; + healthHelper.setHealth(health); + return HasReturnvaluesIF::RETURN_OK; } void DeviceHandlerBase::checkSwitchState() { @@ -1391,18 +1366,6 @@ LocalDataPoolManager* DeviceHandlerBase::getHkManagerHandle() { return &hkManager; } -ReturnValue_t DeviceHandlerBase::addDataSet(sid_t sid) { - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t DeviceHandlerBase::removeDataSet(sid_t sid) { - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t DeviceHandlerBase::changeCollectionInterval(sid_t sid, - dur_seconds_t newInterval) { - return HasReturnvaluesIF::RETURN_OK; -} ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() { // In this function, the task handle should be valid if the task diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 61fb701d..ddbf6041 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -108,7 +108,6 @@ public: CookieIF * comCookie, FailureIsolationBase* fdirInstance = nullptr, size_t cmdQueueSize = 20); - void setDeviceSwitch(uint8_t deviceSwitch); void setHkDestination(object_id_t hkDestination); void setThermalStateRequestPoolIds(uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId); @@ -487,11 +486,6 @@ protected: /** Get the HK manager object handle */ virtual LocalDataPoolManager* getHkManagerHandle() override; - virtual ReturnValue_t addDataSet(sid_t sid) override; - virtual ReturnValue_t removeDataSet(sid_t sid) override; - virtual ReturnValue_t changeCollectionInterval(sid_t sid, - dur_seconds_t newInterval) override; - /** * @brief Hook function for child handlers which is called once per * performOperation(). Default implementation is empty. @@ -610,7 +604,6 @@ protected: /** Health helper for HasHealthIF */ HealthHelper healthHelper; - bool healthHelperActive = false; /** Mode helper for HasModesIF */ ModeHelper modeHelper; /** Parameter helper for ReceivesParameterMessagesIF */ @@ -1079,13 +1072,6 @@ private: */ Submode_t transitionSourceSubMode; - /** - * the switch of the device - * - * for devices using two switches override getSwitches() - */ - uint8_t deviceSwitch; - /** * read the command queue */ From c9bc022941251ad24ddcd2b3e4fff40904c18c1c Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 16 Jul 2020 12:57:29 +0200 Subject: [PATCH 188/653] commented out all new hk manager components --- devicehandlers/DeviceHandlerBase.cpp | 24 ++++++++++++------------ devicehandlers/DeviceHandlerBase.h | 16 ++++++++-------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 282f20b2..6b7dad1e 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -191,14 +191,14 @@ ReturnValue_t DeviceHandlerBase::initialize() { return result; } - if(hkDestination == objects::NO_OBJECT) { - hkDestination = defaultHkDestination; - } - - result = hkManager.initialize(commandQueue, hkDestination); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } +// if(hkDestination == objects::NO_OBJECT) { +// hkDestination = defaultHkDestination; +// } +// +// result = hkManager.initialize(commandQueue, hkDestination); +// if (result != HasReturnvaluesIF::RETURN_OK) { +// return result; +// } fillCommandAndReplyMap(); @@ -262,10 +262,10 @@ void DeviceHandlerBase::readCommandQueue() { return; } - result = hkManager.handleHousekeepingMessage(&command); - if (result == RETURN_OK) { - return; - } +// result = hkManager.handleHousekeepingMessage(&command); +// if (result == RETURN_OK) { +// return; +// } result = handleDeviceHandlerMessage(&command); if (result == RETURN_OK) { diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index ddbf6041..a041dbc7 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -17,8 +17,8 @@ #include #include #include -#include -#include +//#include +//#include #include #include @@ -86,8 +86,8 @@ class DeviceHandlerBase: public DeviceHandlerIF, public HasModesIF, public HasHealthIF, public HasActionsIF, - public ReceivesParameterMessagesIF, - public HasLocalDataPoolIF { + public ReceivesParameterMessagesIF + /* public HasLocalDataPoolIF */ { friend void (Factory::setStaticFrameworkObjectIds)(); public: /** @@ -480,11 +480,11 @@ protected: * @param localDataPoolMap * @return */ - virtual ReturnValue_t initializePoolEntries( - LocalDataPool& localDataPoolMap) override; + //virtual ReturnValue_t initializePoolEntries( + // LocalDataPool& localDataPoolMap) override; /** Get the HK manager object handle */ - virtual LocalDataPoolManager* getHkManagerHandle() override; + //virtual LocalDataPoolManager* getHkManagerHandle() override; /** * @brief Hook function for child handlers which is called once per @@ -611,7 +611,7 @@ protected: /** Action helper for HasActionsIF */ ActionHelper actionHelper; /** Housekeeping Manager */ - LocalDataPoolManager hkManager; + //LocalDataPoolManager hkManager; /** * @brief Information about commands From 6b03a1c03df0ee70c31810b0faafaf507646965b Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 16 Jul 2020 13:00:22 +0200 Subject: [PATCH 189/653] commented out some more components --- devicehandlers/DeviceHandlerBase.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index a041dbc7..66c10778 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -650,9 +650,7 @@ protected: //! The dataset used to access housekeeping data related to the //! respective device reply. Will point to a dataset held by //! the child handler (if one is specified) - DataSetIF* dataSet = nullptr; - float collectionInterval = 0.0; - uint32_t intervalCounter = 0; + // DataSetIF* dataSet = nullptr; //! The command that expects this reply. DeviceCommandMap::iterator command; }; @@ -1195,7 +1193,8 @@ private: ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message); virtual ReturnValue_t initializeAfterTaskCreation() override; - DataSetIF* getDataSetHandle(sid_t sid) override; + + //DataSetIF* getDataSetHandle(sid_t sid) override; void parseReply(const uint8_t* receivedData, size_t receivedDataLen); From dc4db6e031cb1ccb58b89d8a055b54208a939799 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 25 Jun 2020 18:09:32 +0200 Subject: [PATCH 190/653] Fixed spelling mistake in HealthHelper --- devicehandlers/DeviceHandlerBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 6b7dad1e..dc90d812 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -1134,7 +1134,7 @@ ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage( void DeviceHandlerBase::setParentQueue(MessageQueueId_t parentQueueId) { modeHelper.setParentQueue(parentQueueId); - healthHelper.setParentQeueue(parentQueueId); + healthHelper.setParentQueue(parentQueueId); } bool DeviceHandlerBase::isAwaitingReply() { From be9d0a61f47b7e630f8d3ba94b36dd4ee25d0910 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 21 Jul 2020 15:15:53 +0200 Subject: [PATCH 191/653] Fixes #149 --- serviceinterface/ServiceInterfaceBuffer.cpp | 12 ++++++------ serviceinterface/ServiceInterfaceBuffer.h | 2 +- serviceinterface/ServiceInterfaceStream.cpp | 2 +- serviceinterface/ServiceInterfaceStream.h | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 5c80862c..8c510eac 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -78,9 +78,9 @@ int ServiceInterfaceBuffer::sync(void) { } size_t preambleSize = 0; - auto preamble = getPreamble(&preambleSize); + std::string* preamble = getPreamble(&preambleSize); // Write logMessage and time - this->putChars(preamble.data(), preamble.data() + preambleSize); + this->putChars(preamble->data(), preamble->data() + preambleSize); // Handle output this->putChars(pbase(), pptr()); // This tells that buffer is empty again @@ -92,7 +92,7 @@ bool ServiceInterfaceBuffer::isBuffered() const { return buffered; } -std::string ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { +std::string* ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { Clock::TimeOfDay_t loggerTime; Clock::getDateAndTime(&loggerTime); size_t currentSize = 0; @@ -110,18 +110,18 @@ std::string ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { loggerTime.usecond /1000); if(charCount < 0) { printf("ServiceInterfaceBuffer: Failure parsing preamble\r\n"); - return ""; + return &preamble; } if(charCount > MAX_PREAMBLE_SIZE) { printf("ServiceInterfaceBuffer: Char count too large for maximum " "preamble size"); - return ""; + return &preamble; } currentSize += charCount; if(preambleSize != nullptr) { *preambleSize = currentSize; } - return preamble; + return &preamble; } diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index 39ea25c2..7a2ce2ee 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -60,7 +60,7 @@ private: //! In this function, the characters are parsed. void putChars(char const* begin, char const* end); - std::string getPreamble(size_t * preambleSize = nullptr); + std::string* getPreamble(size_t * preambleSize = nullptr); }; #endif diff --git a/serviceinterface/ServiceInterfaceStream.cpp b/serviceinterface/ServiceInterfaceStream.cpp index 76481ed1..31bc7c73 100644 --- a/serviceinterface/ServiceInterfaceStream.cpp +++ b/serviceinterface/ServiceInterfaceStream.cpp @@ -9,7 +9,7 @@ void ServiceInterfaceStream::setActive( bool myActive) { this->streambuf.isActive = myActive; } -std::string ServiceInterfaceStream::getPreamble() { +std::string* ServiceInterfaceStream::getPreamble() { return streambuf.getPreamble(); } diff --git a/serviceinterface/ServiceInterfaceStream.h b/serviceinterface/ServiceInterfaceStream.h index 9e19c228..dc111459 100644 --- a/serviceinterface/ServiceInterfaceStream.h +++ b/serviceinterface/ServiceInterfaceStream.h @@ -33,7 +33,7 @@ public: * the unbuffered mode. * @return Preamle consisting of log message and timestamp. */ - std::string getPreamble(); + std::string* getPreamble(); /** * This prints an error with a preamble. Useful if using the unbuffered From 06e7f286d6592b454823a2027377cfde10be798f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 25 Jul 2020 10:55:28 +0200 Subject: [PATCH 192/653] added explicit brackets --- tmtcservices/CommandingServiceBase.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index 0c5f5eab..331bc7c8 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -212,8 +212,8 @@ void CommandingServiceBase::handleRequestQueue() { address = message.getStorageId(); packet.setStoreAddress(address); - if (packet.getSubService() == 0 - or isValidSubservice(packet.getSubService()) != RETURN_OK) { + if ((packet.getSubService() == 0) + or (isValidSubservice(packet.getSubService()) != RETURN_OK)) { rejectPacket(TC_VERIFY::START_FAILURE, &packet, INVALID_SUBSERVICE); continue; } From 5df88eb73be77446e520d542e062ebcc4728cd78 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 28 Jul 2020 12:20:23 +0200 Subject: [PATCH 193/653] singlyl inked list bugfix --- container/SinglyLinkedList.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/SinglyLinkedList.h b/container/SinglyLinkedList.h index 7d5fc4a9..eb6ae276 100644 --- a/container/SinglyLinkedList.h +++ b/container/SinglyLinkedList.h @@ -100,7 +100,7 @@ public: */ ElementIterator back() const { LinkedElement *element = start; - while (element != nullptr) { + while (element->getNext() != nullptr) { element = element->getNext(); } return ElementIterator::Iterator(element); From 0defc6a7d867ec1d966b2e6078e224c5a94f4686 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 28 Jul 2020 12:36:22 +0200 Subject: [PATCH 194/653] removed folders --- framework.mk | 4 ---- 1 file changed, 4 deletions(-) diff --git a/framework.mk b/framework.mk index c8822981..ee0a7ba4 100644 --- a/framework.mk +++ b/framework.mk @@ -8,9 +8,6 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/controller/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/coordinates/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datalinklayer/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapool/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoolglob/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoollocal/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/housekeeping/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/devicehandlers/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/eventmatching/*.cpp) @@ -58,4 +55,3 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/packetmatcher/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/pus/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcservices/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/test/*.cpp) \ No newline at end of file From 036a887ea31124fe1ae0492343c811afceeb7eef Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 28 Jul 2020 13:02:43 +0200 Subject: [PATCH 195/653] bugfix --- serialize/SerialArrayListAdapter.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/serialize/SerialArrayListAdapter.h b/serialize/SerialArrayListAdapter.h index bcd99818..56fb3452 100644 --- a/serialize/SerialArrayListAdapter.h +++ b/serialize/SerialArrayListAdapter.h @@ -63,6 +63,9 @@ public: count_t tempSize = 0; ReturnValue_t result = SerializeAdapter::deSerialize(&tempSize, buffer, size, streamEndianness); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } if (tempSize > list->maxSize()) { return SerializeIF::TOO_MANY_ELEMENTS; } From 4bffcf17fb2a70373c8d3765796cc8e9f4aac277 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 28 Jul 2020 13:04:58 +0200 Subject: [PATCH 196/653] some formatting stuff --- serialize/SerialArrayListAdapter.h | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/serialize/SerialArrayListAdapter.h b/serialize/SerialArrayListAdapter.h index 56fb3452..21c6951d 100644 --- a/serialize/SerialArrayListAdapter.h +++ b/serialize/SerialArrayListAdapter.h @@ -1,18 +1,13 @@ -/** - * @file SerialArrayListAdapter.h - * @brief This file defines the SerialArrayListAdapter class. - * @date 22.07.2014 - * @author baetz - */ -#ifndef SERIALARRAYLISTADAPTER_H_ -#define SERIALARRAYLISTADAPTER_H_ +#ifndef FRAMEWORK_SERIALIZE_SERIALARRAYLISTADAPTER_H_ +#define FRAMEWORK_SERIALIZE_SERIALARRAYLISTADAPTER_H_ #include #include #include /** - * \ingroup serialize + * @ingroup serialize + * @author baetz */ template class SerialArrayListAdapter : public SerializeIF { @@ -25,14 +20,15 @@ public: return serialize(adaptee, buffer, size, maxSize, streamEndianness); } - static ReturnValue_t serialize(const ArrayList* list, uint8_t** buffer, size_t* size, - size_t maxSize, Endianness streamEndianness) { + static ReturnValue_t serialize(const ArrayList* list, + uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) { ReturnValue_t result = SerializeAdapter::serialize(&list->size, buffer, size, maxSize, streamEndianness); count_t i = 0; while ((result == HasReturnvaluesIF::RETURN_OK) && (i < list->size)) { - result = SerializeAdapter::serialize(&list->entries[i], buffer, size, - maxSize, streamEndianness); + result = SerializeAdapter::serialize(&list->entries[i], buffer, + size, maxSize, streamEndianness); ++i; } return result; @@ -58,7 +54,8 @@ public: return deSerialize(adaptee, buffer, size, streamEndianness); } - static ReturnValue_t deSerialize(ArrayList* list, const uint8_t** buffer, size_t* size, + static ReturnValue_t deSerialize(ArrayList* list, + const uint8_t** buffer, size_t* size, Endianness streamEndianness) { count_t tempSize = 0; ReturnValue_t result = SerializeAdapter::deSerialize(&tempSize, @@ -85,4 +82,4 @@ private: -#endif /* SERIALARRAYLISTADAPTER_H_ */ +#endif /* FRAMEWORK_SERIALIZE_SERIALARRAYLISTADAPTER_H_ */ From 0449c63225de411920dba5a3b7bb88a9eb6c72d1 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 28 Jul 2020 13:13:40 +0200 Subject: [PATCH 197/653] bugfixes --- container/DynamicFIFO.h | 21 ++++++++++++++++++--- container/FIFO.h | 12 ++++++++++-- container/FIFOBase.h | 8 ++++++-- container/FIFOBase.tpp | 8 +++++++- 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/container/DynamicFIFO.h b/container/DynamicFIFO.h index 3a5242c7..59adfb3a 100644 --- a/container/DynamicFIFO.h +++ b/container/DynamicFIFO.h @@ -17,11 +17,26 @@ template class DynamicFIFO: public FIFOBase { public: - DynamicFIFO(size_t maxCapacity): FIFOBase(values.data(), maxCapacity), - values(maxCapacity) {}; + DynamicFIFO(size_t maxCapacity): FIFOBase(nullptr, maxCapacity), + fifoVector(maxCapacity) { + // trying to pass the pointer of the uninitialized vector + // to the FIFOBase constructor directly lead to a super evil bug. + // So we do it like this now. + this->setData(fifoVector.data()); + }; + + /** + * @brief Custom copy constructor which prevents setting the + * underlying pointer wrong. + */ + DynamicFIFO(const DynamicFIFO& other): FIFOBase(other), + fifoVector(other.maxCapacity) { + this->setData(fifoVector.data()); + } + private: - std::vector values; + std::vector fifoVector; }; #endif /* FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ */ diff --git a/container/FIFO.h b/container/FIFO.h index ecb218fd..2e332dc2 100644 --- a/container/FIFO.h +++ b/container/FIFO.h @@ -17,10 +17,18 @@ template class FIFO: public FIFOBase { public: - FIFO(): FIFOBase(values.data(), capacity) {}; + FIFO(): FIFOBase(fifoArray.data(), capacity) {}; + + /** + * @brief Custom copy constructor to set pointer correctly. + * @param other + */ + FIFO(const FIFO& other): FIFOBase(other) { + this->setData(fifoArray.data()); + } private: - std::array values; + std::array fifoArray; }; #endif /* FRAMEWORK_CONTAINERS_STATICFIFO_H_ */ diff --git a/container/FIFOBase.h b/container/FIFOBase.h index 8bdb333f..7f8bde96 100644 --- a/container/FIFOBase.h +++ b/container/FIFOBase.h @@ -3,6 +3,7 @@ #include #include +#include template class FIFOBase { @@ -43,12 +44,15 @@ public: bool full(); size_t size(); + size_t getMaxCapacity() const; -private: - T* values; +protected: + void setData(T* data); size_t maxCapacity = 0; + T* values; + size_t readIndex = 0; size_t writeIndex = 0; size_t currentSize = 0; diff --git a/container/FIFOBase.tpp b/container/FIFOBase.tpp index 48a060ff..c73e9d59 100644 --- a/container/FIFOBase.tpp +++ b/container/FIFOBase.tpp @@ -7,7 +7,7 @@ template inline FIFOBase::FIFOBase(T* values, const size_t maxCapacity): - values(values), maxCapacity(maxCapacity) {}; + maxCapacity(maxCapacity), values(values){}; template inline ReturnValue_t FIFOBase::insert(T value) { @@ -78,4 +78,10 @@ inline size_t FIFOBase::getMaxCapacity() const { return maxCapacity; } + +template +inline void FIFOBase::setData(T *data) { + this->values = data; +} + #endif From 652c60c362f2b9b57ef6b54b6d3ca0b3051e6a3b Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 29 Jul 2020 20:02:04 +0200 Subject: [PATCH 198/653] important bugfix I checked all 5 cases for overflows when checking for missed deadlines (there is current time, timeToWake and lastWakeTime, with various combinations of overflows) This should be the correct implementation now --- osal/FreeRTOS/FixedTimeslotTask.cpp | 19 +++++++++---------- osal/FreeRTOS/PeriodicTask.cpp | 19 +++++++++---------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index c062101d..17804d90 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -125,19 +125,18 @@ void FixedTimeslotTask::checkMissedDeadline(const TickType_t xLastWakeTime, * it. */ TickType_t currentTickCount = xTaskGetTickCount(); TickType_t timeToWake = xLastWakeTime + interval; - // Tick count has overflown - if(currentTickCount < xLastWakeTime) { - // Time to wake has overflown as well. If the tick count - // is larger than the time to wake, a deadline was missed. - if(timeToWake < xLastWakeTime and - currentTickCount > timeToWake) { + // Time to wake has not overflown. + if(timeToWake > xLastWakeTime) { + /* If the current time has overflown exclusively or the current + * tick count is simply larger than the time to wake, a deadline was + * missed */ + if((currentTickCount < xLastWakeTime) or (currentTickCount > timeToWake)) { handleMissedDeadline(); } } - // No tick count overflow. If the timeToWake has not overflown - // and the current tick count is larger than the time to wake, - // a deadline was missed. - else if(timeToWake > xLastWakeTime and currentTickCount > timeToWake) { + /* Time to wake has overflown. A deadline was missed if the current time + * is larger than the time to wake */ + else if((timeToWake < xLastWakeTime) and (currentTickCount > timeToWake)) { handleMissedDeadline(); } } diff --git a/osal/FreeRTOS/PeriodicTask.cpp b/osal/FreeRTOS/PeriodicTask.cpp index 44a7b801..91135375 100644 --- a/osal/FreeRTOS/PeriodicTask.cpp +++ b/osal/FreeRTOS/PeriodicTask.cpp @@ -108,19 +108,18 @@ void PeriodicTask::checkMissedDeadline(const TickType_t xLastWakeTime, * it. */ TickType_t currentTickCount = xTaskGetTickCount(); TickType_t timeToWake = xLastWakeTime + interval; - // Tick count has overflown - if(currentTickCount < xLastWakeTime) { - // Time to wake has overflown as well. If the tick count - // is larger than the time to wake, a deadline was missed. - if(timeToWake < xLastWakeTime and - currentTickCount > timeToWake) { + // Time to wake has not overflown. + if(timeToWake > xLastWakeTime) { + /* If the current time has overflown exclusively or the current + * tick count is simply larger than the time to wake, a deadline was + * missed */ + if((currentTickCount < xLastWakeTime) or (currentTickCount > timeToWake)) { handleMissedDeadline(); } } - // No tick count overflow. If the timeToWake has not overflown - // and the current tick count is larger than the time to wake, - // a deadline was missed. - else if(timeToWake > xLastWakeTime and currentTickCount > timeToWake) { + /* Time to wake has overflown. A deadline was missed if the current time + * is larger than the time to wake */ + else if((timeToWake < xLastWakeTime) and (currentTickCount > timeToWake)) { handleMissedDeadline(); } } From 21984067140f3baf3ecc30db4e1e5d196bae56e6 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 1 Aug 2020 16:53:17 +0200 Subject: [PATCH 199/653] csb update --- tmtcservices/CommandingServiceBase.cpp | 10 +++++----- tmtcservices/CommandingServiceBase.h | 15 ++++++--------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index 98cbbe2c..330fd00f 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -126,11 +126,11 @@ void CommandingServiceBase::handleCommandMessage(CommandMessage* reply) { &nextCommand, iter->objectId, &isStep); /* If the child implementation does not implement special handling for - * rejected replies (RETURN_FAILED is returned), a failure verification - * will be generated with the reason as the return code and the initial - * command as failure parameter 1 */ - if(reply->getCommand() == CommandMessage::REPLY_REJECTED and - result == RETURN_FAILED) { + * rejected replies (RETURN_FAILED or INVALID_REPLY is returned), a + * failure verification will be generated with the reason as the + * return code and the initial command as failure parameter 1 */ + if((reply->getCommand() == CommandMessage::REPLY_REJECTED) and + (result == RETURN_FAILED or result == INVALID_REPLY)) { result = reply->getReplyRejectedReason(); failureParameter1 = iter->command; } diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index 76eca6b7..9290bb7c 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -87,7 +87,7 @@ public: * @param opCode is unused here at the moment * @return RETURN_OK */ - virtual ReturnValue_t performOperation(uint8_t opCode); + virtual ReturnValue_t performOperation(uint8_t opCode) override; virtual uint16_t getIdentifier(); @@ -186,12 +186,11 @@ protected: * @return * - @c RETURN_OK, @c EXECUTION_COMPLETE or @c NO_STEP_MESSAGE to * generate TC verification success - * - @c INVALID_REPLY calls handleUnrequestedReply - * - Anything else triggers a TC verification failure. If RETURN_FAILED or - * INVALID_REPLY is returned and the command ID is - * CommandMessage::REPLY_REJECTED, a failure verification message - * with the reason as the error parameter and the initial command as - * failure parameter 1 is generated. + * - @c INVALID_REPLY Calls handleUnrequestedReply + * - Anything else triggers a TC verification failure. If RETURN_FAILED is + * returned and the command ID is CommandMessage::REPLY_REJECTED, + * a failure verification message with the reason as the error parameter + * and the initial command as failure parameter 1 */ virtual ReturnValue_t handleReply(const CommandMessage* reply, Command_t previousCommand, uint32_t *state, @@ -254,7 +253,6 @@ protected: uint32_t failureParameter1 = 0; uint32_t failureParameter2 = 0; - object_id_t packetSource; static object_id_t defaultPacketSource; object_id_t packetSource = objects::NO_OBJECT; static object_id_t defaultPacketDestination; @@ -303,7 +301,6 @@ protected: void checkAndExecuteFifo(CommandMapIter iter); private: - /** * This method handles internal execution of a command, * once it has been started by @sa{startExecution()} in the request From d8bf1931ccbbca5d96598905599bdf594e914c7f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 1 Aug 2020 16:55:20 +0200 Subject: [PATCH 200/653] doc correction --- tmtcservices/CommandingServiceBase.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index 9290bb7c..b3a15985 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -187,10 +187,11 @@ protected: * - @c RETURN_OK, @c EXECUTION_COMPLETE or @c NO_STEP_MESSAGE to * generate TC verification success * - @c INVALID_REPLY Calls handleUnrequestedReply - * - Anything else triggers a TC verification failure. If RETURN_FAILED is - * returned and the command ID is CommandMessage::REPLY_REJECTED, - * a failure verification message with the reason as the error parameter - * and the initial command as failure parameter 1 + * - Anything else triggers a TC verification failure. If RETURN_FAILED or + * INVALID_REPLY is returned and the command ID is + * CommandMessage::REPLY_REJECTED, a failure verification message with + * the reason as the error parameter and the initial command as + * failure parameter 1 is generated. */ virtual ReturnValue_t handleReply(const CommandMessage* reply, Command_t previousCommand, uint32_t *state, From a0ff1e0019824feb8da8183ce2051b5890bb6cb9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 2 Aug 2020 15:46:25 +0200 Subject: [PATCH 201/653] reverted datapool changes --- devicehandlers/DeviceHandlerBase.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index dc90d812..8e256bcf 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -4,11 +4,11 @@ #include #include -#include -#include +#include +#include #include #include -#include +//#include #include #include #include @@ -203,8 +203,8 @@ ReturnValue_t DeviceHandlerBase::initialize() { fillCommandAndReplyMap(); //Set temperature target state to NON_OP. - GlobDataSet mySet; - gp_uint8_t thermalRequest(deviceThermalRequestPoolId, &mySet, + DataSet mySet; + dp_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_WRITE); mySet.read(); thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; @@ -486,8 +486,8 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) { Clock::getUptime(&timeoutStart); if (mode == MODE_OFF) { - GlobDataSet mySet; - gp_uint8_t thermalRequest(deviceThermalRequestPoolId, &mySet, + DataSet mySet; + db_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { @@ -943,10 +943,10 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, if ((commandedMode == MODE_ON) && (mode == MODE_OFF) && (deviceThermalStatePoolId != PoolVariableIF::NO_PARAMETER)) { - GlobDataSet mySet; - gp_uint8_t thermalState(deviceThermalStatePoolId, &mySet, + DataSet mySet; + db_int8_t thermalState(deviceThermalStatePoolId, &mySet, PoolVariableIF::VAR_READ); - gp_uint8_t thermalRequest(deviceThermalRequestPoolId, &mySet, + db_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_READ); mySet.read(); if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { @@ -973,8 +973,8 @@ void DeviceHandlerBase::startTransition(Mode_t commandedMode, childTransitionDelay = getTransitionDelayMs(_MODE_START_UP, MODE_ON); triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode); - GlobDataSet mySet; - gp_int8_t thermalRequest(deviceThermalRequestPoolId, + DataSet mySet; + db_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { From 2e08037e75f1457d67ef13e14c5b87765ee4a03d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 2 Aug 2020 15:48:09 +0200 Subject: [PATCH 202/653] revertiing pool changes --- devicehandlers/DeviceHandlerBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 8e256bcf..c09d913e 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -204,7 +204,7 @@ ReturnValue_t DeviceHandlerBase::initialize() { //Set temperature target state to NON_OP. DataSet mySet; - dp_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, + db_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_WRITE); mySet.read(); thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; From d58fc5c6f71724221c10968bddad8a3d29e66fe5 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 2 Aug 2020 15:55:56 +0200 Subject: [PATCH 203/653] removed includes in framework.mk --- framework.mk | 2 -- 1 file changed, 2 deletions(-) diff --git a/framework.mk b/framework.mk index 7f27c037..04fac47f 100644 --- a/framework.mk +++ b/framework.mk @@ -8,8 +8,6 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/controller/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/coordinates/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datalinklayer/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapool/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoolglob/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoollocal/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/housekeeping/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/devicehandlers/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/*.cpp) From 6ac36cec1546ba637c822979243ab1fc4a51ba1e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 2 Aug 2020 15:56:38 +0200 Subject: [PATCH 204/653] removed other include in framework.mk --- framework.mk | 1 - 1 file changed, 1 deletion(-) diff --git a/framework.mk b/framework.mk index 04fac47f..c3917f20 100644 --- a/framework.mk +++ b/framework.mk @@ -8,7 +8,6 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/controller/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/coordinates/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datalinklayer/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapool/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/housekeeping/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/devicehandlers/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/eventmatching/*.cpp) From 78442a8b92b5548098fca7439a78ba65978de4b5 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Tue, 4 Aug 2020 12:22:45 +0200 Subject: [PATCH 205/653] Amending PR #145, forgot some documentation --- action/ActionHelper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action/ActionHelper.h b/action/ActionHelper.h index 3d8351d6..eb3bfa54 100644 --- a/action/ActionHelper.h +++ b/action/ActionHelper.h @@ -35,7 +35,7 @@ public: ReturnValue_t handleActionMessage(CommandMessage* command); /** * Helper initialize function. Must be called before use of any other helper function - * @param queueToUse_ Pointer to the messageQueue to be used + * @param queueToUse_ Pointer to the messageQueue to be used, optional if queue was set in constructor * @return Returns RETURN_OK if successful */ ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr); From ea9288d848d62352c78e81dd98cc6555bb6a12d5 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 4 Aug 2020 15:17:40 +0200 Subject: [PATCH 206/653] updated subsystem ID range --- events/fwSubsystemIdRanges.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/events/fwSubsystemIdRanges.h b/events/fwSubsystemIdRanges.h index 4c261e57..a05652c2 100644 --- a/events/fwSubsystemIdRanges.h +++ b/events/fwSubsystemIdRanges.h @@ -18,6 +18,8 @@ enum { SYSTEM_MANAGER = 74, SYSTEM_MANAGER_1 = 75, SYSTEM_1 = 79, + PUS_SERVICE_1 = 80, + FW_SUBSYSTEM_ID_RANGE }; } From c42b5283af448e288bc54775e51e80ebb50715a8 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 4 Aug 2020 15:19:31 +0200 Subject: [PATCH 207/653] periodic task IF: setting task if boolean removed --- osal/linux/PeriodicPosixTask.cpp | 7 ++----- osal/linux/PeriodicPosixTask.h | 3 +-- tasks/PeriodicTaskIF.h | 3 +-- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/osal/linux/PeriodicPosixTask.cpp b/osal/linux/PeriodicPosixTask.cpp index c05f1030..6b2ebd88 100644 --- a/osal/linux/PeriodicPosixTask.cpp +++ b/osal/linux/PeriodicPosixTask.cpp @@ -21,8 +21,7 @@ void* PeriodicPosixTask::taskEntryPoint(void* arg) { return NULL; } -ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object, - bool addTaskIF) { +ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object) { ExecutableObjectIF* newObject = objectManager->get( object); if (newObject == nullptr) { @@ -30,9 +29,7 @@ ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object, } objectList.push_back(newObject); - if(setTaskIF) { - newObject->setTaskIF(this); - } + newObject->setTaskIF(this); return HasReturnvaluesIF::RETURN_OK; } diff --git a/osal/linux/PeriodicPosixTask.h b/osal/linux/PeriodicPosixTask.h index bf1a995b..b194733b 100644 --- a/osal/linux/PeriodicPosixTask.h +++ b/osal/linux/PeriodicPosixTask.h @@ -39,8 +39,7 @@ public: * @param object Id of the object to add. * @return RETURN_OK on success, RETURN_FAILED if the object could not be added. */ - ReturnValue_t addComponent(object_id_t object, - bool addTaskIF = true) override; + ReturnValue_t addComponent(object_id_t object) override; uint32_t getPeriodMs() const override; diff --git a/tasks/PeriodicTaskIF.h b/tasks/PeriodicTaskIF.h index 6f490977..f54d6155 100644 --- a/tasks/PeriodicTaskIF.h +++ b/tasks/PeriodicTaskIF.h @@ -36,8 +36,7 @@ public: * to the component. * @return */ - virtual ReturnValue_t addComponent(object_id_t object, - bool setTaskIF = true) { + virtual ReturnValue_t addComponent(object_id_t object) { return HasReturnvaluesIF::RETURN_FAILED; }; From 9102eec4ab20e13bd15acdac83498e88398856b3 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 4 Aug 2020 15:20:43 +0200 Subject: [PATCH 208/653] interface change for freeRTOS --- osal/FreeRTOS/PeriodicTask.cpp | 6 ++---- osal/FreeRTOS/PeriodicTask.h | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/osal/FreeRTOS/PeriodicTask.cpp b/osal/FreeRTOS/PeriodicTask.cpp index 44a7b801..e84411f8 100644 --- a/osal/FreeRTOS/PeriodicTask.cpp +++ b/osal/FreeRTOS/PeriodicTask.cpp @@ -81,7 +81,7 @@ void PeriodicTask::taskFunctionality() { } } -ReturnValue_t PeriodicTask::addComponent(object_id_t object, bool setTaskIF) { +ReturnValue_t PeriodicTask::addComponent(object_id_t object) { ExecutableObjectIF* newObject = objectManager->get( object); if (newObject == nullptr) { @@ -91,9 +91,7 @@ ReturnValue_t PeriodicTask::addComponent(object_id_t object, bool setTaskIF) { } objectList.push_back(newObject); - if(setTaskIF) { - newObject->setTaskIF(this); - } + newObject->setTaskIF(this); return HasReturnvaluesIF::RETURN_OK; } diff --git a/osal/FreeRTOS/PeriodicTask.h b/osal/FreeRTOS/PeriodicTask.h index 09aa6bc7..eea88dfd 100644 --- a/osal/FreeRTOS/PeriodicTask.h +++ b/osal/FreeRTOS/PeriodicTask.h @@ -63,8 +63,7 @@ public: * -@c RETURN_OK on success * -@c RETURN_FAILED if the object could not be added. */ - ReturnValue_t addComponent(object_id_t object, - bool setTaskIF = true) override; + ReturnValue_t addComponent(object_id_t object) override; uint32_t getPeriodMs() const override; From 7b3fddfd429a02f6dedaad4e33a7c0a308f540d4 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 7 Aug 2020 22:10:58 +0200 Subject: [PATCH 209/653] implemented mutex if changes --- ipc/MutexHelper.h | 5 +++-- ipc/MutexIF.h | 38 ++++++++++++++++++++------------------ osal/FreeRTOS/Mutex.cpp | 17 ++++++++--------- osal/FreeRTOS/Mutex.h | 4 +++- 4 files changed, 34 insertions(+), 30 deletions(-) diff --git a/ipc/MutexHelper.h b/ipc/MutexHelper.h index 20760b32..fc6e38bf 100644 --- a/ipc/MutexHelper.h +++ b/ipc/MutexHelper.h @@ -8,9 +8,10 @@ class MutexHelper { public: MutexHelper(MutexIF* mutex, uint32_t timeoutMs) : internalMutex(mutex) { - ReturnValue_t status = mutex->lockMutex(timeoutMs); + ReturnValue_t status = mutex->lockMutex(MutexIF::TimeoutType::WAITING, + timeoutMs); if(status == MutexIF::MUTEX_TIMEOUT) { - sif::error << "MutexHelper: Lock of mutex failed with timeout of" + sif::error << "MutexHelper: Lock of mutex failed with timeout of " << timeoutMs << " milliseconds!" << std::endl; } else if(status != HasReturnvaluesIF::RETURN_OK){ diff --git a/ipc/MutexIF.h b/ipc/MutexIF.h index 29e59e58..b0096a34 100644 --- a/ipc/MutexIF.h +++ b/ipc/MutexIF.h @@ -5,27 +5,31 @@ /** * @brief Common interface for OS Mutex objects which provide MUTual EXclusion. - * * @details https://en.wikipedia.org/wiki/Lock_(computer_science) * @ingroup osal * @ingroup interface */ class MutexIF { public: - /** - * @brief Timeout value used for polling lock attempt. - * @details - * If the lock is not successfull, MUTEX_TIMEOUT will be returned - * immediately. Value needs to be defined in implementation. - */ - static const uint32_t POLLING; - /** - * @brief Timeout value used for permanent blocking lock attempt. - * @details - * The task will be blocked (indefinitely) until the mutex is unlocked. - * Value needs to be defined in implementation. - */ - static const uint32_t BLOCKING; + /** + * Different types of timeout for the mutex lock. + */ + enum TimeoutType { + POLLING, //!< If mutex is not available, return immediately + WAITING, //!< Wait a specified time for the mutex to become available + BLOCKING //!< Block indefinitely until the mutex becomes available. + }; + + /** + * Lock the mutex. The timeout value will only be used for + * TimeoutType::WAITING + * @param timeoutType + * @param timeoutMs + * @return + */ + virtual ReturnValue_t lockMutex(TimeoutType timeoutType = + TimeoutType::BLOCKING, uint32_t timeoutMs = 0) = 0; + virtual ReturnValue_t unlockMutex() = 0; static const uint8_t INTERFACE_ID = CLASS_ID::MUTEX_IF; /** @@ -77,9 +81,7 @@ public: */ static const ReturnValue_t MUTEX_DESTROYED_WHILE_WAITING = MAKE_RETURN_CODE(12); - virtual ~MutexIF() {} - virtual ReturnValue_t lockMutex(uint32_t timeoutMs) = 0; - virtual ReturnValue_t unlockMutex() = 0; + virtual ~MutexIF() {} }; diff --git a/osal/FreeRTOS/Mutex.cpp b/osal/FreeRTOS/Mutex.cpp index 6d90c3f6..764b0ae0 100644 --- a/osal/FreeRTOS/Mutex.cpp +++ b/osal/FreeRTOS/Mutex.cpp @@ -2,13 +2,10 @@ #include -const uint32_t MutexIF::POLLING = 0; -const uint32_t MutexIF::BLOCKING = portMAX_DELAY; - Mutex::Mutex() { handle = xSemaphoreCreateMutex(); if(handle == nullptr) { - sif::error << "Mutex: Creation failure" << std::endl; + sif::error << "Mutex::Mutex(FreeRTOS): Creation failure" << std::endl; } } @@ -19,15 +16,17 @@ Mutex::~Mutex() { } -ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { +ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType, + uint32_t timeoutMs) { if (handle == nullptr) { return MutexIF::MUTEX_NOT_FOUND; } - TickType_t timeout = MutexIF::POLLING; - if(timeoutMs == MutexIF::BLOCKING) { - timeout = MutexIF::BLOCKING; + // If the timeout type is BLOCKING, this will be the correct value. + uint32_t timeout = portMAX_DELAY; + if(timeoutType == TimeoutType::POLLING) { + timeout = 0; } - else if(timeoutMs > MutexIF::POLLING){ + else if(timeoutType == TimeoutType::WAITING){ timeout = pdMS_TO_TICKS(timeoutMs); } diff --git a/osal/FreeRTOS/Mutex.h b/osal/FreeRTOS/Mutex.h index d6e0aab9..2a4fae26 100644 --- a/osal/FreeRTOS/Mutex.h +++ b/osal/FreeRTOS/Mutex.h @@ -18,8 +18,10 @@ class Mutex : public MutexIF { public: Mutex(); ~Mutex(); - ReturnValue_t lockMutex(uint32_t timeoutMs = MutexIF::BLOCKING) override; + ReturnValue_t lockMutex(TimeoutType timeoutType, + uint32_t timeoutMs) override; ReturnValue_t unlockMutex() override; + private: SemaphoreHandle_t handle; }; From caeb2f9dd639cddd9674f2b0c5cc32887a4db041 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 7 Aug 2020 22:16:10 +0200 Subject: [PATCH 210/653] mutex api changes --- ipc/MutexHelper.h | 5 +++-- osal/linux/Mutex.cpp | 41 ++++++++++++++++++++++++----------------- osal/linux/Mutex.h | 10 +++++++--- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/ipc/MutexHelper.h b/ipc/MutexHelper.h index fc6e38bf..52ce51e3 100644 --- a/ipc/MutexHelper.h +++ b/ipc/MutexHelper.h @@ -6,9 +6,10 @@ class MutexHelper { public: - MutexHelper(MutexIF* mutex, uint32_t timeoutMs) : + MutexHelper(MutexIF* mutex, MutexIF::TimeoutType timeoutType = + MutexIF::TimeoutType::BLOCKING, uint32_t timeoutMs = 0) : internalMutex(mutex) { - ReturnValue_t status = mutex->lockMutex(MutexIF::TimeoutType::WAITING, + ReturnValue_t status = mutex->lockMutex(timeoutType, timeoutMs); if(status == MutexIF::MUTEX_TIMEOUT) { sif::error << "MutexHelper: Lock of mutex failed with timeout of " diff --git a/osal/linux/Mutex.cpp b/osal/linux/Mutex.cpp index 169ac354..03789e62 100644 --- a/osal/linux/Mutex.cpp +++ b/osal/linux/Mutex.cpp @@ -2,8 +2,6 @@ #include #include -const uint32_t MutexIF::POLLING = 0; -const uint32_t MutexIF::BLOCKING = 0xffffffff; uint8_t Mutex::count = 0; @@ -26,7 +24,9 @@ Mutex::Mutex() { sif::error << "Mutex: creation with name, id " << mutex.__data.__count << ", " << " failed with " << strerror(status) << std::endl; } - //After a mutex attributes object has been used to initialize one or more mutexes, any function affecting the attributes object (including destruction) shall not affect any previously initialized mutexes. + // After a mutex attributes object has been used to initialize one or more + // mutexes, any function affecting the attributes object + // (including destruction) shall not affect any previously initialized mutexes. status = pthread_mutexattr_destroy(&mutexAttr); if (status != 0) { sif::error << "Mutex: Attribute destroy failed with " << strerror(status) << std::endl; @@ -38,15 +38,13 @@ Mutex::~Mutex() { pthread_mutex_destroy(&mutex); } -ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { +ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType, uint32_t timeoutMs) { int status = 0; - if(timeoutMs == MutexIF::POLLING) { - status = pthread_mutex_trylock(&mutex); + + if(timeoutType == TimeoutType::POLLING) { + status = pthread_mutex_trylock(&mutex); } - else if (timeoutMs == MutexIF::BLOCKING) { - status = pthread_mutex_lock(&mutex); - } - else { + else if (timeoutType == TimeoutType::WAITING) { timespec timeOut; clock_gettime(CLOCK_REALTIME, &timeOut); uint64_t nseconds = timeOut.tv_sec * 1000000000 + timeOut.tv_nsec; @@ -55,25 +53,34 @@ ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { timeOut.tv_nsec = nseconds - timeOut.tv_sec * 1000000000; status = pthread_mutex_timedlock(&mutex, &timeOut); } + else if(timeoutType == TimeoutType::BLOCKING) { + status = pthread_mutex_lock(&mutex); + } switch (status) { case EINVAL: - //The mutex was created with the protocol attribute having the value PTHREAD_PRIO_PROTECT and the calling thread's priority is higher than the mutex's current priority ceiling. + // The mutex was created with the protocol attribute having the value + // PTHREAD_PRIO_PROTECT and the calling thread's priority is higher + // than the mutex's current priority ceiling. return WRONG_ATTRIBUTE_SETTING; - //The process or thread would have blocked, and the abs_timeout parameter specified a nanoseconds field value less than zero or greater than or equal to 1000 million. - //The value specified by mutex does not refer to an initialized mutex object. + // The process or thread would have blocked, and the abs_timeout + // parameter specified a nanoseconds field value less than zero or + // greater than or equal to 1000 million. + // The value specified by mutex does not refer to an initialized mutex object. //return MUTEX_NOT_FOUND; case EBUSY: - //The mutex could not be acquired because it was already locked. + // The mutex could not be acquired because it was already locked. return MUTEX_ALREADY_LOCKED; case ETIMEDOUT: - //The mutex could not be locked before the specified timeout expired. + // The mutex could not be locked before the specified timeout expired. return MUTEX_TIMEOUT; case EAGAIN: - //The mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded. + // The mutex could not be acquired because the maximum number of + // recursive locks for mutex has been exceeded. return MUTEX_MAX_LOCKS; case EDEADLK: - //A deadlock condition was detected or the current thread already owns the mutex. + // A deadlock condition was detected or the current thread + // already owns the mutex. return CURR_THREAD_ALREADY_OWNS_MUTEX; case 0: //Success diff --git a/osal/linux/Mutex.h b/osal/linux/Mutex.h index d02d008f..26420c2e 100644 --- a/osal/linux/Mutex.h +++ b/osal/linux/Mutex.h @@ -1,14 +1,18 @@ -#ifndef OS_RTEMS_MUTEX_H_ -#define OS_RTEMS_MUTEX_H_ +#ifndef OS_LINUX_MUTEX_H_ +#define OS_LINUX_MUTEX_H_ #include + +extern "C" { #include +} + class Mutex : public MutexIF { public: Mutex(); virtual ~Mutex(); - virtual ReturnValue_t lockMutex(uint32_t timeoutMs); + virtual ReturnValue_t lockMutex(TimeoutType timeoutType, uint32_t timeoutMs); virtual ReturnValue_t unlockMutex(); private: pthread_mutex_t mutex; From 54825dca6b3c63259a4eb1a45878358e5ae1192d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 7 Aug 2020 22:19:13 +0200 Subject: [PATCH 211/653] periodic posix task hotfix --- osal/linux/PeriodicPosixTask.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osal/linux/PeriodicPosixTask.cpp b/osal/linux/PeriodicPosixTask.cpp index c05f1030..548590ac 100644 --- a/osal/linux/PeriodicPosixTask.cpp +++ b/osal/linux/PeriodicPosixTask.cpp @@ -22,7 +22,7 @@ void* PeriodicPosixTask::taskEntryPoint(void* arg) { } ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object, - bool addTaskIF) { + bool addTaskIF) { ExecutableObjectIF* newObject = objectManager->get( object); if (newObject == nullptr) { @@ -30,9 +30,7 @@ ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object, } objectList.push_back(newObject); - if(setTaskIF) { - newObject->setTaskIF(this); - } + newObject->setTaskIF(this); return HasReturnvaluesIF::RETURN_OK; } From 90a3e2b8c5dfa121fb02a8627d9cbe8973261a0e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 7 Aug 2020 22:26:01 +0200 Subject: [PATCH 212/653] linux hotfix --- osal/linux/PeriodicPosixTask.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osal/linux/PeriodicPosixTask.cpp b/osal/linux/PeriodicPosixTask.cpp index c05f1030..6149c84b 100644 --- a/osal/linux/PeriodicPosixTask.cpp +++ b/osal/linux/PeriodicPosixTask.cpp @@ -29,10 +29,8 @@ ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object, return HasReturnvaluesIF::RETURN_FAILED; } objectList.push_back(newObject); + newObject->setTaskIF(this); - if(setTaskIF) { - newObject->setTaskIF(this); - } return HasReturnvaluesIF::RETURN_OK; } From a0f41d3238395e55a4bab09c16eb3c437a72d87b Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 8 Aug 2020 12:46:06 +0200 Subject: [PATCH 213/653] stack size is bytes now --- osal/FreeRTOS/FixedTimeslotTask.cpp | 11 ++++++++--- osal/FreeRTOS/FixedTimeslotTask.h | 7 +++++-- osal/FreeRTOS/FreeRTOSTaskIF.h | 13 +++++++++++++ osal/FreeRTOS/PeriodicTask.cpp | 19 +++++++++++-------- osal/FreeRTOS/PeriodicTask.h | 13 ++++++++----- tasks/Typedef.h | 1 - 6 files changed, 45 insertions(+), 19 deletions(-) create mode 100644 osal/FreeRTOS/FreeRTOSTaskIF.h diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index 17804d90..2a7bff9c 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -5,11 +5,12 @@ uint32_t FixedTimeslotTask::deadlineMissedCount = 0; const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE; -FixedTimeslotTask::FixedTimeslotTask(const char *name, TaskPriority setPriority, +FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority, TaskStackSize setStack, TaskPeriod overallPeriod, void (*setDeadlineMissedFunc)()) : started(false), handle(NULL), pst(overallPeriod * 1000) { - xTaskCreate(taskEntryPoint, name, setStack, this, setPriority, &handle); + configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); + xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle); // All additional attributes are applied to the object. this->deadlineMissedFunc = setDeadlineMissedFunc; } @@ -82,7 +83,7 @@ ReturnValue_t FixedTimeslotTask::checkSequence() const { void FixedTimeslotTask::taskFunctionality() { // A local iterator for the Polling Sequence Table is created to find the // start time for the first entry. - FixedSlotSequence::SlotListIter slotListIter = pst.current; + auto slotListIter = pst.current; //The start time for the first entry is read. uint32_t intervalMs = slotListIter->pollingTimeMs; @@ -155,3 +156,7 @@ ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { vTaskDelay(pdMS_TO_TICKS(ms)); return HasReturnvaluesIF::RETURN_OK; } + +TaskHandle_t FixedTimeslotTask::getTaskHandle() { + return handle; +} diff --git a/osal/FreeRTOS/FixedTimeslotTask.h b/osal/FreeRTOS/FixedTimeslotTask.h index 66af0311..a1fdfdeb 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.h +++ b/osal/FreeRTOS/FixedTimeslotTask.h @@ -1,6 +1,7 @@ #ifndef FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ #define FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ +#include #include #include #include @@ -8,7 +9,7 @@ #include #include -class FixedTimeslotTask: public FixedTimeslotTaskIF { +class FixedTimeslotTask: public FixedTimeslotTaskIF, public FreeRTOSTaskIF { public: /** @@ -23,7 +24,7 @@ public: * @param setDeadlineMissedFunc Callback if a deadline was missed. * @return Pointer to the newly created task. */ - FixedTimeslotTask(const char *name, TaskPriority setPriority, + FixedTimeslotTask(TaskName name, TaskPriority setPriority, TaskStackSize setStack, TaskPeriod overallPeriod, void (*setDeadlineMissedFunc)()); @@ -57,6 +58,8 @@ public: ReturnValue_t sleepFor(uint32_t ms) override; + TaskHandle_t getTaskHandle() override; + protected: bool started; TaskHandle_t handle; diff --git a/osal/FreeRTOS/FreeRTOSTaskIF.h b/osal/FreeRTOS/FreeRTOSTaskIF.h new file mode 100644 index 00000000..06fda282 --- /dev/null +++ b/osal/FreeRTOS/FreeRTOSTaskIF.h @@ -0,0 +1,13 @@ +#ifndef FRAMEWORK_OSAL_FREERTOS_FREERTOSTASKIF_H_ +#define FRAMEWORK_OSAL_FREERTOS_FREERTOSTASKIF_H_ + +#include +#include + +class FreeRTOSTaskIF { +public: + virtual~ FreeRTOSTaskIF() {} + virtual TaskHandle_t getTaskHandle() = 0; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_FREERTOSTASKIF_H_ */ diff --git a/osal/FreeRTOS/PeriodicTask.cpp b/osal/FreeRTOS/PeriodicTask.cpp index 91135375..7b0c8619 100644 --- a/osal/FreeRTOS/PeriodicTask.cpp +++ b/osal/FreeRTOS/PeriodicTask.cpp @@ -5,12 +5,13 @@ PeriodicTask::PeriodicTask(const char *name, TaskPriority setPriority, TaskStackSize setStack, TaskPeriod setPeriod, - void (*setDeadlineMissedFunc)()) : + TaskDeadlineMissedFunction deadlineMissedFunc) : started(false), handle(NULL), period(setPeriod), deadlineMissedFunc( - setDeadlineMissedFunc) + deadlineMissedFunc) { + configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); BaseType_t status = xTaskCreate(taskEntryPoint, name, - setStack, this, setPriority, &handle); + stackSize, this, setPriority, &handle); if(status != pdPASS){ sif::debug << "PeriodicTask Insufficient heap memory remaining. " "Status: " << status << std::endl; @@ -81,19 +82,17 @@ void PeriodicTask::taskFunctionality() { } } -ReturnValue_t PeriodicTask::addComponent(object_id_t object, bool setTaskIF) { +ReturnValue_t PeriodicTask::addComponent(object_id_t object) { ExecutableObjectIF* newObject = objectManager->get( object); if (newObject == nullptr) { sif::error << "PeriodicTask::addComponent: Invalid object. Make sure" - "it implements ExecutableObjectIF!" << std::endl; + "it implement ExecutableObjectIF" << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } objectList.push_back(newObject); + newObject->setTaskIF(this); - if(setTaskIF) { - newObject->setTaskIF(this); - } return HasReturnvaluesIF::RETURN_OK; } @@ -124,6 +123,10 @@ void PeriodicTask::checkMissedDeadline(const TickType_t xLastWakeTime, } } +TaskHandle_t PeriodicTask::getTaskHandle() { + return handle; +} + void PeriodicTask::handleMissedDeadline() { #ifdef DEBUG sif::warning << "PeriodicTask: " << pcTaskGetName(NULL) << diff --git a/osal/FreeRTOS/PeriodicTask.h b/osal/FreeRTOS/PeriodicTask.h index 09aa6bc7..8030baad 100644 --- a/osal/FreeRTOS/PeriodicTask.h +++ b/osal/FreeRTOS/PeriodicTask.h @@ -1,10 +1,12 @@ #ifndef FRAMEWORK_OSAL_FREERTOS_PERIODICTASK_H_ #define FRAMEWORK_OSAL_FREERTOS_PERIODICTASK_H_ +#include #include #include #include + #include #include @@ -17,7 +19,7 @@ class ExecutableObjectIF; * periodic activities of multiple objects. * @ingroup task_handling */ -class PeriodicTask: public PeriodicTaskIF { +class PeriodicTask: public PeriodicTaskIF, public FreeRTOSTaskIF { public: /** * Keep in Mind that you need to call before this vTaskStartScheduler()! @@ -38,9 +40,9 @@ public: * The function pointer to the deadline missed function that shall * be assigned. */ - PeriodicTask(const char *name, TaskPriority setPriority, + PeriodicTask(TaskName name, TaskPriority setPriority, TaskStackSize setStack, TaskPeriod setPeriod, - void (*setDeadlineMissedFunc)()); + TaskDeadlineMissedFunction deadlineMissedFunc); /** * @brief Currently, the executed object's lifetime is not coupled with * the task object's lifetime, so the destructor is empty. @@ -63,12 +65,13 @@ public: * -@c RETURN_OK on success * -@c RETURN_FAILED if the object could not be added. */ - ReturnValue_t addComponent(object_id_t object, - bool setTaskIF = true) override; + ReturnValue_t addComponent(object_id_t object) override; uint32_t getPeriodMs() const override; ReturnValue_t sleepFor(uint32_t ms) override; + + TaskHandle_t getTaskHandle() override; protected: bool started; TaskHandle_t handle; diff --git a/tasks/Typedef.h b/tasks/Typedef.h index b393ee1e..07d96b00 100644 --- a/tasks/Typedef.h +++ b/tasks/Typedef.h @@ -1,7 +1,6 @@ #ifndef FRAMEWORK_TASKS_TYPEDEF_H_ #define FRAMEWORK_TASKS_TYPEDEF_H_ -//TODO more generic? typedef const char* TaskName; typedef uint8_t TaskPriority; typedef size_t TaskStackSize; From 944226c2ed117120749610bdaab03503c523b2fd Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 8 Aug 2020 12:47:14 +0200 Subject: [PATCH 214/653] periodic task if fix --- tasks/PeriodicTaskIF.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tasks/PeriodicTaskIF.h b/tasks/PeriodicTaskIF.h index 6f490977..f54d6155 100644 --- a/tasks/PeriodicTaskIF.h +++ b/tasks/PeriodicTaskIF.h @@ -36,8 +36,7 @@ public: * to the component. * @return */ - virtual ReturnValue_t addComponent(object_id_t object, - bool setTaskIF = true) { + virtual ReturnValue_t addComponent(object_id_t object) { return HasReturnvaluesIF::RETURN_FAILED; }; From e61fdd0d5ef25108c64b467455971cf88a2f0b1c Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 8 Aug 2020 13:15:41 +0200 Subject: [PATCH 215/653] freeRTOS task management init --- osal/FreeRTOS/TaskManagement.cpp | 24 ++++++++++++ osal/FreeRTOS/TaskManagement.h | 64 ++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 osal/FreeRTOS/TaskManagement.cpp create mode 100644 osal/FreeRTOS/TaskManagement.h diff --git a/osal/FreeRTOS/TaskManagement.cpp b/osal/FreeRTOS/TaskManagement.cpp new file mode 100644 index 00000000..ff552adb --- /dev/null +++ b/osal/FreeRTOS/TaskManagement.cpp @@ -0,0 +1,24 @@ +#include + +void TaskManagement::vRequestContextSwitchFromTask() { + vTaskDelay(0); +} + +void TaskManagement::requestContextSwitch( + CallContext callContext = CallContext::TASK) { + if(callContext == CallContext::ISR) { + // This function depends on the partmacro.h definition for the specific device + vRequestContextSwitchFromISR(); + } else { + vRequestContextSwitchFromTask(); + } +} + +TaskHandle_t TaskManagement::getCurrentTaskHandle() { + return xTaskGetCurrentTaskHandle(); +} + +size_t TaskManagement::getTaskStackHighWatermark( + TaskHandle_t task) { + return uxTaskGetStackHighWaterMark(task) * sizeof(StackType_t); +} diff --git a/osal/FreeRTOS/TaskManagement.h b/osal/FreeRTOS/TaskManagement.h new file mode 100644 index 00000000..62c68331 --- /dev/null +++ b/osal/FreeRTOS/TaskManagement.h @@ -0,0 +1,64 @@ +#ifndef FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ +#define FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ + +#include + +extern "C" { +#include +#include +} +#include + +/** + * Architecture dependant portmacro.h function call. + * Should be implemented in bsp. + */ +extern void vRequestContextSwitchFromISR(); + +/*! + * Used by functions to tell if they are being called from + * within an ISR or from a regular task. This is required because FreeRTOS + * has different functions for handling semaphores and messages from within + * an ISR and task. + */ +enum class CallContext { + TASK = 0x00,//!< task_context + ISR = 0xFF //!< isr_context +}; + + +class TaskManagement { +public: + /** + * @brief In this function, a function dependant on the portmacro.h header + * function calls to request a context switch can be specified. + * This can be used if sending to the queue from an ISR caused a task + * to unblock and a context switch is required. + */ + static void requestContextSwitch(CallContext callContext); + + /** + * If task preemption in FreeRTOS is disabled, a context switch + * can be requested manually by calling this function. + */ + static void vRequestContextSwitchFromTask(void); + + /** + * @return The current task handle + */ + static TaskHandle_t getCurrentTaskHandle(); + + /** + * Get returns the minimum amount of remaining stack space in words + * that was a available to the task since the task started executing. + * Please note that the actual value in bytes depends + * on the stack depth type. + * E.g. on a 32 bit machine, a value of 200 means 800 bytes. + * @return Smallest value of stack remaining since the task was started in + * words. + */ + static size_t getTaskStackHighWatermark( + TaskHandle_t task = nullptr); +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */ From 6b4fa0cc0443802d2d51db18dc32a800578afd65 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 8 Aug 2020 13:28:59 +0200 Subject: [PATCH 216/653] fdir update --- .../DeviceHandlerFailureIsolation.cpp | 38 +++++++++++-------- .../DeviceHandlerFailureIsolation.h | 2 + fdir/FailureIsolationBase.cpp | 35 +++++++++++------ fdir/FailureIsolationBase.h | 17 ++++++--- 4 files changed, 60 insertions(+), 32 deletions(-) diff --git a/devicehandlers/DeviceHandlerFailureIsolation.cpp b/devicehandlers/DeviceHandlerFailureIsolation.cpp index 65c40219..46e73cd8 100644 --- a/devicehandlers/DeviceHandlerFailureIsolation.cpp +++ b/devicehandlers/DeviceHandlerFailureIsolation.cpp @@ -7,13 +7,15 @@ 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, - REBOOT_TIME_MS, parameterDomainBase++), fdirState(NONE), powerConfirmation( - 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, REBOOT_TIME_MS, parameterDomainBase++), + fdirState(NONE), powerConfirmation(0) { } DeviceHandlerFailureIsolation::~DeviceHandlerFailureIsolation() { @@ -68,9 +70,11 @@ ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event) break; //****Power***** case PowerSwitchIF::SWITCH_WENT_OFF: - result = sendConfirmationRequest(event, powerConfirmation); - if (result == RETURN_OK) { - setFdirState(DEVICE_MIGHT_BE_OFF); + if(hasPowerConfirmation) { + result = sendConfirmationRequest(event, powerConfirmation); + if (result == RETURN_OK) { + setFdirState(DEVICE_MIGHT_BE_OFF); + } } break; case Fuse::FUSE_WENT_OFF: @@ -133,7 +137,7 @@ void DeviceHandlerFailureIsolation::decrementFaultCounters() { void DeviceHandlerFailureIsolation::handleRecovery(Event reason) { clearFaultCounters(); - if (!recoveryCounter.incrementAndCheck()) { + if (not recoveryCounter.incrementAndCheck()) { startRecovery(reason); } else { setFaulty(reason); @@ -142,7 +146,8 @@ void DeviceHandlerFailureIsolation::handleRecovery(Event reason) { 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? + //This means, no fault message will come through until a MODE_ or + //HEALTH_INFO message comes through -> Is that ok? //Same issue in TxFailureIsolation! // if ((event->getEvent() == PowerSwitchIF::SWITCH_WENT_OFF) // && (fdirState != RECOVERY_ONGOING)) { @@ -158,14 +163,17 @@ void DeviceHandlerFailureIsolation::clearFaultCounters() { ReturnValue_t DeviceHandlerFailureIsolation::initialize() { ReturnValue_t result = FailureIsolationBase::initialize(); if (result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "DeviceHandlerFailureIsolation::initialize: Could not" + " initialize FailureIsolationBase." << std::endl; return result; } ConfirmsFailuresIF* power = objectManager->get( powerConfirmationId); - if (power == NULL) { - return RETURN_FAILED; + if (power != nullptr) { + powerConfirmation = power->getEventReceptionQueue(); + hasPowerConfirmation = true; } - powerConfirmation = power->getEventReceptionQueue(); + return RETURN_OK; } diff --git a/devicehandlers/DeviceHandlerFailureIsolation.h b/devicehandlers/DeviceHandlerFailureIsolation.h index 91f6ef64..4343d88b 100644 --- a/devicehandlers/DeviceHandlerFailureIsolation.h +++ b/devicehandlers/DeviceHandlerFailureIsolation.h @@ -28,8 +28,10 @@ protected: NONE, RECOVERY_ONGOING, DEVICE_MIGHT_BE_OFF, AWAIT_SHUTDOWN }; FDIRState fdirState; + bool hasPowerConfirmation = false; MessageQueueId_t powerConfirmation; static object_id_t powerConfirmationId; + // TODO: Are those hardcoded value? How can they be changed. static const uint32_t MAX_REBOOT = 1; static const uint32_t REBOOT_TIME_MS = 180000; static const uint32_t MAX_STRANGE_REPLIES = 10; diff --git a/fdir/FailureIsolationBase.cpp b/fdir/FailureIsolationBase.cpp index 4b7caac5..ad4493ff 100644 --- a/fdir/FailureIsolationBase.cpp +++ b/fdir/FailureIsolationBase.cpp @@ -5,10 +5,12 @@ #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) { - eventQueue = QueueFactory::instance()->createMessageQueue(messageDepth, EventMessage::EVENT_MESSAGE_SIZE); +FailureIsolationBase::FailureIsolationBase(object_id_t owner, + object_id_t parent, uint8_t messageDepth, uint8_t parameterDomainBase) : + ownerId(owner), faultTreeParent(parent), + parameterDomainBase(parameterDomainBase) { + eventQueue = QueueFactory::instance()->createMessageQueue(messageDepth, + EventMessage::EVENT_MESSAGE_SIZE); } FailureIsolationBase::~FailureIsolationBase() { @@ -18,27 +20,36 @@ FailureIsolationBase::~FailureIsolationBase() { ReturnValue_t FailureIsolationBase::initialize() { EventManagerIF* manager = objectManager->get( objects::EVENT_MANAGER); - if (manager == NULL) { + if (manager == nullptr) { + sif::error << "FailureIsolationBase::initialize: Event Manager has not" + " been initialized!" << std::endl; return RETURN_FAILED; } ReturnValue_t result = manager->registerListener(eventQueue->getId()); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - if (ownerId != 0) { + if (ownerId != objects::NO_OBJECT) { result = manager->subscribeToAllEventsFrom(eventQueue->getId(), ownerId); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } owner = objectManager->get(ownerId); - if (owner == NULL) { - return RETURN_FAILED; + if (owner == nullptr) { + sif::error << "FailureIsolationBase::intialize: Owner object " + "invalid. Make sure it implements HasHealthIF" << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; } } - if (faultTreeParent != 0) { + if (faultTreeParent != objects::NO_OBJECT) { ConfirmsFailuresIF* parentIF = objectManager->get( faultTreeParent); - if (parentIF == NULL) { + if (parentIF == nullptr) { + sif::error << "FailureIsolationBase::intialize: Parent object" + << "invalid." << std::endl; + sif::error << "Make sure it implements ConfirmsFailuresIF." + << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; return RETURN_FAILED; } eventQueue->setDefaultDestination(parentIF->getEventReceptionQueue()); @@ -93,9 +104,9 @@ MessageQueueId_t FailureIsolationBase::getEventReceptionQueue() { ReturnValue_t FailureIsolationBase::sendConfirmationRequest(EventMessage* event, MessageQueueId_t destination) { event->setMessageId(EventMessage::CONFIRMATION_REQUEST); - if (destination != 0) { + if (destination != MessageQueueIF::NO_QUEUE) { return eventQueue->sendMessage(destination, event); - } else if (faultTreeParent != 0) { + } else if (faultTreeParent != objects::NO_OBJECT) { return eventQueue->sendToDefault(event); } return RETURN_FAILED; diff --git a/fdir/FailureIsolationBase.h b/fdir/FailureIsolationBase.h index cd582e39..c0fe6041 100644 --- a/fdir/FailureIsolationBase.h +++ b/fdir/FailureIsolationBase.h @@ -17,18 +17,25 @@ public: static const Event FDIR_CHANGED_STATE = MAKE_EVENT(1, SEVERITY::INFO); //!< FDIR has an internal state, which changed from par2 (oldState) to par1 (newState). static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(2, SEVERITY::MEDIUM); //!< FDIR tries to restart device. Par1: event that caused recovery. static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(3, SEVERITY::MEDIUM); //!< FDIR turns off device. Par1: event that caused recovery. - FailureIsolationBase(object_id_t owner, object_id_t parent = 0, + + FailureIsolationBase(object_id_t owner, + object_id_t parent = objects::NO_OBJECT, 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(); + MessageQueueId_t getEventReceptionQueue() override; virtual void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0); protected: - MessageQueueIF* eventQueue; + MessageQueueIF* eventQueue = nullptr; object_id_t ownerId; - HasHealthIF* owner; + HasHealthIF* owner = nullptr; object_id_t faultTreeParent; uint8_t parameterDomainBase; void setOwnerHealth(HasHealthIF::HealthState health); @@ -38,7 +45,7 @@ protected: virtual ReturnValue_t confirmFault(EventMessage* event); virtual void decrementFaultCounters() = 0; ReturnValue_t sendConfirmationRequest(EventMessage* event, - MessageQueueId_t destination = 0); + MessageQueueId_t destination = MessageQueueIF::NO_QUEUE); void throwFdirEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0); private: From 8c722feafb18f15e5e1db3ddde65ae66a3b09dad Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 11 Aug 2020 16:21:59 +0200 Subject: [PATCH 217/653] Fixes #47 and #36 --- container/ArrayList.h | 8 ++- container/FixedMap.h | 23 ++++----- container/FixedOrderedMultimap.h | 13 +---- subsystem/Subsystem.cpp | 4 +- tmtcservices/CommandingServiceBase.cpp | 70 +++++++++++++------------- 5 files changed, 54 insertions(+), 64 deletions(-) diff --git a/container/ArrayList.h b/container/ArrayList.h index 9c4c4ceb..0a2f460b 100644 --- a/container/ArrayList.h +++ b/container/ArrayList.h @@ -72,11 +72,15 @@ public: return tmp; } - T operator*() { + T& operator*(){ return *value; } - T *operator->() { + const T& operator*() const{ + return *value; + } + + T *operator->(){ return value; } diff --git a/container/FixedMap.h b/container/FixedMap.h index ac170bd2..0823b670 100644 --- a/container/FixedMap.h +++ b/container/FixedMap.h @@ -1,5 +1,5 @@ -#ifndef FIXEDMAP_H_ -#define FIXEDMAP_H_ +#ifndef FRAMEWORK_CONTAINER_FIXEDMAP_H_ +#define FRAMEWORK_CONTAINER_FIXEDMAP_H_ #include #include @@ -7,6 +7,10 @@ /** * \ingroup container + * + * + * \warning Iterators return a non-const key_t in the pair. + * \warning A User is not allowed to change the key, otherwise the map is corrupted. */ template class FixedMap: public SerializeIF { @@ -47,15 +51,6 @@ public: Iterator(std::pair *pair) : ArrayList, uint32_t>::Iterator(pair) { } - - T operator*() { - return ArrayList, uint32_t>::Iterator::value->second; - } - - T *operator->() { - return &ArrayList, uint32_t>::Iterator::value->second; - } - }; Iterator begin() const { @@ -70,7 +65,7 @@ public: return _size; } - ReturnValue_t insert(key_t key, T value, Iterator *storedValue = NULL) { + ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) { if (exists(key) == HasReturnvaluesIF::RETURN_OK) { return KEY_ALREADY_EXISTS; } @@ -79,7 +74,7 @@ public: } theMap[_size].first = key; theMap[_size].second = value; - if (storedValue != NULL) { + if (storedValue != nullptr) { *storedValue = Iterator(&theMap[_size]); } ++_size; @@ -87,7 +82,7 @@ public: } ReturnValue_t insert(std::pair pair) { - return insert(pair.fist, pair.second); + return insert(pair.first, pair.second); } ReturnValue_t exists(key_t key) const { diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 21629664..4f81c97c 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -68,15 +68,6 @@ public: Iterator(std::pair *pair) : ArrayList, uint32_t>::Iterator(pair) { } - - T operator*() { - return ArrayList, uint32_t>::Iterator::value->second; - } - - T *operator->() { - return &ArrayList, uint32_t>::Iterator::value->second; - } - }; Iterator begin() const { @@ -91,7 +82,7 @@ public: return _size; } - ReturnValue_t insert(key_t key, T value, Iterator *storedValue = NULL) { + ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) { if (_size == theMap.maxSize()) { return MAP_FULL; } @@ -101,7 +92,7 @@ public: theMap[position].first = key; theMap[position].second = value; ++_size; - if (storedValue != NULL) { + if (storedValue != nullptr) { *storedValue = Iterator(&theMap[position]); } return HasReturnvaluesIF::RETURN_OK; diff --git a/subsystem/Subsystem.cpp b/subsystem/Subsystem.cpp index fcf2e189..094e79b4 100644 --- a/subsystem/Subsystem.cpp +++ b/subsystem/Subsystem.cpp @@ -549,7 +549,7 @@ Mode_t Subsystem::getFallbackSequence(Mode_t sequence) { for (FixedMap::Iterator iter = modeSequences.begin(); iter != modeSequences.end(); ++iter) { if (iter.value->first == sequence) { - return iter->fallbackSequence; + return iter->second.fallbackSequence; } } return -1; @@ -558,7 +558,7 @@ Mode_t Subsystem::getFallbackSequence(Mode_t sequence) { bool Subsystem::isFallbackSequence(Mode_t SequenceId) { for (FixedMap::Iterator iter = modeSequences.begin(); iter != modeSequences.end(); iter++) { - if (iter->fallbackSequence == SequenceId) { + if (iter->second.fallbackSequence == SequenceId) { return true; } } diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index 331bc7c8..b08e315d 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -104,8 +104,8 @@ void CommandingServiceBase::handleCommandMessage(CommandMessage* reply) { // Implemented by child class, specifies what to do with reply. - ReturnValue_t result = handleReply(reply, iter->command, &iter->state, - &nextCommand, iter->objectId, &isStep); + ReturnValue_t result = handleReply(reply, iter->second.command, &iter->second.state, + &nextCommand, iter->second.objectId, &isStep); /* If the child implementation does not implement special handling for * rejected replies (RETURN_FAILED is returned), a failure verification @@ -114,7 +114,7 @@ void CommandingServiceBase::handleCommandMessage(CommandMessage* reply) { if(reply->getCommand() == CommandMessage::REPLY_REJECTED and result == RETURN_FAILED) { result = reply->getReplyRejectedReason(); - failureParameter1 = iter->command; + failureParameter1 = iter->second.command; } switch (result) { @@ -131,14 +131,14 @@ void CommandingServiceBase::handleCommandMessage(CommandMessage* reply) { default: if (isStep) { verificationReporter.sendFailureReport( - TC_VERIFY::PROGRESS_FAILURE, iter->tcInfo.ackFlags, - iter->tcInfo.tcPacketId, iter->tcInfo.tcSequenceControl, - result, ++iter->step, failureParameter1, + TC_VERIFY::PROGRESS_FAILURE, iter->second.tcInfo.ackFlags, + iter->second.tcInfo.tcPacketId, iter->second.tcInfo.tcSequenceControl, + result, ++iter->second.step, failureParameter1, failureParameter2); } else { verificationReporter.sendFailureReport( - TC_VERIFY::COMPLETION_FAILURE, iter->tcInfo.ackFlags, - iter->tcInfo.tcPacketId, iter->tcInfo.tcSequenceControl, + TC_VERIFY::COMPLETION_FAILURE, iter->second.tcInfo.ackFlags, + iter->second.tcInfo.tcPacketId, iter->second.tcInfo.tcSequenceControl, result, 0, failureParameter1, failureParameter2); } failureParameter1 = 0; @@ -152,7 +152,7 @@ void CommandingServiceBase::handleCommandMessage(CommandMessage* reply) { void CommandingServiceBase::handleReplyHandlerResult(ReturnValue_t result, CommandMapIter iter, CommandMessage* nextCommand, CommandMessage* reply, bool& isStep) { - iter->command = nextCommand->getCommand(); + iter->second.command = nextCommand->getCommand(); // In case a new command is to be sent immediately, this is performed here. // If no new command is sent, only analyse reply result by initializing @@ -167,14 +167,14 @@ void CommandingServiceBase::handleReplyHandlerResult(ReturnValue_t result, if (isStep and result != NO_STEP_MESSAGE) { verificationReporter.sendSuccessReport( TC_VERIFY::PROGRESS_SUCCESS, - iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, - iter->tcInfo.tcSequenceControl, ++iter->step); + iter->second.tcInfo.ackFlags, iter->second.tcInfo.tcPacketId, + iter->second.tcInfo.tcSequenceControl, ++iter->second.step); } else { verificationReporter.sendSuccessReport( TC_VERIFY::COMPLETION_SUCCESS, - iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, - iter->tcInfo.tcSequenceControl, 0); + iter->second.tcInfo.ackFlags, iter->second.tcInfo.tcPacketId, + iter->second.tcInfo.tcSequenceControl, 0); checkAndExecuteFifo(iter); } } @@ -182,16 +182,16 @@ void CommandingServiceBase::handleReplyHandlerResult(ReturnValue_t result, if (isStep) { nextCommand->clearCommandMessage(); verificationReporter.sendFailureReport( - TC_VERIFY::PROGRESS_FAILURE, iter->tcInfo.ackFlags, - iter->tcInfo.tcPacketId, - iter->tcInfo.tcSequenceControl, sendResult, - ++iter->step, failureParameter1, failureParameter2); + TC_VERIFY::PROGRESS_FAILURE, iter->second.tcInfo.ackFlags, + iter->second.tcInfo.tcPacketId, + iter->second.tcInfo.tcSequenceControl, sendResult, + ++iter->second.step, failureParameter1, failureParameter2); } else { nextCommand->clearCommandMessage(); verificationReporter.sendFailureReport( TC_VERIFY::COMPLETION_FAILURE, - iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, - iter->tcInfo.tcSequenceControl, sendResult, 0, + iter->second.tcInfo.ackFlags, iter->second.tcInfo.tcPacketId, + iter->second.tcInfo.tcSequenceControl, sendResult, 0, failureParameter1, failureParameter2); } failureParameter1 = 0; @@ -230,7 +230,7 @@ void CommandingServiceBase::handleRequestQueue() { iter = commandMap.find(queue); if (iter != commandMap.end()) { - result = iter->fifo.insert(address); + result = iter->second.fifo.insert(address); if (result != RETURN_OK) { rejectPacket(TC_VERIFY::START_FAILURE, &packet, OBJECT_BUSY); } @@ -298,11 +298,11 @@ void CommandingServiceBase::startExecution(TcPacketStored *storedPacket, CommandMapIter iter) { ReturnValue_t result = RETURN_OK; CommandMessage command; - iter->subservice = storedPacket->getSubService(); - result = prepareCommand(&command, iter->subservice, + iter->second.subservice = storedPacket->getSubService(); + result = prepareCommand(&command, iter->second.subservice, storedPacket->getApplicationData(), - storedPacket->getApplicationDataSize(), &iter->state, - iter->objectId); + storedPacket->getApplicationDataSize(), &iter->second.state, + iter->second.objectId); ReturnValue_t sendResult = RETURN_OK; switch (result) { @@ -312,13 +312,13 @@ void CommandingServiceBase::startExecution(TcPacketStored *storedPacket, &command); } if (sendResult == RETURN_OK) { - Clock::getUptime(&iter->uptimeOfStart); - iter->step = 0; - iter->subservice = storedPacket->getSubService(); - iter->command = command.getCommand(); - iter->tcInfo.ackFlags = storedPacket->getAcknowledgeFlags(); - iter->tcInfo.tcPacketId = storedPacket->getPacketId(); - iter->tcInfo.tcSequenceControl = + Clock::getUptime(&iter->second.uptimeOfStart); + iter->second.step = 0; + iter->second.subservice = storedPacket->getSubService(); + iter->second.command = command.getCommand(); + iter->second.tcInfo.ackFlags = storedPacket->getAcknowledgeFlags(); + iter->second.tcInfo.tcPacketId = storedPacket->getPacketId(); + iter->second.tcInfo.tcSequenceControl = storedPacket->getPacketSequenceControl(); acceptPacket(TC_VERIFY::START_SUCCESS, storedPacket); } else { @@ -368,7 +368,7 @@ void CommandingServiceBase::acceptPacket(uint8_t reportId, void CommandingServiceBase::checkAndExecuteFifo(CommandMapIter iter) { store_address_t address; - if (iter->fifo.retrieve(&address) != RETURN_OK) { + if (iter->second.fifo.retrieve(&address) != RETURN_OK) { commandMap.erase(&iter); } else { TcPacketStored newPacket(address); @@ -394,10 +394,10 @@ void CommandingServiceBase::checkTimeout() { Clock::getUptime(&uptime); CommandMapIter iter; for (iter = commandMap.begin(); iter != commandMap.end(); ++iter) { - if ((iter->uptimeOfStart + (timeoutSeconds * 1000)) < uptime) { + if ((iter->second.uptimeOfStart + (timeoutSeconds * 1000)) < uptime) { verificationReporter.sendFailureReport( - TC_VERIFY::COMPLETION_FAILURE, iter->tcInfo.ackFlags, - iter->tcInfo.tcPacketId, iter->tcInfo.tcSequenceControl, + TC_VERIFY::COMPLETION_FAILURE, iter->second.tcInfo.ackFlags, + iter->second.tcInfo.tcPacketId, iter->second.tcInfo.tcSequenceControl, TIMEOUT); checkAndExecuteFifo(iter); } From e963aca02a343a8afa46e5ef0103307b1b87248d Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 11 Aug 2020 17:02:19 +0200 Subject: [PATCH 218/653] Fixed an issue with memmove in FixedOrderedMultimap --- container/FixedOrderedMultimap.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 4f81c97c..4ddc5dcb 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -48,7 +48,7 @@ private: if (_size <= position) { return; } - memmove(&theMap[position], &theMap[position + 1], + memmove(static_cast(&theMap[position]), static_cast(&theMap[position + 1]), (_size - position - 1) * sizeof(std::pair)); --_size; } @@ -87,7 +87,7 @@ public: return MAP_FULL; } uint32_t position = findNicePlace(key); - memmove(&theMap[position + 1], &theMap[position], + memmove(static_cast(&theMap[position + 1]),static_cast(&theMap[position]), (_size - position) * sizeof(std::pair)); theMap[position].first = key; theMap[position].second = value; From 3d4daa51d537b0e957644103293b8dbadb773018 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 11 Aug 2020 17:17:50 +0200 Subject: [PATCH 219/653] Corrected warning to fit name of setting --- framework.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework.mk b/framework.mk index ee0a7ba4..643eb74f 100644 --- a/framework.mk +++ b/framework.mk @@ -34,7 +34,7 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/FreeRTOS/*.cpp) else ifeq ($(OS_FSFW),host) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/host/*.cpp) else -$(error invalid OS specified, valid OS are rtems, linux, freeRTOS, host) +$(error invalid OS_FSFW specified, valid OS_FSFW are rtems, linux, freeRTOS, host) endif CXXSRC += $(wildcard $(FRAMEWORK_PATH)/parameters/*.cpp) From b484e4d5ad7325597fa42905fdb984ec145a475e Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 13 Aug 2020 10:27:16 +0200 Subject: [PATCH 220/653] Removed unused function --- container/FixedOrderedMultimap.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 4ddc5dcb..872425e6 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -136,12 +136,6 @@ public: return HasReturnvaluesIF::RETURN_OK; } - //This is potentially unsafe -// T *findValue(key_t key) const { -// return &theMap[findFirstIndex(key)].second; -// } - - Iterator find(key_t key) const { ReturnValue_t result = exists(key); if (result != HasReturnvaluesIF::RETURN_OK) { From 4a2ef6d97f51418864856c53ac596652aa002bb9 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 13 Aug 2020 17:58:42 +0200 Subject: [PATCH 221/653] Fixed a shadowing issue of with moving to inner scope --- subsystem/Subsystem.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/subsystem/Subsystem.cpp b/subsystem/Subsystem.cpp index fcf2e189..2f0cb04e 100644 --- a/subsystem/Subsystem.cpp +++ b/subsystem/Subsystem.cpp @@ -151,7 +151,6 @@ HybridIterator Subsystem::getTable(Mode_t id) { } ReturnValue_t Subsystem::handleCommandMessage(CommandMessage *message) { - ReturnValue_t result; switch (message->getCommand()) { case HealthMessage::HEALTH_INFO: { HealthState health = HealthMessage::getHealth(message); @@ -166,7 +165,7 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage *message) { FixedArrayList sequence; const uint8_t *pointer; size_t sizeRead; - result = IPCStore->getData( + ReturnValue_t result = IPCStore->getData( ModeSequenceMessage::getStoreAddress(message), &pointer, &sizeRead); if (result == RETURN_OK) { @@ -193,7 +192,7 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage *message) { FixedArrayList table; const uint8_t *pointer; size_t sizeRead; - result = IPCStore->getData( + ReturnValue_t result = IPCStore->getData( ModeSequenceMessage::getStoreAddress(message), &pointer, &sizeRead); if (result == RETURN_OK) { @@ -210,21 +209,23 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage *message) { } break; - case ModeSequenceMessage::DELETE_SEQUENCE: + case ModeSequenceMessage::DELETE_SEQUENCE:{ if (isInTransition) { replyToCommand(IN_TRANSITION, 0); break; } - result = deleteSequence(ModeSequenceMessage::getSequenceId(message)); + ReturnValue_t result = deleteSequence(ModeSequenceMessage::getSequenceId(message)); replyToCommand(result, 0); + } break; - case ModeSequenceMessage::DELETE_TABLE: + case ModeSequenceMessage::DELETE_TABLE:{ if (isInTransition) { replyToCommand(IN_TRANSITION, 0); break; } - result = deleteTable(ModeSequenceMessage::getTableId(message)); + ReturnValue_t result = deleteTable(ModeSequenceMessage::getTableId(message)); replyToCommand(result, 0); + } break; case ModeSequenceMessage::LIST_SEQUENCES: { SerialFixedArrayListAdapter sequences; From 3d89bc83e5a872a781fd6e1b1af6b39b20e06ddc Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 13 Aug 2020 18:08:17 +0200 Subject: [PATCH 222/653] Another shadowing, altough again no problem --- timemanager/CCSDSTime.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/timemanager/CCSDSTime.cpp b/timemanager/CCSDSTime.cpp index 71b2539d..cdb14d9a 100644 --- a/timemanager/CCSDSTime.cpp +++ b/timemanager/CCSDSTime.cpp @@ -119,7 +119,7 @@ ReturnValue_t CCSDSTime::convertFromCCS(Clock::TimeOfDay_t* to, const uint8_t* f if (temp->pField & (1 << 3)) { //day of year variation uint16_t tempDay = (temp->month << 8) + temp->day; - ReturnValue_t result = convertDaysOfYear(tempDay, to->year, + result = convertDaysOfYear(tempDay, to->year, &(temp->month), &(temp->day)); if (result != RETURN_OK) { return result; From 287a83c54c54da467b339fbb32fda52ce8946a67 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 13 Aug 2020 19:11:23 +0200 Subject: [PATCH 223/653] Another shadowing error --- objectmanager/ObjectManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/objectmanager/ObjectManager.cpp b/objectmanager/ObjectManager.cpp index 1c54355a..71769d68 100644 --- a/objectmanager/ObjectManager.cpp +++ b/objectmanager/ObjectManager.cpp @@ -100,7 +100,6 @@ void ObjectManager::initialize() { } void ObjectManager::printList() { - std::map::iterator it; sif::debug << "ObjectManager: Object List contains:" << std::endl; for (auto const& it : objectList) { sif::debug << std::hex << it.first << " | " << it.second << std::endl; From d5dedce294d02e2afe44331f455cd65eee00197a Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 13 Aug 2020 20:53:35 +0200 Subject: [PATCH 224/653] Relative Paths --- action/ActionHelper.cpp | 6 +- action/ActionHelper.h | 6 +- action/ActionMessage.cpp | 6 +- action/ActionMessage.h | 6 +- action/CommandActionHelper.cpp | 10 +- action/CommandActionHelper.h | 12 +- action/CommandsActionsIF.h | 6 +- action/HasActionsIF.h | 10 +- action/SimpleActionHelper.cpp | 4 +- action/SimpleActionHelper.h | 2 +- container/ArrayList.h | 6 +- container/FIFO.h | 2 +- container/FixedArrayList.h | 2 +- container/FixedMap.h | 4 +- container/FixedOrderedMultimap.h | 2 +- container/HybridIterator.h | 4 +- container/IndexedRingMemoryArray.h | 10 +- container/PlacementFactory.h | 2 +- container/RingBufferBase.h | 2 +- container/SimpleRingBuffer.cpp | 2 +- container/SimpleRingBuffer.h | 2 +- controller/ControllerBase.cpp | 10 +- controller/ControllerBase.h | 14 +- coordinates/CoordinateTransformations.cpp | 8 +- coordinates/CoordinateTransformations.h | 2 +- coordinates/Jgm3Model.h | 8 +- coordinates/Sgp4Propagator.cpp | 12 +- coordinates/Sgp4Propagator.h | 2 +- datalinklayer/BCFrame.h | 2 +- datalinklayer/CCSDSReturnValuesIF.h | 2 +- datalinklayer/Clcw.cpp | 4 +- datalinklayer/Clcw.h | 2 +- datalinklayer/DataLinkLayer.cpp | 6 +- datalinklayer/DataLinkLayer.h | 10 +- datalinklayer/Farm1StateIF.h | 2 +- datalinklayer/Farm1StateLockout.cpp | 8 +- datalinklayer/Farm1StateLockout.h | 2 +- datalinklayer/Farm1StateOpen.cpp | 8 +- datalinklayer/Farm1StateOpen.h | 2 +- datalinklayer/Farm1StateWait.cpp | 8 +- datalinklayer/Farm1StateWait.h | 2 +- datalinklayer/MapPacketExtraction.cpp | 14 +- datalinklayer/MapPacketExtraction.h | 8 +- datalinklayer/MapPacketExtractionIF.h | 4 +- datalinklayer/TcTransferFrame.cpp | 4 +- datalinklayer/TcTransferFrameLocal.cpp | 6 +- datalinklayer/TcTransferFrameLocal.h | 2 +- datalinklayer/VirtualChannelReception.cpp | 6 +- datalinklayer/VirtualChannelReception.h | 16 +- datalinklayer/VirtualChannelReceptionIF.h | 6 +- datapool/ControllerSet.cpp | 2 +- datapool/ControllerSet.h | 2 +- datapool/DataPool.cpp | 6 +- datapool/DataPool.h | 6 +- datapool/DataPoolAdmin.cpp | 14 +- datapool/DataPoolAdmin.h | 18 +- datapool/DataPoolParameterWrapper.cpp | 6 +- datapool/DataPoolParameterWrapper.h | 4 +- datapool/DataSet.cpp | 4 +- datapool/DataSet.h | 14 +- datapool/HkSwitchHelper.cpp | 4 +- datapool/HkSwitchHelper.h | 6 +- datapool/PIDReader.h | 12 +- datapool/PIDReaderList.h | 4 +- datapool/PoolEntry.cpp | 6 +- datapool/PoolEntry.h | 2 +- datapool/PoolEntryIF.h | 2 +- datapool/PoolRawAccess.cpp | 10 +- datapool/PoolRawAccess.h | 4 +- datapool/PoolVarList.h | 4 +- datapool/PoolVariable.h | 10 +- datapool/PoolVariableIF.h | 4 +- datapool/PoolVector.h | 10 +- devicehandlers/AcceptsDeviceResponsesIF.h | 2 +- devicehandlers/AssemblyBase.cpp | 2 +- devicehandlers/AssemblyBase.h | 6 +- devicehandlers/ChildHandlerBase.cpp | 6 +- devicehandlers/ChildHandlerBase.h | 4 +- devicehandlers/ChildHandlerFDIR.cpp | 2 +- devicehandlers/ChildHandlerFDIR.h | 2 +- devicehandlers/DeviceCommunicationIF.h | 4 +- devicehandlers/DeviceHandlerBase.cpp | 24 +- devicehandlers/DeviceHandlerBase.h | 30 +- .../DeviceHandlerFailureIsolation.cpp | 12 +- .../DeviceHandlerFailureIsolation.h | 4 +- devicehandlers/DeviceHandlerIF.h | 10 +- devicehandlers/DeviceHandlerMessage.cpp | 6 +- devicehandlers/DeviceHandlerMessage.h | 8 +- devicehandlers/DeviceTmReportingWrapper.cpp | 6 +- devicehandlers/DeviceTmReportingWrapper.h | 6 +- devicehandlers/FixedSequenceSlot.cpp | 4 +- devicehandlers/FixedSequenceSlot.h | 4 +- devicehandlers/FixedSlotSequence.cpp | 4 +- devicehandlers/FixedSlotSequence.h | 4 +- devicehandlers/HealthDevice.cpp | 4 +- devicehandlers/HealthDevice.h | 10 +- events/Event.cpp | 2 +- events/Event.h | 2 +- events/EventManager.cpp | 10 +- events/EventManager.h | 14 +- events/EventManagerIF.h | 8 +- events/EventMessage.cpp | 2 +- events/EventMessage.h | 6 +- events/EventReportingProxyIF.h | 2 +- events/eventmatching/EventIdRangeMatcher.cpp | 2 +- events/eventmatching/EventIdRangeMatcher.h | 2 +- events/eventmatching/EventMatchTree.cpp | 8 +- events/eventmatching/EventMatchTree.h | 8 +- events/eventmatching/EventRangeMatcherBase.h | 6 +- events/eventmatching/ReporterRangeMatcher.cpp | 2 +- events/eventmatching/ReporterRangeMatcher.h | 2 +- events/eventmatching/SeverityRangeMatcher.cpp | 6 +- events/eventmatching/SeverityRangeMatcher.h | 2 +- events/eventmatching/eventmatching.h | 8 +- fdir/ConfirmsFailuresIF.h | 4 +- fdir/EventCorrelation.cpp | 2 +- fdir/EventCorrelation.h | 2 +- fdir/FailureIsolationBase.cpp | 12 +- fdir/FailureIsolationBase.h | 14 +- fdir/FaultCounter.cpp | 2 +- fdir/FaultCounter.h | 4 +- globalfunctions/AsciiConverter.cpp | 2 +- globalfunctions/AsciiConverter.h | 2 +- globalfunctions/CRC.cpp | 2 +- globalfunctions/DleEncoder.cpp | 2 +- globalfunctions/DleEncoder.h | 2 +- globalfunctions/Type.cpp | 6 +- globalfunctions/Type.h | 4 +- globalfunctions/arrayprinter.cpp | 4 +- globalfunctions/matching/BinaryMatcher.h | 2 +- globalfunctions/matching/DecimalMatcher.h | 2 +- globalfunctions/matching/MatchTree.h | 6 +- globalfunctions/matching/RangeMatcher.h | 4 +- .../matching/SerializeableMatcherIF.h | 4 +- globalfunctions/math/QuaternionOperations.cpp | 2 +- globalfunctions/timevalOperations.cpp | 2 +- health/HasHealthIF.h | 6 +- health/HealthHelper.cpp | 6 +- health/HealthHelper.h | 14 +- health/HealthMessage.cpp | 2 +- health/HealthMessage.h | 4 +- health/HealthTable.cpp | 6 +- health/HealthTable.h | 6 +- health/HealthTableIF.h | 6 +- health/ManagesHealthIF.h | 4 +- internalError/InternalErrorReporter.cpp | 8 +- internalError/InternalErrorReporter.h | 6 +- ipc/CommandMessage.cpp | 18 +- ipc/CommandMessage.h | 4 +- ipc/MessageQueueIF.h | 6 +- ipc/MessageQueueMessage.cpp | 4 +- ipc/MessageQueueMessage.h | 2 +- ipc/MessageQueueSenderIF.h | 2 +- ipc/MutexFactory.h | 2 +- ipc/MutexHelper.h | 4 +- ipc/MutexIF.h | 2 +- ipc/QueueFactory.h | 2 +- memory/AcceptsMemoryMessagesIF.h | 6 +- memory/HasMemoryIF.h | 2 +- memory/MemoryHelper.cpp | 12 +- memory/MemoryHelper.h | 10 +- memory/MemoryMessage.cpp | 4 +- memory/MemoryMessage.h | 4 +- memory/MemoryProxyIF.h | 2 +- modes/HasModesIF.h | 8 +- modes/ModeHelper.cpp | 6 +- modes/ModeHelper.h | 6 +- modes/ModeMessage.cpp | 2 +- modes/ModeMessage.h | 2 +- monitoring/AbsLimitMonitor.h | 2 +- monitoring/HasMonitorsIF.h | 6 +- monitoring/LimitMonitor.h | 2 +- monitoring/LimitViolationReporter.cpp | 10 +- monitoring/LimitViolationReporter.h | 8 +- monitoring/MonitorBase.h | 12 +- monitoring/MonitorReporter.h | 10 +- monitoring/MonitoringIF.h | 6 +- monitoring/MonitoringMessage.cpp | 4 +- monitoring/MonitoringMessage.h | 4 +- monitoring/MonitoringMessageContent.h | 18 +- monitoring/ReceivesMonitoringReportsIF.h | 2 +- monitoring/TriplexMonitor.h | 10 +- monitoring/TwoValueLimitMonitor.h | 2 +- objectmanager/ObjectManager.cpp | 4 +- objectmanager/ObjectManager.h | 4 +- objectmanager/ObjectManagerIF.h | 8 +- objectmanager/SystemObject.cpp | 6 +- objectmanager/SystemObject.h | 8 +- objectmanager/SystemObjectIF.h | 4 +- osal/FreeRTOS/Clock.cpp | 6 +- osal/FreeRTOS/FixedTimeslotTask.cpp | 2 +- osal/FreeRTOS/FixedTimeslotTask.h | 6 +- osal/FreeRTOS/MessageQueue.cpp | 2 +- osal/FreeRTOS/MessageQueue.h | 6 +- osal/FreeRTOS/Mutex.cpp | 2 +- osal/FreeRTOS/Mutex.h | 2 +- osal/FreeRTOS/MutexFactory.cpp | 2 +- osal/FreeRTOS/PeriodicTask.cpp | 4 +- osal/FreeRTOS/PeriodicTask.h | 6 +- osal/FreeRTOS/QueueFactory.cpp | 4 +- osal/FreeRTOS/TaskFactory.cpp | 4 +- osal/FreeRTOS/Timekeeper.cpp | 2 +- osal/FreeRTOS/Timekeeper.h | 2 +- osal/InternalErrorCodes.h | 2 +- osal/linux/Clock.cpp | 4 +- osal/linux/FixedTimeslotTask.cpp | 4 +- osal/linux/FixedTimeslotTask.h | 6 +- osal/linux/InternalErrorCodes.cpp | 2 +- osal/linux/MessageQueue.cpp | 4 +- osal/linux/MessageQueue.h | 6 +- osal/linux/Mutex.cpp | 6 +- osal/linux/Mutex.h | 2 +- osal/linux/MutexFactory.cpp | 4 +- osal/linux/PeriodicPosixTask.cpp | 6 +- osal/linux/PeriodicPosixTask.h | 8 +- osal/linux/PosixThread.cpp | 4 +- osal/linux/PosixThread.h | 2 +- osal/linux/QueueFactory.cpp | 6 +- osal/linux/TaskFactory.cpp | 8 +- osal/linux/Timer.cpp | 4 +- osal/rtems/Clock.cpp | 2 +- osal/rtems/CpuUsage.cpp | 4 +- osal/rtems/CpuUsage.h | 4 +- osal/rtems/InternalErrorCodes.cpp | 2 +- osal/rtems/Interrupt.h | 2 +- osal/rtems/MessageQueue.cpp | 2 +- osal/rtems/MessageQueue.h | 6 +- osal/rtems/MultiObjectTask.cpp | 4 +- osal/rtems/MultiObjectTask.h | 4 +- osal/rtems/Mutex.cpp | 2 +- osal/rtems/Mutex.h | 2 +- osal/rtems/MutexFactory.cpp | 2 +- osal/rtems/PollingTask.cpp | 12 +- osal/rtems/PollingTask.h | 4 +- osal/rtems/QueueFactory.cpp | 2 +- osal/rtems/RtemsBasic.h | 2 +- osal/rtems/TaskBase.cpp | 2 +- osal/rtems/TaskBase.h | 2 +- osal/rtems/TaskFactory.cpp | 4 +- parameters/HasParametersIF.h | 4 +- parameters/ParameterHelper.cpp | 6 +- parameters/ParameterHelper.h | 4 +- parameters/ParameterMessage.cpp | 4 +- parameters/ParameterMessage.h | 6 +- parameters/ParameterWrapper.cpp | 2 +- parameters/ParameterWrapper.h | 8 +- parameters/ReceivesParameterMessagesIF.h | 4 +- power/Fuse.cpp | 12 +- power/Fuse.h | 16 +- power/PowerComponent.cpp | 2 +- power/PowerComponent.h | 4 +- power/PowerComponentIF.h | 4 +- power/PowerSensor.cpp | 4 +- power/PowerSensor.h | 16 +- power/PowerSwitchIF.h | 4 +- power/PowerSwitcher.cpp | 6 +- power/PowerSwitcher.h | 6 +- pus/CService200ModeCommanding.cpp | 238 +++++----- pus/CService200ModeCommanding.h | 170 +++---- pus/Service1TelecommandVerification.cpp | 16 +- pus/Service1TelecommandVerification.h | 12 +- pus/Service2DeviceAccess.cpp | 334 +++++++------- pus/Service2DeviceAccess.h | 184 ++++---- pus/Service5EventReporting.cpp | 12 +- pus/Service5EventReporting.h | 4 +- pus/Service8FunctionManagement.cpp | 284 ++++++------ pus/Service8FunctionManagement.h | 134 +++--- pus/servicepackets/Service1Packets.h | 4 +- pus/servicepackets/Service200Packets.h | 126 +++--- pus/servicepackets/Service2Packets.h | 152 +++---- pus/servicepackets/Service5Packets.h | 4 +- pus/servicepackets/Service8Packets.h | 242 +++++----- returnvalues/HasReturnvaluesIF.h | 2 +- rmap/RMAP.cpp | 8 +- rmap/RMAP.h | 4 +- rmap/RMAPChannelIF.h | 4 +- rmap/RMAPCookie.cpp | 4 +- rmap/RMAPCookie.h | 4 +- rmap/RmapDeviceCommunicationIF.cpp | 4 +- rmap/RmapDeviceCommunicationIF.h | 2 +- serialize/EndianConverter.h | 2 +- serialize/SerialArrayListAdapter.h | 4 +- serialize/SerialBufferAdapter.cpp | 2 +- serialize/SerialBufferAdapter.h | 4 +- serialize/SerialFixedArrayListAdapter.h | 4 +- serialize/SerialLinkedListAdapter.h | 8 +- serialize/SerializeAdapter.h | 8 +- serialize/SerializeElement.h | 4 +- serialize/SerializeIF.h | 2 +- serviceinterface/ServiceInterfaceBuffer.cpp | 6 +- serviceinterface/ServiceInterfaceBuffer.h | 2 +- serviceinterface/ServiceInterfaceStream.cpp | 2 +- serviceinterface/ServiceInterfaceStream.h | 2 +- storagemanager/LocalPool.h | 12 +- storagemanager/PoolManager.h | 4 +- storagemanager/StorageManagerIF.h | 4 +- subsystem/Subsystem.cpp | 14 +- subsystem/Subsystem.h | 14 +- subsystem/SubsystemBase.cpp | 8 +- subsystem/SubsystemBase.h | 18 +- subsystem/modes/HasModeSequenceIF.h | 6 +- subsystem/modes/ModeDefinitions.h | 8 +- subsystem/modes/ModeSequenceMessage.cpp | 10 +- subsystem/modes/ModeSequenceMessage.h | 6 +- subsystem/modes/ModeStore.cpp | 2 +- subsystem/modes/ModeStore.h | 8 +- subsystem/modes/ModeStoreIF.h | 8 +- tasks/ExecutableObjectIF.h | 2 +- tasks/FixedTimeslotTaskIF.h | 4 +- tasks/PeriodicTaskIF.h | 4 +- tasks/TaskFactory.h | 4 +- tcdistribution/CCSDSDistributor.cpp | 6 +- tcdistribution/CCSDSDistributor.h | 10 +- tcdistribution/CCSDSDistributorIF.h | 4 +- tcdistribution/PUSDistributor.cpp | 10 +- tcdistribution/PUSDistributor.h | 12 +- tcdistribution/PUSDistributorIF.h | 4 +- tcdistribution/TcDistributor.cpp | 10 +- tcdistribution/TcDistributor.h | 14 +- tcdistribution/TcPacketCheck.cpp | 10 +- tcdistribution/TcPacketCheck.h | 6 +- thermal/AbstractTemperatureSensor.cpp | 2 +- thermal/AbstractTemperatureSensor.h | 12 +- thermal/CoreComponent.h | 12 +- thermal/Heater.cpp | 6 +- thermal/Heater.h | 10 +- thermal/RedundantHeater.h | 2 +- thermal/TemperatureSensor.h | 4 +- thermal/ThermalComponentIF.h | 8 +- thermal/ThermalModule.cpp | 4 +- thermal/ThermalModule.h | 8 +- thermal/ThermalMonitor.cpp | 6 +- thermal/ThermalMonitor.h | 4 +- timemanager/CCSDSTime.cpp | 2 +- timemanager/CCSDSTime.h | 4 +- timemanager/Clock.h | 6 +- timemanager/Countdown.cpp | 2 +- timemanager/Countdown.h | 2 +- timemanager/Stopwatch.cpp | 114 ++--- timemanager/Stopwatch.h | 142 +++--- timemanager/TimeMessage.cpp | 2 +- timemanager/TimeMessage.h | 4 +- timemanager/TimeStamperIF.h | 2 +- tmstorage/TmStoreBackendIF.h | 10 +- tmstorage/TmStoreFrontendIF.h | 6 +- tmstorage/TmStoreMessage.cpp | 4 +- tmstorage/TmStoreMessage.h | 8 +- tmstorage/TmStorePackets.h | 16 +- tmtcpacket/SpacePacket.cpp | 6 +- tmtcpacket/SpacePacket.h | 2 +- tmtcpacket/SpacePacketBase.cpp | 4 +- tmtcpacket/SpacePacketBase.h | 2 +- tmtcpacket/packetmatcher/ApidMatcher.h | 6 +- tmtcpacket/packetmatcher/PacketMatchTree.cpp | 8 +- tmtcpacket/packetmatcher/PacketMatchTree.h | 8 +- tmtcpacket/packetmatcher/ServiceMatcher.h | 6 +- tmtcpacket/packetmatcher/SubserviceMatcher.h | 6 +- tmtcpacket/pus/PacketTimestampInterpreterIF.h | 2 +- tmtcpacket/pus/TcPacketBase.cpp | 6 +- tmtcpacket/pus/TcPacketBase.h | 2 +- tmtcpacket/pus/TcPacketStored.cpp | 6 +- tmtcpacket/pus/TcPacketStored.h | 4 +- tmtcpacket/pus/TmPacketBase.cpp | 10 +- tmtcpacket/pus/TmPacketBase.h | 8 +- tmtcpacket/pus/TmPacketMinimal.cpp | 4 +- tmtcpacket/pus/TmPacketMinimal.h | 4 +- tmtcpacket/pus/TmPacketStored.cpp | 8 +- tmtcpacket/pus/TmPacketStored.h | 10 +- tmtcservices/AcceptsTelecommandsIF.h | 2 +- tmtcservices/AcceptsTelemetryIF.h | 2 +- tmtcservices/AcceptsVerifyMessageIF.h | 2 +- tmtcservices/CommandingServiceBase.cpp | 16 +- tmtcservices/CommandingServiceBase.h | 20 +- tmtcservices/PusServiceBase.cpp | 14 +- tmtcservices/PusServiceBase.h | 18 +- tmtcservices/PusVerificationReport.cpp | 4 +- tmtcservices/PusVerificationReport.h | 6 +- tmtcservices/SourceSequenceCounter.h | 2 +- tmtcservices/TmTcBridge.cpp | 414 +++++++++--------- tmtcservices/TmTcBridge.h | 308 ++++++------- tmtcservices/TmTcMessage.cpp | 2 +- tmtcservices/TmTcMessage.h | 4 +- tmtcservices/VerificationReporter.cpp | 8 +- tmtcservices/VerificationReporter.h | 4 +- 384 files changed, 2477 insertions(+), 2477 deletions(-) diff --git a/action/ActionHelper.cpp b/action/ActionHelper.cpp index dc6bd498..b43c676d 100644 --- a/action/ActionHelper.cpp +++ b/action/ActionHelper.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "ActionHelper.h" +#include "HasActionsIF.h" +#include "../objectmanager/ObjectManagerIF.h" ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue) : owner(setOwner), queueToUse(useThisQueue), ipcStore(nullptr) { diff --git a/action/ActionHelper.h b/action/ActionHelper.h index eb3bfa54..bbc6d114 100644 --- a/action/ActionHelper.h +++ b/action/ActionHelper.h @@ -1,9 +1,9 @@ #ifndef ACTIONHELPER_H_ #define ACTIONHELPER_H_ -#include -#include -#include +#include "ActionMessage.h" +#include "../serialize/SerializeIF.h" +#include "../ipc/MessageQueueIF.h" /** * \brief Action Helper is a helper class which handles action messages * diff --git a/action/ActionMessage.cpp b/action/ActionMessage.cpp index 96ff59b6..b0bcabaa 100644 --- a/action/ActionMessage.cpp +++ b/action/ActionMessage.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "ActionMessage.h" +#include "../objectmanager/ObjectManagerIF.h" +#include "../storagemanager/StorageManagerIF.h" ActionMessage::ActionMessage() { } diff --git a/action/ActionMessage.h b/action/ActionMessage.h index 5d8332cb..c564911c 100644 --- a/action/ActionMessage.h +++ b/action/ActionMessage.h @@ -1,9 +1,9 @@ #ifndef ACTIONMESSAGE_H_ #define ACTIONMESSAGE_H_ -#include -#include -#include +#include "../ipc/CommandMessage.h" +#include "../objectmanager/ObjectManagerIF.h" +#include "../storagemanager/StorageManagerIF.h" typedef uint32_t ActionId_t; class ActionMessage { diff --git a/action/CommandActionHelper.cpp b/action/CommandActionHelper.cpp index 70ffbbde..4e88f3c3 100644 --- a/action/CommandActionHelper.cpp +++ b/action/CommandActionHelper.cpp @@ -1,8 +1,8 @@ -#include -#include -#include -#include -#include +#include "ActionMessage.h" +#include "CommandActionHelper.h" +#include "CommandsActionsIF.h" +#include "HasActionsIF.h" +#include "../objectmanager/ObjectManagerIF.h" CommandActionHelper::CommandActionHelper(CommandsActionsIF *setOwner) : owner(setOwner), queueToUse(NULL), ipcStore( diff --git a/action/CommandActionHelper.h b/action/CommandActionHelper.h index 24d0380c..cfed8c94 100644 --- a/action/CommandActionHelper.h +++ b/action/CommandActionHelper.h @@ -1,12 +1,12 @@ #ifndef COMMANDACTIONHELPER_H_ #define COMMANDACTIONHELPER_H_ -#include -#include -#include -#include -#include -#include +#include "ActionMessage.h" +#include "../objectmanager/ObjectManagerIF.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../serialize/SerializeIF.h" +#include "../storagemanager/StorageManagerIF.h" +#include "../ipc/MessageQueueIF.h" class CommandsActionsIF; diff --git a/action/CommandsActionsIF.h b/action/CommandsActionsIF.h index db76fb50..3d04015d 100644 --- a/action/CommandsActionsIF.h +++ b/action/CommandsActionsIF.h @@ -1,9 +1,9 @@ #ifndef COMMANDSACTIONSIF_H_ #define COMMANDSACTIONSIF_H_ -#include -#include -#include +#include "CommandActionHelper.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../ipc/MessageQueueIF.h" /** * Interface to separate commanding actions of other objects. diff --git a/action/HasActionsIF.h b/action/HasActionsIF.h index 008d9eaf..886d0837 100644 --- a/action/HasActionsIF.h +++ b/action/HasActionsIF.h @@ -1,11 +1,11 @@ #ifndef FRAMEWORK_ACTION_HASACTIONSIF_H_ #define FRAMEWORK_ACTION_HASACTIONSIF_H_ -#include -#include -#include -#include -#include +#include "ActionHelper.h" +#include "ActionMessage.h" +#include "SimpleActionHelper.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../ipc/MessageQueueIF.h" /** * @brief * Interface for component which uses actions diff --git a/action/SimpleActionHelper.cpp b/action/SimpleActionHelper.cpp index 6861fc28..d79a3c97 100644 --- a/action/SimpleActionHelper.cpp +++ b/action/SimpleActionHelper.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "HasActionsIF.h" +#include "SimpleActionHelper.h" SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue) : ActionHelper(setOwner, useThisQueue), isExecuting(false), lastCommander( diff --git a/action/SimpleActionHelper.h b/action/SimpleActionHelper.h index 71e73c5a..1329b5fb 100644 --- a/action/SimpleActionHelper.h +++ b/action/SimpleActionHelper.h @@ -1,7 +1,7 @@ #ifndef SIMPLEACTIONHELPER_H_ #define SIMPLEACTIONHELPER_H_ -#include +#include "ActionHelper.h" class SimpleActionHelper: public ActionHelper { public: diff --git a/container/ArrayList.h b/container/ArrayList.h index 9c4c4ceb..018f9894 100644 --- a/container/ArrayList.h +++ b/container/ArrayList.h @@ -1,9 +1,9 @@ #ifndef ARRAYLIST_H_ #define ARRAYLIST_H_ -#include -#include -#include +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../serialize/SerializeAdapter.h" +#include "../serialize/SerializeIF.h" /** * A List that stores its values in an array. diff --git a/container/FIFO.h b/container/FIFO.h index f70c78b0..3172d9d1 100644 --- a/container/FIFO.h +++ b/container/FIFO.h @@ -1,7 +1,7 @@ #ifndef FIFO_H_ #define FIFO_H_ -#include +#include "../returnvalues/HasReturnvaluesIF.h" /** * @brief Simple First-In-First-Out data structure diff --git a/container/FixedArrayList.h b/container/FixedArrayList.h index eeffcc87..42b59177 100644 --- a/container/FixedArrayList.h +++ b/container/FixedArrayList.h @@ -1,7 +1,7 @@ #ifndef FIXEDARRAYLIST_H_ #define FIXEDARRAYLIST_H_ -#include +#include "ArrayList.h" /** * \ingroup container */ diff --git a/container/FixedMap.h b/container/FixedMap.h index ac170bd2..dc19ce53 100644 --- a/container/FixedMap.h +++ b/container/FixedMap.h @@ -1,8 +1,8 @@ #ifndef FIXEDMAP_H_ #define FIXEDMAP_H_ -#include -#include +#include "ArrayList.h" +#include "../returnvalues/HasReturnvaluesIF.h" #include /** diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 21629664..6152d8d7 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ #define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ -#include +#include "ArrayList.h" #include #include /** diff --git a/container/HybridIterator.h b/container/HybridIterator.h index f2fd6b28..8d020cb9 100644 --- a/container/HybridIterator.h +++ b/container/HybridIterator.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ #define FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ -#include -#include +#include "ArrayList.h" +#include "SinglyLinkedList.h" template class HybridIterator: public LinkedElement::Iterator, diff --git a/container/IndexedRingMemoryArray.h b/container/IndexedRingMemoryArray.h index 6e7f330c..0d85b49b 100644 --- a/container/IndexedRingMemoryArray.h +++ b/container/IndexedRingMemoryArray.h @@ -1,11 +1,11 @@ #ifndef FRAMEWORK_CONTAINER_INDEXEDRINGMEMORY_H_ #define FRAMEWORK_CONTAINER_INDEXEDRINGMEMORY_H_ -#include -#include -#include -#include -#include +#include "ArrayList.h" +#include "../globalfunctions/CRC.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../serialize/SerialArrayListAdapter.h" #include template diff --git a/container/PlacementFactory.h b/container/PlacementFactory.h index daf4ee20..05538478 100644 --- a/container/PlacementFactory.h +++ b/container/PlacementFactory.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_ #define FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_ -#include +#include "../storagemanager/StorageManagerIF.h" #include class PlacementFactory { diff --git a/container/RingBufferBase.h b/container/RingBufferBase.h index 3ef782d8..e3a87d9d 100644 --- a/container/RingBufferBase.h +++ b/container/RingBufferBase.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ #define FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ -#include +#include "../returnvalues/HasReturnvaluesIF.h" template class RingBufferBase { diff --git a/container/SimpleRingBuffer.cpp b/container/SimpleRingBuffer.cpp index 63dc3514..ee087643 100644 --- a/container/SimpleRingBuffer.cpp +++ b/container/SimpleRingBuffer.cpp @@ -1,4 +1,4 @@ -#include +#include "SimpleRingBuffer.h" #include SimpleRingBuffer::SimpleRingBuffer(uint32_t size, bool overwriteOld) : diff --git a/container/SimpleRingBuffer.h b/container/SimpleRingBuffer.h index 6d7d67e1..5d4fecab 100644 --- a/container/SimpleRingBuffer.h +++ b/container/SimpleRingBuffer.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ #define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ -#include +#include "RingBufferBase.h" #include class SimpleRingBuffer: public RingBufferBase<> { diff --git a/controller/ControllerBase.cpp b/controller/ControllerBase.cpp index 7b11bdfa..69551731 100644 --- a/controller/ControllerBase.cpp +++ b/controller/ControllerBase.cpp @@ -1,8 +1,8 @@ -#include -#include -#include -#include -#include +#include "../subsystem/SubsystemBase.h" +#include "ControllerBase.h" +#include "../subsystem/SubsystemBase.h" +#include "../ipc/QueueFactory.h" +#include "../action/HasActionsIF.h" ControllerBase::ControllerBase(uint32_t setObjectId, uint32_t parentId, size_t commandQueueDepth) : diff --git a/controller/ControllerBase.h b/controller/ControllerBase.h index 804bc7c2..f5182ceb 100644 --- a/controller/ControllerBase.h +++ b/controller/ControllerBase.h @@ -1,13 +1,13 @@ #ifndef CONTROLLERBASE_H_ #define CONTROLLERBASE_H_ -#include -#include -#include -#include -#include -#include -#include +#include "../health/HasHealthIF.h" +#include "../health/HealthHelper.h" +#include "../modes/HasModesIF.h" +#include "../modes/ModeHelper.h" +#include "../objectmanager/SystemObject.h" +#include "../tasks/ExecutableObjectIF.h" +#include "../datapool/HkSwitchHelper.h" class ControllerBase: public HasModesIF, diff --git a/coordinates/CoordinateTransformations.cpp b/coordinates/CoordinateTransformations.cpp index b57519a3..4e2debbe 100644 --- a/coordinates/CoordinateTransformations.cpp +++ b/coordinates/CoordinateTransformations.cpp @@ -1,7 +1,7 @@ -#include -#include -#include -#include +#include "CoordinateTransformations.h" +#include "../globalfunctions/constants.h" +#include "../globalfunctions/math/MatrixOperations.h" +#include "../globalfunctions/math/VectorOperations.h" #include #include diff --git a/coordinates/CoordinateTransformations.h b/coordinates/CoordinateTransformations.h index b072271f..09ea2c48 100644 --- a/coordinates/CoordinateTransformations.h +++ b/coordinates/CoordinateTransformations.h @@ -1,7 +1,7 @@ #ifndef COORDINATETRANSFORMATIONS_H_ #define COORDINATETRANSFORMATIONS_H_ -#include +#include "../timemanager/Clock.h" #include class CoordinateTransformations { diff --git a/coordinates/Jgm3Model.h b/coordinates/Jgm3Model.h index 8f0598f8..884ed141 100644 --- a/coordinates/Jgm3Model.h +++ b/coordinates/Jgm3Model.h @@ -2,10 +2,10 @@ #define FRAMEWORK_COORDINATES_JGM3MODEL_H_ #include -#include -#include -#include -#include +#include "CoordinateTransformations.h" +#include "../globalfunctions/math/VectorOperations.h" +#include "../globalfunctions/timevalOperations.h" +#include "../globalfunctions/constants.h" #include diff --git a/coordinates/Sgp4Propagator.cpp b/coordinates/Sgp4Propagator.cpp index 0eb20f08..5cb1497c 100644 --- a/coordinates/Sgp4Propagator.cpp +++ b/coordinates/Sgp4Propagator.cpp @@ -1,9 +1,9 @@ -#include -#include -#include -#include -#include -#include +#include "CoordinateTransformations.h" +#include "Sgp4Propagator.h" +#include "../globalfunctions/constants.h" +#include "../globalfunctions/math/MatrixOperations.h" +#include "../globalfunctions/math/VectorOperations.h" +#include "../globalfunctions/timevalOperations.h" #include Sgp4Propagator::Sgp4Propagator() : initialized(false), epoch({0, 0}), whichconst(wgs84) { diff --git a/coordinates/Sgp4Propagator.h b/coordinates/Sgp4Propagator.h index 95739762..3949547e 100644 --- a/coordinates/Sgp4Propagator.h +++ b/coordinates/Sgp4Propagator.h @@ -3,7 +3,7 @@ #include #include "../contrib/sgp4/sgp4unit.h" -#include +#include "../returnvalues/HasReturnvaluesIF.h" class Sgp4Propagator { public: diff --git a/datalinklayer/BCFrame.h b/datalinklayer/BCFrame.h index bcdf5300..b7795556 100644 --- a/datalinklayer/BCFrame.h +++ b/datalinklayer/BCFrame.h @@ -8,7 +8,7 @@ #ifndef BCFRAME_H_ #define BCFRAME_H_ -#include +#include "CCSDSReturnValuesIF.h" /** * Small helper class to identify a BcFrame. diff --git a/datalinklayer/CCSDSReturnValuesIF.h b/datalinklayer/CCSDSReturnValuesIF.h index 4d4f4bde..805b6969 100644 --- a/datalinklayer/CCSDSReturnValuesIF.h +++ b/datalinklayer/CCSDSReturnValuesIF.h @@ -8,7 +8,7 @@ #ifndef CCSDSRETURNVALUESIF_H_ #define CCSDSRETURNVALUESIF_H_ -#include +#include "../returnvalues/HasReturnvaluesIF.h" /** * This is a helper class to collect special return values that come up during CCSDS Handling. * @ingroup ccsds_handling diff --git a/datalinklayer/Clcw.cpp b/datalinklayer/Clcw.cpp index ee497e20..dc435a2b 100644 --- a/datalinklayer/Clcw.cpp +++ b/datalinklayer/Clcw.cpp @@ -7,8 +7,8 @@ -#include -#include +#include "Clcw.h" +#include "../serviceinterface/ServiceInterfaceStream.h" Clcw::Clcw() { content.raw = 0; diff --git a/datalinklayer/Clcw.h b/datalinklayer/Clcw.h index f19f37b6..8116d63b 100644 --- a/datalinklayer/Clcw.h +++ b/datalinklayer/Clcw.h @@ -8,7 +8,7 @@ #ifndef CLCW_H_ #define CLCW_H_ -#include +#include "ClcwIF.h" /** * Small helper method to handle the Clcw values. * It has a content struct that manages the register and can be set externally. diff --git a/datalinklayer/DataLinkLayer.cpp b/datalinklayer/DataLinkLayer.cpp index 4ca7f270..75f2edda 100644 --- a/datalinklayer/DataLinkLayer.cpp +++ b/datalinklayer/DataLinkLayer.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "DataLinkLayer.h" +#include "../globalfunctions/CRC.h" +#include "../serviceinterface/ServiceInterfaceStream.h" DataLinkLayer::DataLinkLayer(uint8_t* set_frame_buffer, ClcwIF* setClcw, uint8_t set_start_sequence_length, uint16_t set_scid) : diff --git a/datalinklayer/DataLinkLayer.h b/datalinklayer/DataLinkLayer.h index 8a3bb8e5..5a900099 100644 --- a/datalinklayer/DataLinkLayer.h +++ b/datalinklayer/DataLinkLayer.h @@ -1,11 +1,11 @@ #ifndef DATALINKLAYER_H_ #define DATALINKLAYER_H_ -#include -#include -#include -#include -#include +#include "CCSDSReturnValuesIF.h" +#include "ClcwIF.h" +#include "TcTransferFrame.h" +#include "VirtualChannelReceptionIF.h" +#include "../events/Event.h" #include diff --git a/datalinklayer/Farm1StateIF.h b/datalinklayer/Farm1StateIF.h index 25836e6a..71794d75 100644 --- a/datalinklayer/Farm1StateIF.h +++ b/datalinklayer/Farm1StateIF.h @@ -8,7 +8,7 @@ #ifndef FARM1STATEIF_H_ #define FARM1STATEIF_H_ -#include +#include "CCSDSReturnValuesIF.h" class VirtualChannelReception; class TcTransferFrame; class ClcwIF; diff --git a/datalinklayer/Farm1StateLockout.cpp b/datalinklayer/Farm1StateLockout.cpp index 45ae47f9..1b339a85 100644 --- a/datalinklayer/Farm1StateLockout.cpp +++ b/datalinklayer/Farm1StateLockout.cpp @@ -7,10 +7,10 @@ -#include -#include -#include -#include +#include "ClcwIF.h" +#include "Farm1StateLockout.h" +#include "TcTransferFrame.h" +#include "VirtualChannelReception.h" Farm1StateLockout::Farm1StateLockout(VirtualChannelReception* setMyVC) : myVC(setMyVC) { } diff --git a/datalinklayer/Farm1StateLockout.h b/datalinklayer/Farm1StateLockout.h index aac8ed74..63cdc4d2 100644 --- a/datalinklayer/Farm1StateLockout.h +++ b/datalinklayer/Farm1StateLockout.h @@ -8,7 +8,7 @@ #ifndef FARM1STATELOCKOUT_H_ #define FARM1STATELOCKOUT_H_ -#include +#include "Farm1StateIF.h" /** * This class represents the FARM-1 "Lockout" State. diff --git a/datalinklayer/Farm1StateOpen.cpp b/datalinklayer/Farm1StateOpen.cpp index b06cff48..61c0997f 100644 --- a/datalinklayer/Farm1StateOpen.cpp +++ b/datalinklayer/Farm1StateOpen.cpp @@ -8,10 +8,10 @@ -#include -#include -#include -#include +#include "ClcwIF.h" +#include "Farm1StateOpen.h" +#include "TcTransferFrame.h" +#include "VirtualChannelReception.h" Farm1StateOpen::Farm1StateOpen(VirtualChannelReception* setMyVC) : myVC(setMyVC) { } diff --git a/datalinklayer/Farm1StateOpen.h b/datalinklayer/Farm1StateOpen.h index 09caacbb..3b3a2604 100644 --- a/datalinklayer/Farm1StateOpen.h +++ b/datalinklayer/Farm1StateOpen.h @@ -8,7 +8,7 @@ #ifndef FARM1STATEOPEN_H_ #define FARM1STATEOPEN_H_ -#include +#include "Farm1StateIF.h" /** * This class represents the FARM-1 "Open" State. diff --git a/datalinklayer/Farm1StateWait.cpp b/datalinklayer/Farm1StateWait.cpp index 1c72e68f..9001e1f5 100644 --- a/datalinklayer/Farm1StateWait.cpp +++ b/datalinklayer/Farm1StateWait.cpp @@ -6,10 +6,10 @@ */ -#include -#include -#include -#include +#include "ClcwIF.h" +#include "Farm1StateWait.h" +#include "TcTransferFrame.h" +#include "VirtualChannelReception.h" Farm1StateWait::Farm1StateWait(VirtualChannelReception* setMyVC) : myVC(setMyVC) { } diff --git a/datalinklayer/Farm1StateWait.h b/datalinklayer/Farm1StateWait.h index f1201791..877c36c2 100644 --- a/datalinklayer/Farm1StateWait.h +++ b/datalinklayer/Farm1StateWait.h @@ -8,7 +8,7 @@ #ifndef FARM1STATEWAIT_H_ #define FARM1STATEWAIT_H_ -#include +#include "Farm1StateIF.h" /** * This class represents the FARM-1 "Wait" State. diff --git a/datalinklayer/MapPacketExtraction.cpp b/datalinklayer/MapPacketExtraction.cpp index 11b0792a..cb12b321 100644 --- a/datalinklayer/MapPacketExtraction.cpp +++ b/datalinklayer/MapPacketExtraction.cpp @@ -5,13 +5,13 @@ * @author baetz */ -#include -#include -#include -#include -#include -#include -#include +#include "MapPacketExtraction.h" +#include "../ipc/QueueFactory.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../storagemanager/StorageManagerIF.h" +#include "../tmtcpacket/SpacePacketBase.h" +#include "../tmtcservices/AcceptsTelecommandsIF.h" +#include "../tmtcservices/TmTcMessage.h" #include MapPacketExtraction::MapPacketExtraction(uint8_t setMapId, diff --git a/datalinklayer/MapPacketExtraction.h b/datalinklayer/MapPacketExtraction.h index 5a32366c..507f13db 100644 --- a/datalinklayer/MapPacketExtraction.h +++ b/datalinklayer/MapPacketExtraction.h @@ -8,10 +8,10 @@ #ifndef MAPPACKETEXTRACTION_H_ #define MAPPACKETEXTRACTION_H_ -#include -#include -#include -#include +#include "MapPacketExtractionIF.h" +#include "../objectmanager/ObjectManagerIF.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../ipc/MessageQueueSenderIF.h" class StorageManagerIF; diff --git a/datalinklayer/MapPacketExtractionIF.h b/datalinklayer/MapPacketExtractionIF.h index 802a893d..e29ac666 100644 --- a/datalinklayer/MapPacketExtractionIF.h +++ b/datalinklayer/MapPacketExtractionIF.h @@ -8,8 +8,8 @@ #ifndef MAPPACKETEXTRACTIONIF_H_ #define MAPPACKETEXTRACTIONIF_H_ -#include -#include +#include "CCSDSReturnValuesIF.h" +#include "TcTransferFrame.h" /** * This is the interface for MAP Packet Extraction classes. diff --git a/datalinklayer/TcTransferFrame.cpp b/datalinklayer/TcTransferFrame.cpp index 30398e9b..f1a70bdc 100644 --- a/datalinklayer/TcTransferFrame.cpp +++ b/datalinklayer/TcTransferFrame.cpp @@ -7,8 +7,8 @@ -#include -#include +#include "TcTransferFrame.h" +#include "../serviceinterface/ServiceInterfaceStream.h" TcTransferFrame::TcTransferFrame() { frame = NULL; diff --git a/datalinklayer/TcTransferFrameLocal.cpp b/datalinklayer/TcTransferFrameLocal.cpp index 79e14167..e8785c92 100644 --- a/datalinklayer/TcTransferFrameLocal.cpp +++ b/datalinklayer/TcTransferFrameLocal.cpp @@ -5,9 +5,9 @@ * @author baetz */ -#include -#include -#include +#include "TcTransferFrameLocal.h" +#include "../globalfunctions/CRC.h" +#include "../serviceinterface/ServiceInterfaceStream.h" #include TcTransferFrameLocal::TcTransferFrameLocal(bool bypass, bool controlCommand, uint16_t scid, diff --git a/datalinklayer/TcTransferFrameLocal.h b/datalinklayer/TcTransferFrameLocal.h index f20f12ec..487d8940 100644 --- a/datalinklayer/TcTransferFrameLocal.h +++ b/datalinklayer/TcTransferFrameLocal.h @@ -8,7 +8,7 @@ #ifndef TCTRANSFERFRAMELOCAL_H_ #define TCTRANSFERFRAMELOCAL_H_ -#include +#include "TcTransferFrame.h" /** * This is a helper class to locally create TC Transfer Frames. diff --git a/datalinklayer/VirtualChannelReception.cpp b/datalinklayer/VirtualChannelReception.cpp index 373f6c62..cde28de3 100644 --- a/datalinklayer/VirtualChannelReception.cpp +++ b/datalinklayer/VirtualChannelReception.cpp @@ -5,9 +5,9 @@ * @author baetz */ -#include -#include -#include +#include "BCFrame.h" +#include "VirtualChannelReception.h" +#include "../serviceinterface/ServiceInterfaceStream.h" VirtualChannelReception::VirtualChannelReception(uint8_t setChannelId, uint8_t setSlidingWindowWidth) : diff --git a/datalinklayer/VirtualChannelReception.h b/datalinklayer/VirtualChannelReception.h index f364c6e5..9b4e2987 100644 --- a/datalinklayer/VirtualChannelReception.h +++ b/datalinklayer/VirtualChannelReception.h @@ -8,14 +8,14 @@ #ifndef VIRTUALCHANNELRECEPTION_H_ #define VIRTUALCHANNELRECEPTION_H_ -#include -#include -#include -#include -#include -#include -#include -#include +#include "CCSDSReturnValuesIF.h" +#include "Clcw.h" +#include "Farm1StateIF.h" +#include "Farm1StateLockout.h" +#include "Farm1StateOpen.h" +#include "Farm1StateWait.h" +#include "MapPacketExtractionIF.h" +#include "VirtualChannelReceptionIF.h" #include /** * Implementation of a TC Virtual Channel. diff --git a/datalinklayer/VirtualChannelReceptionIF.h b/datalinklayer/VirtualChannelReceptionIF.h index 98a9b72c..36f60e8c 100644 --- a/datalinklayer/VirtualChannelReceptionIF.h +++ b/datalinklayer/VirtualChannelReceptionIF.h @@ -8,9 +8,9 @@ #ifndef VIRTUALCHANNELRECEPTIONIF_H_ #define VIRTUALCHANNELRECEPTIONIF_H_ -#include -#include -#include +#include "ClcwIF.h" +#include "TcTransferFrame.h" +#include "../returnvalues/HasReturnvaluesIF.h" /** * This is the interface for Virtual Channel reception classes. diff --git a/datapool/ControllerSet.cpp b/datapool/ControllerSet.cpp index eb4f6d0f..6339034c 100644 --- a/datapool/ControllerSet.cpp +++ b/datapool/ControllerSet.cpp @@ -1,4 +1,4 @@ -#include +#include "ControllerSet.h" ControllerSet::ControllerSet() { diff --git a/datapool/ControllerSet.h b/datapool/ControllerSet.h index de06bf91..e27debff 100644 --- a/datapool/ControllerSet.h +++ b/datapool/ControllerSet.h @@ -1,7 +1,7 @@ #ifndef CONTROLLERSET_H_ #define CONTROLLERSET_H_ -#include +#include "DataSet.h" class ControllerSet :public DataSet { public: diff --git a/datapool/DataPool.cpp b/datapool/DataPool.cpp index f44da64e..817089bf 100644 --- a/datapool/DataPool.cpp +++ b/datapool/DataPool.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "DataPool.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../ipc/MutexFactory.h" DataPool::DataPool( void ( *initFunction )( std::map* pool_map ) ) { mutex = MutexFactory::instance()->createMutex(); diff --git a/datapool/DataPool.h b/datapool/DataPool.h index 6e38dc1b..7abf2898 100644 --- a/datapool/DataPool.h +++ b/datapool/DataPool.h @@ -11,9 +11,9 @@ #ifndef DATAPOOL_H_ #define DATAPOOL_H_ -#include -#include -#include +#include "PoolEntry.h" +#include "../globalfunctions/Type.h" +#include "../ipc/MutexIF.h" #include /** diff --git a/datapool/DataPoolAdmin.cpp b/datapool/DataPoolAdmin.cpp index 3ea266ea..f298d530 100644 --- a/datapool/DataPoolAdmin.cpp +++ b/datapool/DataPoolAdmin.cpp @@ -1,10 +1,10 @@ -#include -#include -#include -#include -#include -#include -#include +#include "DataPool.h" +#include "DataPoolAdmin.h" +#include "DataSet.h" +#include "PoolRawAccess.h" +#include "../ipc/CommandMessage.h" +#include "../ipc/QueueFactory.h" +#include "../parameters/ParameterMessage.h" DataPoolAdmin::DataPoolAdmin(object_id_t objectId) : SystemObject(objectId), storage(NULL), commandQueue(NULL), memoryHelper( diff --git a/datapool/DataPoolAdmin.h b/datapool/DataPoolAdmin.h index 1be920b5..e2d1e9e1 100644 --- a/datapool/DataPoolAdmin.h +++ b/datapool/DataPoolAdmin.h @@ -1,15 +1,15 @@ #ifndef DATAPOOLADMIN_H_ #define DATAPOOLADMIN_H_ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "../memory/MemoryHelper.h" +#include "../action/HasActionsIF.h" +#include "../action/SimpleActionHelper.h" +#include "../objectmanager/SystemObject.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../tasks/ExecutableObjectIF.h" +#include "../parameters/ReceivesParameterMessagesIF.h" +#include "DataPoolParameterWrapper.h" +#include "../ipc/MessageQueueIF.h" class DataPoolAdmin: public HasActionsIF, public ExecutableObjectIF, diff --git a/datapool/DataPoolParameterWrapper.cpp b/datapool/DataPoolParameterWrapper.cpp index e08eba5b..79367405 100644 --- a/datapool/DataPoolParameterWrapper.cpp +++ b/datapool/DataPoolParameterWrapper.cpp @@ -1,10 +1,10 @@ #include "DataPoolParameterWrapper.h" //for returncodes -#include +#include "../parameters/HasParametersIF.h" -#include -#include +#include "DataSet.h" +#include "PoolRawAccess.h" DataPoolParameterWrapper::DataPoolParameterWrapper() : type(Type::UNKNOWN_TYPE), rows(0), columns(0), poolId( diff --git a/datapool/DataPoolParameterWrapper.h b/datapool/DataPoolParameterWrapper.h index a3dbdc04..b1e505a7 100644 --- a/datapool/DataPoolParameterWrapper.h +++ b/datapool/DataPoolParameterWrapper.h @@ -1,8 +1,8 @@ #ifndef DATAPOOLPARAMETERWRAPPER_H_ #define DATAPOOLPARAMETERWRAPPER_H_ -#include -#include +#include "../globalfunctions/Type.h" +#include "../parameters/ParameterWrapper.h" class DataPoolParameterWrapper: public SerializeIF { public: diff --git a/datapool/DataSet.cpp b/datapool/DataSet.cpp index f49f2ee5..e41489bd 100644 --- a/datapool/DataSet.cpp +++ b/datapool/DataSet.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "DataSet.h" +#include "../serviceinterface/ServiceInterfaceStream.h" DataSet::DataSet() : fill_count(0), state(DATA_SET_UNINITIALISED) { diff --git a/datapool/DataSet.h b/datapool/DataSet.h index 3d211537..04044bfe 100644 --- a/datapool/DataSet.h +++ b/datapool/DataSet.h @@ -12,13 +12,13 @@ #ifndef DATASET_H_ #define DATASET_H_ -#include -#include -#include -#include -#include -#include -#include +#include "DataPool.h" +#include "DataSetIF.h" +#include "PoolRawAccess.h" +#include "PoolVariable.h" +#include "PoolVarList.h" +#include "PoolVector.h" +#include "../serialize/SerializeAdapter.h" /** * \brief The DataSet class manages a set of locally checked out variables. * diff --git a/datapool/HkSwitchHelper.cpp b/datapool/HkSwitchHelper.cpp index caae2146..04096aca 100644 --- a/datapool/HkSwitchHelper.cpp +++ b/datapool/HkSwitchHelper.cpp @@ -1,6 +1,6 @@ -#include +#include "HkSwitchHelper.h" //#include -#include +#include "../ipc/QueueFactory.h" HkSwitchHelper::HkSwitchHelper(EventReportingProxyIF* eventProxy) : commandActionHelper(this), eventProxy(eventProxy) { diff --git a/datapool/HkSwitchHelper.h b/datapool/HkSwitchHelper.h index 1a3b6275..385b2047 100644 --- a/datapool/HkSwitchHelper.h +++ b/datapool/HkSwitchHelper.h @@ -1,9 +1,9 @@ #ifndef FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_ #define FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_ -#include -#include -#include +#include "../tasks/ExecutableObjectIF.h" +#include "../action/CommandsActionsIF.h" +#include "../events/EventReportingProxyIF.h" //TODO this class violations separation between mission and framework //but it is only a transitional solution until the Datapool is diff --git a/datapool/PIDReader.h b/datapool/PIDReader.h index 464b1549..3b38b51d 100644 --- a/datapool/PIDReader.h +++ b/datapool/PIDReader.h @@ -1,11 +1,11 @@ #ifndef PIDREADER_H_ #define PIDREADER_H_ -#include -#include -#include -#include -#include -#include +#include "DataPool.h" +#include "DataSetIF.h" +#include "PoolEntry.h" +#include "PoolVariableIF.h" +#include "../serialize/SerializeAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" template class PIDReaderList; diff --git a/datapool/PIDReaderList.h b/datapool/PIDReaderList.h index 07d1b8e6..1f6aa99c 100644 --- a/datapool/PIDReaderList.h +++ b/datapool/PIDReaderList.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_DATAPOOL_PIDREADERLIST_H_ #define FRAMEWORK_DATAPOOL_PIDREADERLIST_H_ -#include -#include +#include "PIDReader.h" +#include "PoolVariableIF.h" template class PIDReaderList { private: diff --git a/datapool/PoolEntry.cpp b/datapool/PoolEntry.cpp index d535a72b..56e489a5 100644 --- a/datapool/PoolEntry.cpp +++ b/datapool/PoolEntry.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "PoolEntry.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../globalfunctions/arrayprinter.h" #include template diff --git a/datapool/PoolEntry.h b/datapool/PoolEntry.h index 1a22bb63..7b47c673 100644 --- a/datapool/PoolEntry.h +++ b/datapool/PoolEntry.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_DATAPOOL_POOLENTRY_H_ #define FRAMEWORK_DATAPOOL_POOLENTRY_H_ -#include +#include "PoolEntryIF.h" #include #include diff --git a/datapool/PoolEntryIF.h b/datapool/PoolEntryIF.h index a075436e..462de18b 100644 --- a/datapool/PoolEntryIF.h +++ b/datapool/PoolEntryIF.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_DATAPOOL_POOLENTRYIF_H_ #define FRAMEWORK_DATAPOOL_POOLENTRYIF_H_ -#include +#include "../globalfunctions/Type.h" #include /** diff --git a/datapool/PoolRawAccess.cpp b/datapool/PoolRawAccess.cpp index eca354a9..f9264081 100644 --- a/datapool/PoolRawAccess.cpp +++ b/datapool/PoolRawAccess.cpp @@ -1,8 +1,8 @@ -#include -#include -#include -#include -#include +#include "DataPool.h" +#include "PoolEntryIF.h" +#include "PoolRawAccess.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../serialize/EndianConverter.h" #include diff --git a/datapool/PoolRawAccess.h b/datapool/PoolRawAccess.h index 09d19afd..0c7a06bf 100644 --- a/datapool/PoolRawAccess.h +++ b/datapool/PoolRawAccess.h @@ -1,8 +1,8 @@ #ifndef POOLRAWACCESS_H_ #define POOLRAWACCESS_H_ -#include -#include +#include "DataSetIF.h" +#include "PoolVariableIF.h" /** * This class allows accessing Data Pool variables as raw bytes. diff --git a/datapool/PoolVarList.h b/datapool/PoolVarList.h index 90c9f178..035ff2ac 100644 --- a/datapool/PoolVarList.h +++ b/datapool/PoolVarList.h @@ -1,8 +1,8 @@ #ifndef POOLVARLIST_H_ #define POOLVARLIST_H_ -#include -#include +#include "PoolVariable.h" +#include "PoolVariableIF.h" template class PoolVarList { private: diff --git a/datapool/PoolVariable.h b/datapool/PoolVariable.h index a06935c3..a9d3407d 100644 --- a/datapool/PoolVariable.h +++ b/datapool/PoolVariable.h @@ -11,11 +11,11 @@ #ifndef POOLVARIABLE_H_ #define POOLVARIABLE_H_ -#include -#include -#include -#include -#include +#include "DataSetIF.h" +#include "PoolEntry.h" +#include "PoolVariableIF.h" +#include "../serialize/SerializeAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" template class PoolVarList; diff --git a/datapool/PoolVariableIF.h b/datapool/PoolVariableIF.h index 7626c9c1..f47173df 100644 --- a/datapool/PoolVariableIF.h +++ b/datapool/PoolVariableIF.h @@ -11,8 +11,8 @@ #ifndef POOLVARIABLEIF_H_ #define POOLVARIABLEIF_H_ -#include -#include +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../serialize/SerializeIF.h" /** * \brief This interface is used to control local data pool variable representations. diff --git a/datapool/PoolVector.h b/datapool/PoolVector.h index 777ec723..d4ca0842 100644 --- a/datapool/PoolVector.h +++ b/datapool/PoolVector.h @@ -11,11 +11,11 @@ #ifndef POOLVECTOR_H_ #define POOLVECTOR_H_ -#include -#include -#include -#include -#include +#include "DataSetIF.h" +#include "PoolEntry.h" +#include "PoolVariableIF.h" +#include "../serialize/SerializeAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" /** * \brief This is the access class for array-type data pool entries. diff --git a/devicehandlers/AcceptsDeviceResponsesIF.h b/devicehandlers/AcceptsDeviceResponsesIF.h index 0eedae88..8dc69de4 100644 --- a/devicehandlers/AcceptsDeviceResponsesIF.h +++ b/devicehandlers/AcceptsDeviceResponsesIF.h @@ -8,7 +8,7 @@ #ifndef ACCEPTSDEVICERESPONSESIF_H_ #define ACCEPTSDEVICERESPONSESIF_H_ -#include +#include "../ipc/MessageQueueSenderIF.h" class AcceptsDeviceResponsesIF { public: diff --git a/devicehandlers/AssemblyBase.cpp b/devicehandlers/AssemblyBase.cpp index c250cf73..8b3f7f4d 100644 --- a/devicehandlers/AssemblyBase.cpp +++ b/devicehandlers/AssemblyBase.cpp @@ -1,4 +1,4 @@ -#include +#include "AssemblyBase.h" AssemblyBase::AssemblyBase(object_id_t objectId, object_id_t parentId, uint16_t commandQueueDepth) : diff --git a/devicehandlers/AssemblyBase.h b/devicehandlers/AssemblyBase.h index ee121032..bd2e8fad 100644 --- a/devicehandlers/AssemblyBase.h +++ b/devicehandlers/AssemblyBase.h @@ -1,9 +1,9 @@ #ifndef ASSEMBLYBASE_H_ #define ASSEMBLYBASE_H_ -#include -#include -#include +#include "../container/FixedArrayList.h" +#include "DeviceHandlerBase.h" +#include "../subsystem/SubsystemBase.h" class AssemblyBase: public SubsystemBase { public: diff --git a/devicehandlers/ChildHandlerBase.cpp b/devicehandlers/ChildHandlerBase.cpp index 34e45b68..cee2a349 100644 --- a/devicehandlers/ChildHandlerBase.cpp +++ b/devicehandlers/ChildHandlerBase.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "../subsystem/SubsystemBase.h" +#include "ChildHandlerBase.h" +#include "../subsystem/SubsystemBase.h" ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF * comCookie, diff --git a/devicehandlers/ChildHandlerBase.h b/devicehandlers/ChildHandlerBase.h index 59cf26b1..005e8065 100644 --- a/devicehandlers/ChildHandlerBase.h +++ b/devicehandlers/ChildHandlerBase.h @@ -1,8 +1,8 @@ #ifndef PAYLOADHANDLERBASE_H_ #define PAYLOADHANDLERBASE_H_ -#include -#include +#include "ChildHandlerFDIR.h" +#include "DeviceHandlerBase.h" class ChildHandlerBase: public DeviceHandlerBase { public: diff --git a/devicehandlers/ChildHandlerFDIR.cpp b/devicehandlers/ChildHandlerFDIR.cpp index 1bba47fe..14043a77 100644 --- a/devicehandlers/ChildHandlerFDIR.cpp +++ b/devicehandlers/ChildHandlerFDIR.cpp @@ -1,4 +1,4 @@ -#include +#include "ChildHandlerFDIR.h" ChildHandlerFDIR::ChildHandlerFDIR(object_id_t owner, object_id_t faultTreeParent, uint32_t recoveryCount) : DeviceHandlerFailureIsolation(owner, faultTreeParent) { diff --git a/devicehandlers/ChildHandlerFDIR.h b/devicehandlers/ChildHandlerFDIR.h index 7df9d238..ce844518 100644 --- a/devicehandlers/ChildHandlerFDIR.h +++ b/devicehandlers/ChildHandlerFDIR.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_DEVICEHANDLERS_CHILDHANDLERFDIR_H_ #define FRAMEWORK_DEVICEHANDLERS_CHILDHANDLERFDIR_H_ -#include +#include "DeviceHandlerFailureIsolation.h" /** * Very simple extension to normal FDIR. diff --git a/devicehandlers/DeviceCommunicationIF.h b/devicehandlers/DeviceCommunicationIF.h index 9ca31a9b..11960d8e 100644 --- a/devicehandlers/DeviceCommunicationIF.h +++ b/devicehandlers/DeviceCommunicationIF.h @@ -1,8 +1,8 @@ #ifndef DEVICECOMMUNICATIONIF_H_ #define DEVICECOMMUNICATIONIF_H_ -#include -#include +#include "CookieIF.h" +#include "../returnvalues/HasReturnvaluesIF.h" #include /** * @defgroup interfaces Interfaces diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 79b504b5..a87b6de1 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -1,16 +1,16 @@ -#include -#include -#include -#include -#include +#include "DeviceHandlerBase.h" +#include "../objectmanager/ObjectManager.h" +#include "../storagemanager/StorageManagerIF.h" +#include "../thermal/ThermalComponentIF.h" +#include "AcceptsDeviceResponsesIF.h" -#include -#include -#include -#include -#include -#include -#include +#include "../datapool/DataSet.h" +#include "../datapool/PoolVariable.h" +#include "DeviceTmReportingWrapper.h" +#include "../globalfunctions/CRC.h" +#include "../subsystem/SubsystemBase.h" +#include "../ipc/QueueFactory.h" +#include "../serviceinterface/ServiceInterfaceStream.h" #include diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index e79d5d5c..7c68ce06 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -1,22 +1,22 @@ #ifndef DEVICEHANDLERBASE_H_ #define DEVICEHANDLERBASE_H_ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "../objectmanager/SystemObject.h" +#include "../tasks/ExecutableObjectIF.h" +#include "DeviceHandlerIF.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../action/HasActionsIF.h" +#include "../datapool/PoolVariableIF.h" +#include "DeviceCommunicationIF.h" +#include "../modes/HasModesIF.h" +#include "../power/PowerSwitchIF.h" +#include "../ipc/MessageQueueIF.h" -#include -#include -#include -#include -#include +#include "../action/ActionHelper.h" +#include "../health/HealthHelper.h" +#include "../parameters/ParameterHelper.h" +#include "../datapool/HkSwitchHelper.h" +#include "DeviceHandlerFailureIsolation.h" #include diff --git a/devicehandlers/DeviceHandlerFailureIsolation.cpp b/devicehandlers/DeviceHandlerFailureIsolation.cpp index 65c40219..497d6469 100644 --- a/devicehandlers/DeviceHandlerFailureIsolation.cpp +++ b/devicehandlers/DeviceHandlerFailureIsolation.cpp @@ -1,9 +1,9 @@ -#include -#include -#include -#include -#include -#include +#include "DeviceHandlerBase.h" +#include "DeviceHandlerFailureIsolation.h" +#include "../health/HealthTableIF.h" +#include "../power/Fuse.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../thermal/ThermalComponentIF.h" object_id_t DeviceHandlerFailureIsolation::powerConfirmationId = 0; diff --git a/devicehandlers/DeviceHandlerFailureIsolation.h b/devicehandlers/DeviceHandlerFailureIsolation.h index 91f6ef64..aa43b762 100644 --- a/devicehandlers/DeviceHandlerFailureIsolation.h +++ b/devicehandlers/DeviceHandlerFailureIsolation.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFAILUREISOLATION_H_ #define FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFAILUREISOLATION_H_ -#include -#include +#include "../fdir/FaultCounter.h" +#include "../fdir/FailureIsolationBase.h" namespace Factory{ void setStaticFrameworkObjectIds(); } diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index 666d9efc..52a3be4d 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -1,11 +1,11 @@ #ifndef DEVICEHANDLERIF_H_ #define DEVICEHANDLERIF_H_ -#include -#include -#include -#include -#include +#include "../action/HasActionsIF.h" +#include "DeviceHandlerMessage.h" +#include "../events/Event.h" +#include "../modes/HasModesIF.h" +#include "../ipc/MessageQueueSenderIF.h" /** * @brief This is the Interface used to communicate with a device handler. diff --git a/devicehandlers/DeviceHandlerMessage.cpp b/devicehandlers/DeviceHandlerMessage.cpp index 58a6d312..564fae21 100644 --- a/devicehandlers/DeviceHandlerMessage.cpp +++ b/devicehandlers/DeviceHandlerMessage.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "../objectmanager/ObjectManagerIF.h" +#include "DeviceHandlerMessage.h" +#include "../objectmanager/ObjectManagerIF.h" DeviceHandlerMessage::DeviceHandlerMessage() { } diff --git a/devicehandlers/DeviceHandlerMessage.h b/devicehandlers/DeviceHandlerMessage.h index fad0f1b1..f33fdad8 100644 --- a/devicehandlers/DeviceHandlerMessage.h +++ b/devicehandlers/DeviceHandlerMessage.h @@ -1,10 +1,10 @@ #ifndef DEVICEHANDLERMESSAGE_H_ #define DEVICEHANDLERMESSAGE_H_ -#include -#include -#include -#include +#include "../action/ActionMessage.h" +#include "../ipc/CommandMessage.h" +#include "../objectmanager/SystemObjectIF.h" +#include "../storagemanager/StorageManagerIF.h" //SHOULDDO: rework the static constructors to name the type of command they are building, maybe even hide setting the commandID. /** diff --git a/devicehandlers/DeviceTmReportingWrapper.cpp b/devicehandlers/DeviceTmReportingWrapper.cpp index ce5eb109..84f926f0 100644 --- a/devicehandlers/DeviceTmReportingWrapper.cpp +++ b/devicehandlers/DeviceTmReportingWrapper.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "../serialize/SerializeAdapter.h" +#include "DeviceTmReportingWrapper.h" +#include "../serialize/SerializeAdapter.h" DeviceTmReportingWrapper::DeviceTmReportingWrapper(object_id_t objectId, ActionId_t actionId, SerializeIF* data) : diff --git a/devicehandlers/DeviceTmReportingWrapper.h b/devicehandlers/DeviceTmReportingWrapper.h index 4432b7f1..a14c4261 100644 --- a/devicehandlers/DeviceTmReportingWrapper.h +++ b/devicehandlers/DeviceTmReportingWrapper.h @@ -1,9 +1,9 @@ #ifndef DEVICETMREPORTINGWRAPPER_H_ #define DEVICETMREPORTINGWRAPPER_H_ -#include -#include -#include +#include "../action/HasActionsIF.h" +#include "../objectmanager/SystemObjectIF.h" +#include "../serialize/SerializeIF.h" class DeviceTmReportingWrapper: public SerializeIF { public: diff --git a/devicehandlers/FixedSequenceSlot.cpp b/devicehandlers/FixedSequenceSlot.cpp index bb97a8e5..667aba1d 100644 --- a/devicehandlers/FixedSequenceSlot.cpp +++ b/devicehandlers/FixedSequenceSlot.cpp @@ -5,8 +5,8 @@ * @author baetz */ -#include -#include +#include "FixedSequenceSlot.h" +#include "../objectmanager/SystemObjectIF.h" #include FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime, diff --git a/devicehandlers/FixedSequenceSlot.h b/devicehandlers/FixedSequenceSlot.h index 7868cce3..73504955 100644 --- a/devicehandlers/FixedSequenceSlot.h +++ b/devicehandlers/FixedSequenceSlot.h @@ -8,8 +8,8 @@ #ifndef FIXEDSEQUENCESLOT_H_ #define FIXEDSEQUENCESLOT_H_ -#include -#include +#include "../objectmanager/ObjectManagerIF.h" +#include "../tasks/ExecutableObjectIF.h" class PeriodicTaskIF; /** diff --git a/devicehandlers/FixedSlotSequence.cpp b/devicehandlers/FixedSlotSequence.cpp index 9a0dc372..38d4dcea 100644 --- a/devicehandlers/FixedSlotSequence.cpp +++ b/devicehandlers/FixedSlotSequence.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "FixedSlotSequence.h" +#include "../serviceinterface/ServiceInterfaceStream.h" FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) : lengthMs(setLengthMs) { diff --git a/devicehandlers/FixedSlotSequence.h b/devicehandlers/FixedSlotSequence.h index 32b61f56..be6dc2d1 100644 --- a/devicehandlers/FixedSlotSequence.h +++ b/devicehandlers/FixedSlotSequence.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_DEVICEHANDLERS_FIXEDSLOTSEQUENCE_H_ #define FRAMEWORK_DEVICEHANDLERS_FIXEDSLOTSEQUENCE_H_ -#include -#include +#include "FixedSequenceSlot.h" +#include "../objectmanager/SystemObject.h" #include /** diff --git a/devicehandlers/HealthDevice.cpp b/devicehandlers/HealthDevice.cpp index 61a82421..411731dc 100644 --- a/devicehandlers/HealthDevice.cpp +++ b/devicehandlers/HealthDevice.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "HealthDevice.h" +#include "../ipc/QueueFactory.h" HealthDevice::HealthDevice(object_id_t setObjectId, MessageQueueId_t parentQueue) : diff --git a/devicehandlers/HealthDevice.h b/devicehandlers/HealthDevice.h index ffb9e5bd..53b0ab09 100644 --- a/devicehandlers/HealthDevice.h +++ b/devicehandlers/HealthDevice.h @@ -1,11 +1,11 @@ #ifndef HEALTHDEVICE_H_ #define HEALTHDEVICE_H_ -#include -#include -#include -#include -#include +#include "../health/HasHealthIF.h" +#include "../health/HealthHelper.h" +#include "../objectmanager/SystemObject.h" +#include "../tasks/ExecutableObjectIF.h" +#include "../ipc/MessageQueueIF.h" class HealthDevice: public SystemObject, public ExecutableObjectIF, diff --git a/events/Event.cpp b/events/Event.cpp index 9ea9f552..ea3d46fe 100644 --- a/events/Event.cpp +++ b/events/Event.cpp @@ -1,4 +1,4 @@ -#include +#include "Event.h" namespace EVENT { EventId_t getEventId(Event event) { return (event & 0xFFFF); diff --git a/events/Event.h b/events/Event.h index 96800f34..e22c9db1 100644 --- a/events/Event.h +++ b/events/Event.h @@ -2,7 +2,7 @@ #define EVENTOBJECT_EVENT_H_ #include -#include +#include "fwSubsystemIdRanges.h" //could be move to more suitable location #include diff --git a/events/EventManager.cpp b/events/EventManager.cpp index 0f1511e4..fb4499b2 100644 --- a/events/EventManager.cpp +++ b/events/EventManager.cpp @@ -1,8 +1,8 @@ -#include -#include -#include -#include -#include +#include "EventManager.h" +#include "EventMessage.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../ipc/QueueFactory.h" +#include "../ipc/MutexFactory.h" const uint16_t EventManager::POOL_SIZES[N_POOLS] = { diff --git a/events/EventManager.h b/events/EventManager.h index 76dde9f8..7badc3bf 100644 --- a/events/EventManager.h +++ b/events/EventManager.h @@ -1,13 +1,13 @@ #ifndef EVENTMANAGER_H_ #define EVENTMANAGER_H_ -#include -#include -#include -#include -#include -#include -#include +#include "eventmatching/EventMatchTree.h" +#include "EventManagerIF.h" +#include "../objectmanager/SystemObject.h" +#include "../storagemanager/LocalPool.h" +#include "../tasks/ExecutableObjectIF.h" +#include "../ipc/MessageQueueIF.h" +#include "../ipc/MutexIF.h" #include class EventManager: public EventManagerIF, diff --git a/events/EventManagerIF.h b/events/EventManagerIF.h index bc0de432..f9ac420b 100644 --- a/events/EventManagerIF.h +++ b/events/EventManagerIF.h @@ -1,10 +1,10 @@ #ifndef EVENTMANAGERIF_H_ #define EVENTMANAGERIF_H_ -#include -#include -#include -#include +#include "eventmatching/eventmatching.h" +#include "EventMessage.h" +#include "../objectmanager/ObjectManagerIF.h" +#include "../ipc/MessageQueueSenderIF.h" class EventManagerIF { public: diff --git a/events/EventMessage.cpp b/events/EventMessage.cpp index f06f68c3..b911abab 100644 --- a/events/EventMessage.cpp +++ b/events/EventMessage.cpp @@ -1,4 +1,4 @@ -#include +#include "EventMessage.h" #include EventMessage::EventMessage() { diff --git a/events/EventMessage.h b/events/EventMessage.h index 9cbe3336..4d003bd7 100644 --- a/events/EventMessage.h +++ b/events/EventMessage.h @@ -1,9 +1,9 @@ #ifndef EVENTMESSAGE_H_ #define EVENTMESSAGE_H_ -#include -#include -#include +#include "Event.h" +#include "../ipc/MessageQueueMessage.h" +#include "../objectmanager/ObjectManagerIF.h" /** * Passing on events through IPC. diff --git a/events/EventReportingProxyIF.h b/events/EventReportingProxyIF.h index 8aca4e26..7a96e3d1 100644 --- a/events/EventReportingProxyIF.h +++ b/events/EventReportingProxyIF.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_EVENTS_EVENTREPORTINGPROXYIF_H_ #define FRAMEWORK_EVENTS_EVENTREPORTINGPROXYIF_H_ -#include +#include "Event.h" class EventReportingProxyIF { diff --git a/events/eventmatching/EventIdRangeMatcher.cpp b/events/eventmatching/EventIdRangeMatcher.cpp index ac9156fd..974567d4 100644 --- a/events/eventmatching/EventIdRangeMatcher.cpp +++ b/events/eventmatching/EventIdRangeMatcher.cpp @@ -1,4 +1,4 @@ -#include +#include "EventIdRangeMatcher.h" EventIdRangeMatcher::EventIdRangeMatcher(EventId_t lower, EventId_t upper, bool inverted) : EventRangeMatcherBase(lower, upper, inverted) { diff --git a/events/eventmatching/EventIdRangeMatcher.h b/events/eventmatching/EventIdRangeMatcher.h index 57b77cb1..540d372f 100644 --- a/events/eventmatching/EventIdRangeMatcher.h +++ b/events/eventmatching/EventIdRangeMatcher.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_EVENTS_EVENTMATCHING_EVENTIDRANGEMATCHER_H_ #define FRAMEWORK_EVENTS_EVENTMATCHING_EVENTIDRANGEMATCHER_H_ -#include +#include "EventRangeMatcherBase.h" class EventIdRangeMatcher: public EventRangeMatcherBase { public: diff --git a/events/eventmatching/EventMatchTree.cpp b/events/eventmatching/EventMatchTree.cpp index e1925b8f..55e4083f 100644 --- a/events/eventmatching/EventMatchTree.cpp +++ b/events/eventmatching/EventMatchTree.cpp @@ -1,7 +1,7 @@ -#include -#include -#include -#include +#include "EventIdRangeMatcher.h" +#include "EventMatchTree.h" +#include "ReporterRangeMatcher.h" +#include "SeverityRangeMatcher.h" EventMatchTree::EventMatchTree(StorageManagerIF* storageBackend, bool invertedMatch) : diff --git a/events/eventmatching/EventMatchTree.h b/events/eventmatching/EventMatchTree.h index bd81e3be..82a6de81 100644 --- a/events/eventmatching/EventMatchTree.h +++ b/events/eventmatching/EventMatchTree.h @@ -1,10 +1,10 @@ #ifndef FRAMEWORK_EVENTS_EVENTMATCHING_EVENTMATCHTREE_H_ #define FRAMEWORK_EVENTS_EVENTMATCHING_EVENTMATCHTREE_H_ -#include -#include -#include -#include +#include "../../container/PlacementFactory.h" +#include "../../events/EventMessage.h" +#include "../../globalfunctions/matching/MatchTree.h" +#include "../../returnvalues/HasReturnvaluesIF.h" class StorageManagerIF; class EventMatchTree: public MatchTree, public HasReturnvaluesIF { diff --git a/events/eventmatching/EventRangeMatcherBase.h b/events/eventmatching/EventRangeMatcherBase.h index 587669ba..e9d57f1c 100644 --- a/events/eventmatching/EventRangeMatcherBase.h +++ b/events/eventmatching/EventRangeMatcherBase.h @@ -1,9 +1,9 @@ #ifndef FRAMEWORK_EVENTS_EVENTMATCHING_EVENTRANGEMATCHERBASE_H_ #define FRAMEWORK_EVENTS_EVENTMATCHING_EVENTRANGEMATCHERBASE_H_ -#include -#include -#include +#include "../../events/EventMessage.h" +#include "../../globalfunctions/matching/RangeMatcher.h" +#include "../../globalfunctions/matching/SerializeableMatcherIF.h" template class EventRangeMatcherBase: public SerializeableMatcherIF { diff --git a/events/eventmatching/ReporterRangeMatcher.cpp b/events/eventmatching/ReporterRangeMatcher.cpp index 76b8e788..61179726 100644 --- a/events/eventmatching/ReporterRangeMatcher.cpp +++ b/events/eventmatching/ReporterRangeMatcher.cpp @@ -1,4 +1,4 @@ -#include +#include "ReporterRangeMatcher.h" ReporterRangeMatcher::ReporterRangeMatcher(object_id_t lower, object_id_t upper, bool inverted) : EventRangeMatcherBase(lower, upper, inverted) { diff --git a/events/eventmatching/ReporterRangeMatcher.h b/events/eventmatching/ReporterRangeMatcher.h index 65be2365..9a0a5fcf 100644 --- a/events/eventmatching/ReporterRangeMatcher.h +++ b/events/eventmatching/ReporterRangeMatcher.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_EVENTS_EVENTMATCHING_REPORTERRANGEMATCHER_H_ #define FRAMEWORK_EVENTS_EVENTMATCHING_REPORTERRANGEMATCHER_H_ -#include +#include "EventRangeMatcherBase.h" class ReporterRangeMatcher: public EventRangeMatcherBase { public: diff --git a/events/eventmatching/SeverityRangeMatcher.cpp b/events/eventmatching/SeverityRangeMatcher.cpp index 98f8d7e1..6fd38271 100644 --- a/events/eventmatching/SeverityRangeMatcher.cpp +++ b/events/eventmatching/SeverityRangeMatcher.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "SeverityRangeMatcher.h" +#include "../../events/EventMessage.h" +#include "../../serialize/SerializeAdapter.h" SeverityRangeMatcher::SeverityRangeMatcher(EventSeverity_t from, EventSeverity_t till, bool inverted) : EventRangeMatcherBase(from, till, inverted) { diff --git a/events/eventmatching/SeverityRangeMatcher.h b/events/eventmatching/SeverityRangeMatcher.h index ffacff81..3f7cc418 100644 --- a/events/eventmatching/SeverityRangeMatcher.h +++ b/events/eventmatching/SeverityRangeMatcher.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_EVENTS_EVENTMATCHING_SEVERITYRANGEMATCHER_H_ #define FRAMEWORK_EVENTS_EVENTMATCHING_SEVERITYRANGEMATCHER_H_ -#include +#include "EventRangeMatcherBase.h" class SeverityRangeMatcher: public EventRangeMatcherBase { public: diff --git a/events/eventmatching/eventmatching.h b/events/eventmatching/eventmatching.h index 435c7457..7a87e177 100644 --- a/events/eventmatching/eventmatching.h +++ b/events/eventmatching/eventmatching.h @@ -1,10 +1,10 @@ #ifndef EVENTMATCHING_H_ #define EVENTMATCHING_H_ -#include -#include -#include -#include +#include "EventIdRangeMatcher.h" +#include "EventMatchTree.h" +#include "ReporterRangeMatcher.h" +#include "SeverityRangeMatcher.h" #endif /* EVENTMATCHING_H_ */ diff --git a/fdir/ConfirmsFailuresIF.h b/fdir/ConfirmsFailuresIF.h index 99cd212a..14411461 100644 --- a/fdir/ConfirmsFailuresIF.h +++ b/fdir/ConfirmsFailuresIF.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_FDIR_CONFIRMSFAILURESIF_H_ #define FRAMEWORK_FDIR_CONFIRMSFAILURESIF_H_ -#include -#include +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../ipc/MessageQueueSenderIF.h" class ConfirmsFailuresIF { public: diff --git a/fdir/EventCorrelation.cpp b/fdir/EventCorrelation.cpp index 32aa3cd3..d60fc6ca 100644 --- a/fdir/EventCorrelation.cpp +++ b/fdir/EventCorrelation.cpp @@ -1,4 +1,4 @@ -#include +#include "EventCorrelation.h" EventCorrelation::EventCorrelation(uint32_t timeout) : eventPending(false) { diff --git a/fdir/EventCorrelation.h b/fdir/EventCorrelation.h index 0cad6265..b8793edf 100644 --- a/fdir/EventCorrelation.h +++ b/fdir/EventCorrelation.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_FDIR_EVENTCORRELATION_H_ #define FRAMEWORK_FDIR_EVENTCORRELATION_H_ -#include +#include "../timemanager/Countdown.h" class EventCorrelation { public: diff --git a/fdir/FailureIsolationBase.cpp b/fdir/FailureIsolationBase.cpp index 4b7caac5..eb7b1bfc 100644 --- a/fdir/FailureIsolationBase.cpp +++ b/fdir/FailureIsolationBase.cpp @@ -1,9 +1,9 @@ -#include -#include -#include -#include -#include -#include +#include "../events/EventManagerIF.h" +#include "FailureIsolationBase.h" +#include "../health/HasHealthIF.h" +#include "../health/HealthMessage.h" +#include "../ipc/QueueFactory.h" +#include "../objectmanager/ObjectManagerIF.h" FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent, uint8_t messageDepth, uint8_t parameterDomainBase) : eventQueue(NULL), ownerId( diff --git a/fdir/FailureIsolationBase.h b/fdir/FailureIsolationBase.h index cd582e39..6f38bc9f 100644 --- a/fdir/FailureIsolationBase.h +++ b/fdir/FailureIsolationBase.h @@ -1,13 +1,13 @@ #ifndef FRAMEWORK_FDIR_FAILUREISOLATIONBASE_H_ #define FRAMEWORK_FDIR_FAILUREISOLATIONBASE_H_ -#include -#include -#include -#include -#include -#include -#include +#include "../events/EventMessage.h" +#include "ConfirmsFailuresIF.h" +#include "FaultCounter.h" +#include "../health/HealthMessage.h" +#include "../parameters/HasParametersIF.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../ipc/MessageQueueIF.h" class FailureIsolationBase: public HasReturnvaluesIF, public ConfirmsFailuresIF, diff --git a/fdir/FaultCounter.cpp b/fdir/FaultCounter.cpp index 3dc899c2..443adb52 100644 --- a/fdir/FaultCounter.cpp +++ b/fdir/FaultCounter.cpp @@ -1,4 +1,4 @@ -#include +#include "FaultCounter.h" FaultCounter::FaultCounter(uint32_t failureThreshold, uint32_t decrementAfterMs, uint8_t setParameterDomain) : diff --git a/fdir/FaultCounter.h b/fdir/FaultCounter.h index ac23853c..dc929deb 100644 --- a/fdir/FaultCounter.h +++ b/fdir/FaultCounter.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_FDIR_FAULTCOUNTER_H_ #define FRAMEWORK_FDIR_FAULTCOUNTER_H_ -#include -#include +#include "../parameters/HasParametersIF.h" +#include "../timemanager/Countdown.h" class FaultCounter: public HasParametersIF { public: diff --git a/globalfunctions/AsciiConverter.cpp b/globalfunctions/AsciiConverter.cpp index 1459a241..9eb3698f 100644 --- a/globalfunctions/AsciiConverter.cpp +++ b/globalfunctions/AsciiConverter.cpp @@ -1,4 +1,4 @@ -#include +#include "AsciiConverter.h" #include #include diff --git a/globalfunctions/AsciiConverter.h b/globalfunctions/AsciiConverter.h index acd406da..7af3cb3d 100644 --- a/globalfunctions/AsciiConverter.h +++ b/globalfunctions/AsciiConverter.h @@ -1,7 +1,7 @@ #ifndef ASCIICONVERTER_H_ #define ASCIICONVERTER_H_ -#include +#include "../returnvalues/HasReturnvaluesIF.h" class AsciiConverter: public HasReturnvaluesIF { public: diff --git a/globalfunctions/CRC.cpp b/globalfunctions/CRC.cpp index ecd0b675..7bb56806 100644 --- a/globalfunctions/CRC.cpp +++ b/globalfunctions/CRC.cpp @@ -1,4 +1,4 @@ -#include +#include "CRC.h" #include const uint16_t CRC::crc16ccitt_table[256] = { diff --git a/globalfunctions/DleEncoder.cpp b/globalfunctions/DleEncoder.cpp index a68f1524..088c9d80 100644 --- a/globalfunctions/DleEncoder.cpp +++ b/globalfunctions/DleEncoder.cpp @@ -1,4 +1,4 @@ -#include +#include "DleEncoder.h" DleEncoder::DleEncoder() { } diff --git a/globalfunctions/DleEncoder.h b/globalfunctions/DleEncoder.h index fc155600..ff3a2727 100644 --- a/globalfunctions/DleEncoder.h +++ b/globalfunctions/DleEncoder.h @@ -1,7 +1,7 @@ #ifndef DLEENCODER_H_ #define DLEENCODER_H_ -#include +#include "../returnvalues/HasReturnvaluesIF.h" class DleEncoder: public HasReturnvaluesIF { private: diff --git a/globalfunctions/Type.cpp b/globalfunctions/Type.cpp index a481f768..ae595b81 100644 --- a/globalfunctions/Type.cpp +++ b/globalfunctions/Type.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "../serialize/SerializeAdapter.h" +#include "Type.h" +#include "../serialize/SerializeAdapter.h" Type::Type() : actualType(UNKNOWN_TYPE) { diff --git a/globalfunctions/Type.h b/globalfunctions/Type.h index 3ec250b0..be499ffc 100644 --- a/globalfunctions/Type.h +++ b/globalfunctions/Type.h @@ -1,8 +1,8 @@ #ifndef TYPE_H_ #define TYPE_H_ -#include -#include +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../serialize/SerializeIF.h" class Type: public SerializeIF { public: diff --git a/globalfunctions/arrayprinter.cpp b/globalfunctions/arrayprinter.cpp index e8fce56c..b1e888c5 100644 --- a/globalfunctions/arrayprinter.cpp +++ b/globalfunctions/arrayprinter.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "arrayprinter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" #include void arrayprinter::print(const uint8_t *data, size_t size, OutputType type, diff --git a/globalfunctions/matching/BinaryMatcher.h b/globalfunctions/matching/BinaryMatcher.h index df7325cf..4f6db85d 100644 --- a/globalfunctions/matching/BinaryMatcher.h +++ b/globalfunctions/matching/BinaryMatcher.h @@ -1,7 +1,7 @@ #ifndef BINARYMATCHER_H_ #define BINARYMATCHER_H_ -#include +#include "MatcherIF.h" template class BinaryMatcher: public MatcherIF { diff --git a/globalfunctions/matching/DecimalMatcher.h b/globalfunctions/matching/DecimalMatcher.h index f4722e6b..53505020 100644 --- a/globalfunctions/matching/DecimalMatcher.h +++ b/globalfunctions/matching/DecimalMatcher.h @@ -1,7 +1,7 @@ #ifndef DECIMALMATCHER_H_ #define DECIMALMATCHER_H_ -#include +#include "MatcherIF.h" template class DecimalMatcher: public MatcherIF { diff --git a/globalfunctions/matching/MatchTree.h b/globalfunctions/matching/MatchTree.h index b54f5492..755687b2 100644 --- a/globalfunctions/matching/MatchTree.h +++ b/globalfunctions/matching/MatchTree.h @@ -1,9 +1,9 @@ #ifndef FRAMEWORK_GLOBALFUNCTIONS_MATCHING_MATCHTREE_H_ #define FRAMEWORK_GLOBALFUNCTIONS_MATCHING_MATCHTREE_H_ -#include -#include -#include +#include "../../container/BinaryTree.h" +#include "SerializeableMatcherIF.h" +#include "../../serialize/SerializeAdapter.h" template class MatchTree: public SerializeableMatcherIF, public BinaryTree< diff --git a/globalfunctions/matching/RangeMatcher.h b/globalfunctions/matching/RangeMatcher.h index 6fee1f52..b64b9e30 100644 --- a/globalfunctions/matching/RangeMatcher.h +++ b/globalfunctions/matching/RangeMatcher.h @@ -1,8 +1,8 @@ #ifndef RANGEMATCHER_H_ #define RANGEMATCHER_H_ -#include -#include +#include "SerializeableMatcherIF.h" +#include "../../serialize/SerializeAdapter.h" template class RangeMatcher: public SerializeableMatcherIF { diff --git a/globalfunctions/matching/SerializeableMatcherIF.h b/globalfunctions/matching/SerializeableMatcherIF.h index 7b00a1b3..067b0251 100644 --- a/globalfunctions/matching/SerializeableMatcherIF.h +++ b/globalfunctions/matching/SerializeableMatcherIF.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_GLOBALFUNCTIONS_MATCHING_SERIALIZEABLEMATCHERIF_H_ #define FRAMEWORK_GLOBALFUNCTIONS_MATCHING_SERIALIZEABLEMATCHERIF_H_ -#include -#include +#include "MatcherIF.h" +#include "../../serialize/SerializeIF.h" template class SerializeableMatcherIF : public MatcherIF, public SerializeIF { diff --git a/globalfunctions/math/QuaternionOperations.cpp b/globalfunctions/math/QuaternionOperations.cpp index f8c75149..c09426da 100644 --- a/globalfunctions/math/QuaternionOperations.cpp +++ b/globalfunctions/math/QuaternionOperations.cpp @@ -1,5 +1,5 @@ #include "QuaternionOperations.h" -#include +#include "VectorOperations.h" #include #include diff --git a/globalfunctions/timevalOperations.cpp b/globalfunctions/timevalOperations.cpp index 253b6eb7..6efe75ba 100644 --- a/globalfunctions/timevalOperations.cpp +++ b/globalfunctions/timevalOperations.cpp @@ -1,4 +1,4 @@ -#include +#include "timevalOperations.h" timeval& operator+=(timeval& lhs, const timeval& rhs) { int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; diff --git a/health/HasHealthIF.h b/health/HasHealthIF.h index dd27fe39..ac404300 100644 --- a/health/HasHealthIF.h +++ b/health/HasHealthIF.h @@ -1,9 +1,9 @@ #ifndef HASHEALTHIF_H_ #define HASHEALTHIF_H_ -#include -#include -#include +#include "../events/Event.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../ipc/MessageQueueSenderIF.h" class HasHealthIF { public: diff --git a/health/HealthHelper.cpp b/health/HealthHelper.cpp index 7b8b3a53..1cc7d858 100644 --- a/health/HealthHelper.cpp +++ b/health/HealthHelper.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "HealthHelper.h" +#include "../ipc/MessageQueueSenderIF.h" +#include "../serviceinterface/ServiceInterfaceStream.h" HealthHelper::HealthHelper(HasHealthIF* owner, object_id_t objectId) : healthTable(NULL), eventSender(NULL), objectId(objectId), parentQueue( 0), owner(owner) { diff --git a/health/HealthHelper.h b/health/HealthHelper.h index 471bc7e9..90155ad4 100644 --- a/health/HealthHelper.h +++ b/health/HealthHelper.h @@ -1,13 +1,13 @@ #ifndef HEALTHHELPER_H_ #define HEALTHHELPER_H_ -#include -#include -#include -#include -#include -#include -#include +#include "../events/EventManagerIF.h" +#include "../events/EventReportingProxyIF.h" +#include "HasHealthIF.h" +#include "HealthMessage.h" +#include "HealthTableIF.h" +#include "../objectmanager/ObjectManagerIF.h" +#include "../returnvalues/HasReturnvaluesIF.h" /** * Helper class for Objects that implement HasHealthIF diff --git a/health/HealthMessage.cpp b/health/HealthMessage.cpp index 768dea46..1bb29526 100644 --- a/health/HealthMessage.cpp +++ b/health/HealthMessage.cpp @@ -1,4 +1,4 @@ -#include +#include "HealthMessage.h" void HealthMessage::setHealthMessage(CommandMessage* message, Command_t command, HasHealthIF::HealthState health, HasHealthIF::HealthState oldHealth) { diff --git a/health/HealthMessage.h b/health/HealthMessage.h index 7fd00904..95bd9d45 100644 --- a/health/HealthMessage.h +++ b/health/HealthMessage.h @@ -1,8 +1,8 @@ #ifndef HEALTHMESSAGE_H_ #define HEALTHMESSAGE_H_ -#include -#include +#include "HasHealthIF.h" +#include "../ipc/CommandMessage.h" class HealthMessage { public: diff --git a/health/HealthTable.cpp b/health/HealthTable.cpp index bd6606db..846152f6 100644 --- a/health/HealthTable.cpp +++ b/health/HealthTable.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "HealthTable.h" +#include "../serialize/SerializeAdapter.h" +#include "../ipc/MutexFactory.h" HealthTable::HealthTable(object_id_t objectid) : SystemObject(objectid) { diff --git a/health/HealthTable.h b/health/HealthTable.h index 2c74bda4..6f5dd18d 100644 --- a/health/HealthTable.h +++ b/health/HealthTable.h @@ -1,9 +1,9 @@ #ifndef HEALTHTABLE_H_ #define HEALTHTABLE_H_ -#include -#include -#include +#include "HealthTableIF.h" +#include "../objectmanager/SystemObject.h" +#include "../ipc/MutexIF.h" #include typedef std::map HealthMap; diff --git a/health/HealthTableIF.h b/health/HealthTableIF.h index a850a804..404c03e4 100644 --- a/health/HealthTableIF.h +++ b/health/HealthTableIF.h @@ -1,9 +1,9 @@ #ifndef HEALTHTABLEIF_H_ #define HEALTHTABLEIF_H_ -#include -#include -#include +#include "ManagesHealthIF.h" +#include "../objectmanager/ObjectManagerIF.h" +#include "../returnvalues/HasReturnvaluesIF.h" #include diff --git a/health/ManagesHealthIF.h b/health/ManagesHealthIF.h index ff0c5386..42d4c4f0 100644 --- a/health/ManagesHealthIF.h +++ b/health/ManagesHealthIF.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_HEALTH_MANAGESHEALTHIF_H_ #define FRAMEWORK_HEALTH_MANAGESHEALTHIF_H_ -#include -#include +#include "HasHealthIF.h" +#include "../objectmanager/ObjectManagerIF.h" class ManagesHealthIF { public: virtual ~ManagesHealthIF() { diff --git a/internalError/InternalErrorReporter.cpp b/internalError/InternalErrorReporter.cpp index 9a8ede00..b468ca5e 100644 --- a/internalError/InternalErrorReporter.cpp +++ b/internalError/InternalErrorReporter.cpp @@ -1,10 +1,10 @@ #include "InternalErrorReporter.h" -#include -#include -#include +#include "../datapool/DataSet.h" +#include "../datapool/PoolVariable.h" +#include "../ipc/MutexFactory.h" -#include +#include "../serviceinterface/ServiceInterfaceStream.h" InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t queuePoolId, uint32_t tmPoolId, uint32_t storePoolId) : diff --git a/internalError/InternalErrorReporter.h b/internalError/InternalErrorReporter.h index 7c1df6a7..9aa24a0f 100644 --- a/internalError/InternalErrorReporter.h +++ b/internalError/InternalErrorReporter.h @@ -3,9 +3,9 @@ #include "InternalErrorReporterIF.h" -#include -#include -#include +#include "../tasks/ExecutableObjectIF.h" +#include "../objectmanager/SystemObject.h" +#include "../ipc/MutexIF.h" class InternalErrorReporter: public SystemObject, public ExecutableObjectIF, diff --git a/ipc/CommandMessage.cpp b/ipc/CommandMessage.cpp index 05896cbc..8c5e15b8 100644 --- a/ipc/CommandMessage.cpp +++ b/ipc/CommandMessage.cpp @@ -5,15 +5,15 @@ * @author baetz */ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "../devicehandlers/DeviceHandlerMessage.h" +#include "../health/HealthMessage.h" +#include "CommandMessage.h" +#include "../memory/MemoryMessage.h" +#include "../modes/ModeMessage.h" +#include "../monitoring/MonitoringMessage.h" +#include "../subsystem/modes/ModeSequenceMessage.h" +#include "../tmstorage/TmStoreMessage.h" +#include "../parameters/ParameterMessage.h" namespace MESSAGE_TYPE { void clearMissionMessage(CommandMessage* message); diff --git a/ipc/CommandMessage.h b/ipc/CommandMessage.h index 897632fe..87244c11 100644 --- a/ipc/CommandMessage.h +++ b/ipc/CommandMessage.h @@ -9,10 +9,10 @@ #define COMMANDMESSAGE_H_ -#include +#include "FwMessageTypes.h" #include -#include +#include "MessageQueueMessage.h" #define MAKE_COMMAND_ID( number ) ((MESSAGE_ID << 8) + (number)) typedef ReturnValue_t Command_t; diff --git a/ipc/MessageQueueIF.h b/ipc/MessageQueueIF.h index 18e2d99a..9fff5287 100644 --- a/ipc/MessageQueueIF.h +++ b/ipc/MessageQueueIF.h @@ -3,9 +3,9 @@ // COULDDO: We could support blocking calls -#include -#include -#include +#include "MessageQueueMessage.h" +#include "MessageQueueSenderIF.h" +#include "../returnvalues/HasReturnvaluesIF.h" class MessageQueueIF { public: diff --git a/ipc/MessageQueueMessage.cpp b/ipc/MessageQueueMessage.cpp index 30e0325c..05dde1f5 100644 --- a/ipc/MessageQueueMessage.cpp +++ b/ipc/MessageQueueMessage.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "MessageQueueMessage.h" +#include "../serviceinterface/ServiceInterfaceStream.h" #include diff --git a/ipc/MessageQueueMessage.h b/ipc/MessageQueueMessage.h index 8c4ec947..aa3559d6 100644 --- a/ipc/MessageQueueMessage.h +++ b/ipc/MessageQueueMessage.h @@ -1,7 +1,7 @@ #ifndef MESSAGEQUEUEMESSAGE_H_ #define MESSAGEQUEUEMESSAGE_H_ -#include +#include "MessageQueueSenderIF.h" #include /** diff --git a/ipc/MessageQueueSenderIF.h b/ipc/MessageQueueSenderIF.h index 9e7e11c0..d9692f54 100644 --- a/ipc/MessageQueueSenderIF.h +++ b/ipc/MessageQueueSenderIF.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ #define FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ -#include +#include "../objectmanager/ObjectManagerIF.h" class MessageQueueMessage; diff --git a/ipc/MutexFactory.h b/ipc/MutexFactory.h index b2e58b6e..f8133d81 100644 --- a/ipc/MutexFactory.h +++ b/ipc/MutexFactory.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_IPC_MUTEXFACTORY_H_ #define FRAMEWORK_IPC_MUTEXFACTORY_H_ -#include +#include "MutexIF.h" /** * Creates Mutex. * This class is a "singleton" interface, i.e. it provides an diff --git a/ipc/MutexHelper.h b/ipc/MutexHelper.h index f76ccec4..dffcd54e 100644 --- a/ipc/MutexHelper.h +++ b/ipc/MutexHelper.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_IPC_MUTEXHELPER_H_ #define FRAMEWORK_IPC_MUTEXHELPER_H_ -#include -#include +#include "MutexFactory.h" +#include "../serviceinterface/ServiceInterfaceStream.h" class MutexHelper { public: diff --git a/ipc/MutexIF.h b/ipc/MutexIF.h index 35786d6a..851d50a1 100644 --- a/ipc/MutexIF.h +++ b/ipc/MutexIF.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_IPC_MUTEXIF_H_ #define FRAMEWORK_IPC_MUTEXIF_H_ -#include +#include "../returnvalues/HasReturnvaluesIF.h" class MutexIF { public: diff --git a/ipc/QueueFactory.h b/ipc/QueueFactory.h index 6e7c4a26..4f4d72c7 100644 --- a/ipc/QueueFactory.h +++ b/ipc/QueueFactory.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_IPC_QUEUEFACTORY_H_ #define FRAMEWORK_IPC_QUEUEFACTORY_H_ -#include +#include "MessageQueueIF.h" #include /** * Creates message queues. diff --git a/memory/AcceptsMemoryMessagesIF.h b/memory/AcceptsMemoryMessagesIF.h index 2b37f1af..a1cbddf8 100644 --- a/memory/AcceptsMemoryMessagesIF.h +++ b/memory/AcceptsMemoryMessagesIF.h @@ -8,9 +8,9 @@ #ifndef ACCEPTSMEMORYMESSAGESIF_H_ #define ACCEPTSMEMORYMESSAGESIF_H_ -#include -#include -#include +#include "HasMemoryIF.h" +#include "MemoryMessage.h" +#include "../ipc/MessageQueueSenderIF.h" class AcceptsMemoryMessagesIF : public HasMemoryIF { public: diff --git a/memory/HasMemoryIF.h b/memory/HasMemoryIF.h index cd6e6665..4096d1b7 100644 --- a/memory/HasMemoryIF.h +++ b/memory/HasMemoryIF.h @@ -1,7 +1,7 @@ #ifndef HASMEMORYIF_H_ #define HASMEMORYIF_H_ -#include +#include "../returnvalues/HasReturnvaluesIF.h" class HasMemoryIF { public: diff --git a/memory/MemoryHelper.cpp b/memory/MemoryHelper.cpp index af56f2b8..48a605be 100644 --- a/memory/MemoryHelper.cpp +++ b/memory/MemoryHelper.cpp @@ -1,9 +1,9 @@ -#include -#include -#include -#include -#include -#include +#include "../globalfunctions/CRC.h" +#include "MemoryHelper.h" +#include "MemoryMessage.h" +#include "../objectmanager/ObjectManagerIF.h" +#include "../serialize/EndianConverter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" MemoryHelper::MemoryHelper(HasMemoryIF* workOnThis, MessageQueueIF* useThisQueue) : workOnThis(workOnThis), queueToUse(useThisQueue), ipcStore(NULL), ipcAddress(), lastCommand( diff --git a/memory/MemoryHelper.h b/memory/MemoryHelper.h index 2ff82eb3..5e1a99b6 100644 --- a/memory/MemoryHelper.h +++ b/memory/MemoryHelper.h @@ -1,10 +1,10 @@ #ifndef MEMORYHELPER_H_ #define MEMORYHELPER_H_ -#include -#include -#include -#include -#include +#include "../ipc/CommandMessage.h" +#include "AcceptsMemoryMessagesIF.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../storagemanager/StorageManagerIF.h" +#include "../ipc/MessageQueueIF.h" class MemoryHelper : public HasReturnvaluesIF { public: diff --git a/memory/MemoryMessage.cpp b/memory/MemoryMessage.cpp index c1116e08..741565fc 100644 --- a/memory/MemoryMessage.cpp +++ b/memory/MemoryMessage.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "MemoryMessage.h" +#include "../objectmanager/ObjectManagerIF.h" MemoryMessage::MemoryMessage() { } diff --git a/memory/MemoryMessage.h b/memory/MemoryMessage.h index 124fad08..f723bbb6 100644 --- a/memory/MemoryMessage.h +++ b/memory/MemoryMessage.h @@ -1,8 +1,8 @@ #ifndef MEMORYMESSAGE_H_ #define MEMORYMESSAGE_H_ -#include -#include +#include "../ipc/CommandMessage.h" +#include "../storagemanager/StorageManagerIF.h" class MemoryMessage { diff --git a/memory/MemoryProxyIF.h b/memory/MemoryProxyIF.h index d325ba4e..1494d523 100644 --- a/memory/MemoryProxyIF.h +++ b/memory/MemoryProxyIF.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_MEMORY_MEMORYPROXYIF_H_ #define FRAMEWORK_MEMORY_MEMORYPROXYIF_H_ -#include +#include "AcceptsMemoryMessagesIF.h" /** * This was a nice idea to transparently forward incoming messages to another object. diff --git a/modes/HasModesIF.h b/modes/HasModesIF.h index 263b0a87..4381046c 100644 --- a/modes/HasModesIF.h +++ b/modes/HasModesIF.h @@ -8,10 +8,10 @@ #ifndef HASMODESIF_H_ #define HASMODESIF_H_ -#include -#include -#include -#include +#include "../events/Event.h" +#include "ModeHelper.h" +#include "ModeMessage.h" +#include "../returnvalues/HasReturnvaluesIF.h" #include diff --git a/modes/ModeHelper.cpp b/modes/ModeHelper.cpp index 7b98bdc6..cb62c468 100644 --- a/modes/ModeHelper.cpp +++ b/modes/ModeHelper.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "HasModesIF.h" +#include "ModeHelper.h" +#include "../ipc/MessageQueueSenderIF.h" ModeHelper::ModeHelper(HasModesIF *owner) : theOneWhoCommandedAMode(0), commandedMode(HasModesIF::MODE_OFF), commandedSubmode( diff --git a/modes/ModeHelper.h b/modes/ModeHelper.h index 87f6d411..542fe780 100644 --- a/modes/ModeHelper.h +++ b/modes/ModeHelper.h @@ -1,9 +1,9 @@ #ifndef MODEHELPER_H_ #define MODEHELPER_H_ -#include -#include -#include +#include "ModeMessage.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../timemanager/Countdown.h" class HasModesIF; diff --git a/modes/ModeMessage.cpp b/modes/ModeMessage.cpp index 1d3baad5..14dbbb31 100644 --- a/modes/ModeMessage.cpp +++ b/modes/ModeMessage.cpp @@ -1,4 +1,4 @@ -#include +#include "ModeMessage.h" Mode_t ModeMessage::getMode(const CommandMessage* message) { return message->getParameter(); diff --git a/modes/ModeMessage.h b/modes/ModeMessage.h index f72fdeec..5fd82512 100644 --- a/modes/ModeMessage.h +++ b/modes/ModeMessage.h @@ -8,7 +8,7 @@ #ifndef MODEMESSAGE_H_ #define MODEMESSAGE_H_ -#include +#include "../ipc/CommandMessage.h" typedef uint32_t Mode_t; typedef uint8_t Submode_t; diff --git a/monitoring/AbsLimitMonitor.h b/monitoring/AbsLimitMonitor.h index 3525ba2c..2e60f6f8 100644 --- a/monitoring/AbsLimitMonitor.h +++ b/monitoring/AbsLimitMonitor.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_MONITORING_ABSLIMITMONITOR_H_ #define FRAMEWORK_MONITORING_ABSLIMITMONITOR_H_ -#include +#include "MonitorBase.h" #include template diff --git a/monitoring/HasMonitorsIF.h b/monitoring/HasMonitorsIF.h index 6f1dc1b3..85d92b6b 100644 --- a/monitoring/HasMonitorsIF.h +++ b/monitoring/HasMonitorsIF.h @@ -7,9 +7,9 @@ #ifndef HASMONITORSIF_H_ #define HASMONITORSIF_H_ -#include -#include -#include +#include "../events/EventReportingProxyIF.h" +#include "../objectmanager/ObjectManagerIF.h" +#include "../ipc/MessageQueueSenderIF.h" class HasMonitorsIF { public: diff --git a/monitoring/LimitMonitor.h b/monitoring/LimitMonitor.h index 45abe48b..66e6725e 100644 --- a/monitoring/LimitMonitor.h +++ b/monitoring/LimitMonitor.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_MONITORING_LIMITMONITOR_H_ #define FRAMEWORK_MONITORING_LIMITMONITOR_H_ -#include +#include "MonitorBase.h" /** * Variant of a limit checking class. diff --git a/monitoring/LimitViolationReporter.cpp b/monitoring/LimitViolationReporter.cpp index 489a8f9e..c531a6e6 100644 --- a/monitoring/LimitViolationReporter.cpp +++ b/monitoring/LimitViolationReporter.cpp @@ -4,11 +4,11 @@ * @date 17.07.2014 * @author baetz */ -#include -#include -#include -#include -#include +#include "LimitViolationReporter.h" +#include "MonitoringIF.h" +#include "ReceivesMonitoringReportsIF.h" +#include "../objectmanager/ObjectManagerIF.h" +#include "../serialize/SerializeAdapter.h" ReturnValue_t LimitViolationReporter::sendLimitViolationReport(const SerializeIF* data) { ReturnValue_t result = checkClassLoaded(); diff --git a/monitoring/LimitViolationReporter.h b/monitoring/LimitViolationReporter.h index 3a9d04dd..a71b972f 100644 --- a/monitoring/LimitViolationReporter.h +++ b/monitoring/LimitViolationReporter.h @@ -7,10 +7,10 @@ #ifndef LIMITVIOLATIONREPORTER_H_ #define LIMITVIOLATIONREPORTER_H_ -#include -#include -#include -#include +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../serialize/SerializeIF.h" +#include "../storagemanager/StorageManagerIF.h" +#include "../ipc/MessageQueueSenderIF.h" namespace Factory{ void setStaticFrameworkObjectIds(); diff --git a/monitoring/MonitorBase.h b/monitoring/MonitorBase.h index 79622645..b2d0e6cb 100644 --- a/monitoring/MonitorBase.h +++ b/monitoring/MonitorBase.h @@ -1,12 +1,12 @@ #ifndef MONITORBASE_H_ #define MONITORBASE_H_ -#include -#include -#include -#include -#include -#include +#include "../datapool/DataSet.h" +#include "../datapool/PIDReader.h" +#include "LimitViolationReporter.h" +#include "MonitoringIF.h" +#include "MonitoringMessageContent.h" +#include "MonitorReporter.h" /** * Base class for monitoring of parameters. diff --git a/monitoring/MonitorReporter.h b/monitoring/MonitorReporter.h index 6274313f..ca2b534b 100644 --- a/monitoring/MonitorReporter.h +++ b/monitoring/MonitorReporter.h @@ -1,11 +1,11 @@ #ifndef FRAMEWORK_MONITORING_MONITORREPORTER_H_ #define FRAMEWORK_MONITORING_MONITORREPORTER_H_ -#include -#include -#include -#include -#include +#include "../events/EventManagerIF.h" +#include "LimitViolationReporter.h" +#include "MonitoringIF.h" +#include "MonitoringMessageContent.h" +#include "../parameters/HasParametersIF.h" template class MonitorReporter: public HasParametersIF { diff --git a/monitoring/MonitoringIF.h b/monitoring/MonitoringIF.h index d2d62f35..44218c36 100644 --- a/monitoring/MonitoringIF.h +++ b/monitoring/MonitoringIF.h @@ -1,9 +1,9 @@ #ifndef MONITORINGIF_H_ #define MONITORINGIF_H_ -#include -#include -#include +#include "../memory/HasMemoryIF.h" +#include "MonitoringMessage.h" +#include "../serialize/SerializeIF.h" class MonitoringIF : public SerializeIF { public: diff --git a/monitoring/MonitoringMessage.cpp b/monitoring/MonitoringMessage.cpp index 77919bfe..8caa27ae 100644 --- a/monitoring/MonitoringMessage.cpp +++ b/monitoring/MonitoringMessage.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "MonitoringMessage.h" +#include "../objectmanager/ObjectManagerIF.h" MonitoringMessage::~MonitoringMessage() { } diff --git a/monitoring/MonitoringMessage.h b/monitoring/MonitoringMessage.h index d2ff9b4d..248cd6ff 100644 --- a/monitoring/MonitoringMessage.h +++ b/monitoring/MonitoringMessage.h @@ -1,8 +1,8 @@ #ifndef MONITORINGMESSAGE_H_ #define MONITORINGMESSAGE_H_ -#include -#include +#include "../ipc/CommandMessage.h" +#include "../storagemanager/StorageManagerIF.h" class MonitoringMessage: public CommandMessage { public: diff --git a/monitoring/MonitoringMessageContent.h b/monitoring/MonitoringMessageContent.h index 7e1aca62..c82506f3 100644 --- a/monitoring/MonitoringMessageContent.h +++ b/monitoring/MonitoringMessageContent.h @@ -1,15 +1,15 @@ #ifndef MONITORINGMESSAGECONTENT_H_ #define MONITORINGMESSAGECONTENT_H_ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "HasMonitorsIF.h" +#include "MonitoringIF.h" +#include "../objectmanager/ObjectManagerIF.h" +#include "../serialize/SerialBufferAdapter.h" +#include "../serialize/SerialFixedArrayListAdapter.h" +#include "../serialize/SerializeElement.h" +#include "../serialize/SerialLinkedListAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../timemanager/TimeStamperIF.h" namespace Factory{ void setStaticFrameworkObjectIds(); diff --git a/monitoring/ReceivesMonitoringReportsIF.h b/monitoring/ReceivesMonitoringReportsIF.h index 42c365c1..fb37c16c 100644 --- a/monitoring/ReceivesMonitoringReportsIF.h +++ b/monitoring/ReceivesMonitoringReportsIF.h @@ -1,7 +1,7 @@ #ifndef RECEIVESMONITORINGREPORTSIF_H_ #define RECEIVESMONITORINGREPORTSIF_H_ -#include +#include "../ipc/MessageQueueSenderIF.h" class ReceivesMonitoringReportsIF { public: diff --git a/monitoring/TriplexMonitor.h b/monitoring/TriplexMonitor.h index 9a2e69c3..9b60aeb6 100644 --- a/monitoring/TriplexMonitor.h +++ b/monitoring/TriplexMonitor.h @@ -1,11 +1,11 @@ #ifndef FRAMEWORK_MONITORING_TRIPLEXMONITOR_H_ #define FRAMEWORK_MONITORING_TRIPLEXMONITOR_H_ -#include -#include -#include -#include -#include +#include "../datapool/DataSet.h" +#include "../datapool/PIDReaderList.h" +#include "../health/HealthTableIF.h" +#include "../parameters/HasParametersIF.h" +#include "../objectmanager/ObjectManagerIF.h" //SHOULDDO: This is by far not perfect. Could be merged with new Monitor classes. But still, it's over-engineering. diff --git a/monitoring/TwoValueLimitMonitor.h b/monitoring/TwoValueLimitMonitor.h index c17ad433..e690cdae 100644 --- a/monitoring/TwoValueLimitMonitor.h +++ b/monitoring/TwoValueLimitMonitor.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_MONITORING_TWOVALUELIMITMONITOR_H_ #define FRAMEWORK_MONITORING_TWOVALUELIMITMONITOR_H_ -#include +#include "LimitMonitor.h" template class TwoValueLimitMonitor: public LimitMonitor { diff --git a/objectmanager/ObjectManager.cpp b/objectmanager/ObjectManager.cpp index 1c54355a..dd0ae188 100644 --- a/objectmanager/ObjectManager.cpp +++ b/objectmanager/ObjectManager.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "ObjectManager.h" +#include "../serviceinterface/ServiceInterfaceStream.h" #include #include diff --git a/objectmanager/ObjectManager.h b/objectmanager/ObjectManager.h index 63451071..0d2b3c4a 100644 --- a/objectmanager/ObjectManager.h +++ b/objectmanager/ObjectManager.h @@ -8,8 +8,8 @@ #ifndef OBJECTMANAGER_H_ #define OBJECTMANAGER_H_ -#include -#include +#include "ObjectManagerIF.h" +#include "SystemObjectIF.h" #include /** diff --git a/objectmanager/ObjectManagerIF.h b/objectmanager/ObjectManagerIF.h index dcef81cd..e0162af9 100644 --- a/objectmanager/ObjectManagerIF.h +++ b/objectmanager/ObjectManagerIF.h @@ -1,10 +1,10 @@ #ifndef FRAMEWORK_OBJECTMANAGER_OBJECTMANAGERIF_H_ #define FRAMEWORK_OBJECTMANAGER_OBJECTMANAGERIF_H_ -#include -#include -#include -#include +#include "frameworkObjects.h" +#include "SystemObjectIF.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../serviceinterface/ServiceInterfaceStream.h" /** * @brief This class provides an interface to the global object manager. diff --git a/objectmanager/SystemObject.cpp b/objectmanager/SystemObject.cpp index 85daaa35..53aac599 100644 --- a/objectmanager/SystemObject.cpp +++ b/objectmanager/SystemObject.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "../events/EventManagerIF.h" +#include "ObjectManager.h" +#include "SystemObject.h" SystemObject::SystemObject(object_id_t setObjectId, bool doRegister) : objectId(setObjectId), registered(doRegister) { diff --git a/objectmanager/SystemObject.h b/objectmanager/SystemObject.h index 6a1b35b6..8e9f20d5 100644 --- a/objectmanager/SystemObject.h +++ b/objectmanager/SystemObject.h @@ -8,10 +8,10 @@ #ifndef SYSTEMOBJECT_H_ #define SYSTEMOBJECT_H_ -#include -#include -#include -#include +#include "../events/Event.h" +#include "../events/EventReportingProxyIF.h" +#include "SystemObjectIF.h" +#include "../timemanager/Clock.h" /** * @brief This class automates insertion into the ObjectManager and diff --git a/objectmanager/SystemObjectIF.h b/objectmanager/SystemObjectIF.h index 7540f80f..c5a92196 100644 --- a/objectmanager/SystemObjectIF.h +++ b/objectmanager/SystemObjectIF.h @@ -8,8 +8,8 @@ #ifndef SYSTEMOBJECTIF_H_ #define SYSTEMOBJECTIF_H_ -#include -#include +#include "../events/EventReportingProxyIF.h" +#include "../returnvalues/HasReturnvaluesIF.h" #include /** * \defgroup system_objects Software System Object Management diff --git a/osal/FreeRTOS/Clock.cpp b/osal/FreeRTOS/Clock.cpp index dce20265..9733c405 100644 --- a/osal/FreeRTOS/Clock.cpp +++ b/osal/FreeRTOS/Clock.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "../../timemanager/Clock.h" +#include "../../globalfunctions/timevalOperations.h" +#include "Timekeeper.h" #include #include diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index 17804d90..902502f9 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -1,6 +1,6 @@ #include "FixedTimeslotTask.h" -#include +#include "../../serviceinterface/ServiceInterfaceStream.h" uint32_t FixedTimeslotTask::deadlineMissedCount = 0; const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE; diff --git a/osal/FreeRTOS/FixedTimeslotTask.h b/osal/FreeRTOS/FixedTimeslotTask.h index 66af0311..d65f1fe4 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.h +++ b/osal/FreeRTOS/FixedTimeslotTask.h @@ -1,9 +1,9 @@ #ifndef FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ #define FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ -#include -#include -#include +#include "../../devicehandlers/FixedSlotSequence.h" +#include "../../tasks/FixedTimeslotTaskIF.h" +#include "../../tasks/Typedef.h" #include #include diff --git a/osal/FreeRTOS/MessageQueue.cpp b/osal/FreeRTOS/MessageQueue.cpp index 18e7aa3d..3bbd4d9d 100644 --- a/osal/FreeRTOS/MessageQueue.cpp +++ b/osal/FreeRTOS/MessageQueue.cpp @@ -1,6 +1,6 @@ #include "MessageQueue.h" -#include +#include "../../serviceinterface/ServiceInterfaceStream.h" // TODO I guess we should have a way of checking if we are in an ISR and then use the "fromISR" versions of all calls diff --git a/osal/FreeRTOS/MessageQueue.h b/osal/FreeRTOS/MessageQueue.h index 32f41b44..aa3d54c1 100644 --- a/osal/FreeRTOS/MessageQueue.h +++ b/osal/FreeRTOS/MessageQueue.h @@ -1,9 +1,9 @@ #ifndef MESSAGEQUEUE_H_ #define MESSAGEQUEUE_H_ -#include -#include -#include +#include "../../internalError/InternalErrorReporterIF.h" +#include "../../ipc/MessageQueueIF.h" +#include "../../ipc/MessageQueueMessage.h" #include #include diff --git a/osal/FreeRTOS/Mutex.cpp b/osal/FreeRTOS/Mutex.cpp index 7c511091..6da58783 100644 --- a/osal/FreeRTOS/Mutex.cpp +++ b/osal/FreeRTOS/Mutex.cpp @@ -1,6 +1,6 @@ #include "Mutex.h" -#include +#include "../../serviceinterface/ServiceInterfaceStream.h" const uint32_t MutexIF::NO_TIMEOUT = 0; diff --git a/osal/FreeRTOS/Mutex.h b/osal/FreeRTOS/Mutex.h index 91f29585..d376b7bc 100644 --- a/osal/FreeRTOS/Mutex.h +++ b/osal/FreeRTOS/Mutex.h @@ -1,7 +1,7 @@ #ifndef OS_RTEMS_MUTEX_H_ #define OS_RTEMS_MUTEX_H_ -#include +#include "../../ipc/MutexIF.h" #include diff --git a/osal/FreeRTOS/MutexFactory.cpp b/osal/FreeRTOS/MutexFactory.cpp index cadb54fb..75b63d07 100644 --- a/osal/FreeRTOS/MutexFactory.cpp +++ b/osal/FreeRTOS/MutexFactory.cpp @@ -1,4 +1,4 @@ -#include +#include "../../ipc/MutexFactory.h" #include "../FreeRTOS/Mutex.h" diff --git a/osal/FreeRTOS/PeriodicTask.cpp b/osal/FreeRTOS/PeriodicTask.cpp index 91135375..a95333b4 100644 --- a/osal/FreeRTOS/PeriodicTask.cpp +++ b/osal/FreeRTOS/PeriodicTask.cpp @@ -1,7 +1,7 @@ #include "PeriodicTask.h" -#include -#include +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../tasks/ExecutableObjectIF.h" PeriodicTask::PeriodicTask(const char *name, TaskPriority setPriority, TaskStackSize setStack, TaskPeriod setPeriod, diff --git a/osal/FreeRTOS/PeriodicTask.h b/osal/FreeRTOS/PeriodicTask.h index 09aa6bc7..3eb8f57e 100644 --- a/osal/FreeRTOS/PeriodicTask.h +++ b/osal/FreeRTOS/PeriodicTask.h @@ -1,9 +1,9 @@ #ifndef FRAMEWORK_OSAL_FREERTOS_PERIODICTASK_H_ #define FRAMEWORK_OSAL_FREERTOS_PERIODICTASK_H_ -#include -#include -#include +#include "../../objectmanager/ObjectManagerIF.h" +#include "../../tasks/PeriodicTaskIF.h" +#include "../../tasks/Typedef.h" #include #include diff --git a/osal/FreeRTOS/QueueFactory.cpp b/osal/FreeRTOS/QueueFactory.cpp index a0128918..e639179a 100644 --- a/osal/FreeRTOS/QueueFactory.cpp +++ b/osal/FreeRTOS/QueueFactory.cpp @@ -1,6 +1,6 @@ -#include +#include "../../ipc/QueueFactory.h" -#include +#include "MessageQueue.h" QueueFactory* QueueFactory::factoryInstance = NULL; diff --git a/osal/FreeRTOS/TaskFactory.cpp b/osal/FreeRTOS/TaskFactory.cpp index 753da60f..80df38b2 100644 --- a/osal/FreeRTOS/TaskFactory.cpp +++ b/osal/FreeRTOS/TaskFactory.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "../../tasks/TaskFactory.h" +#include "../../returnvalues/HasReturnvaluesIF.h" #include "PeriodicTask.h" #include "FixedTimeslotTask.h" diff --git a/osal/FreeRTOS/Timekeeper.cpp b/osal/FreeRTOS/Timekeeper.cpp index 643b2747..1031f0c4 100644 --- a/osal/FreeRTOS/Timekeeper.cpp +++ b/osal/FreeRTOS/Timekeeper.cpp @@ -1,4 +1,4 @@ -#include +#include "Timekeeper.h" #include "FreeRTOSConfig.h" diff --git a/osal/FreeRTOS/Timekeeper.h b/osal/FreeRTOS/Timekeeper.h index 7d3ca22b..7d583f7d 100644 --- a/osal/FreeRTOS/Timekeeper.h +++ b/osal/FreeRTOS/Timekeeper.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_OSAL_FREERTOS_TIMEKEEPER_H_ #define FRAMEWORK_OSAL_FREERTOS_TIMEKEEPER_H_ -#include +#include "../../timemanager/Clock.h" #include #include diff --git a/osal/InternalErrorCodes.h b/osal/InternalErrorCodes.h index 5419fd94..1da116fa 100644 --- a/osal/InternalErrorCodes.h +++ b/osal/InternalErrorCodes.h @@ -1,7 +1,7 @@ #ifndef INTERNALERRORCODES_H_ #define INTERNALERRORCODES_H_ -#include +#include "../returnvalues/HasReturnvaluesIF.h" class InternalErrorCodes { public: diff --git a/osal/linux/Clock.cpp b/osal/linux/Clock.cpp index 630b2cf4..48e325ef 100644 --- a/osal/linux/Clock.cpp +++ b/osal/linux/Clock.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../timemanager/Clock.h" #include #include diff --git a/osal/linux/FixedTimeslotTask.cpp b/osal/linux/FixedTimeslotTask.cpp index e5c68f9d..858a39a7 100644 --- a/osal/linux/FixedTimeslotTask.cpp +++ b/osal/linux/FixedTimeslotTask.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "FixedTimeslotTask.h" #include diff --git a/osal/linux/FixedTimeslotTask.h b/osal/linux/FixedTimeslotTask.h index 916e6d6c..42802b1d 100644 --- a/osal/linux/FixedTimeslotTask.h +++ b/osal/linux/FixedTimeslotTask.h @@ -1,9 +1,9 @@ #ifndef FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ #define FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ -#include -#include -#include +#include "../../tasks/FixedTimeslotTaskIF.h" +#include "../../devicehandlers/FixedSlotSequence.h" +#include "PosixThread.h" #include class FixedTimeslotTask: public FixedTimeslotTaskIF, public PosixThread { diff --git a/osal/linux/InternalErrorCodes.cpp b/osal/linux/InternalErrorCodes.cpp index 7f83663b..a01cc72a 100644 --- a/osal/linux/InternalErrorCodes.cpp +++ b/osal/linux/InternalErrorCodes.cpp @@ -1,4 +1,4 @@ -#include +#include "../../osal/InternalErrorCodes.h" ReturnValue_t InternalErrorCodes::translate(uint8_t code) { //TODO This class can be removed diff --git a/osal/linux/MessageQueue.cpp b/osal/linux/MessageQueue.cpp index a0749ded..e5c61cae 100644 --- a/osal/linux/MessageQueue.cpp +++ b/osal/linux/MessageQueue.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "MessageQueue.h" #include diff --git a/osal/linux/MessageQueue.h b/osal/linux/MessageQueue.h index 2808d36e..31cdca11 100644 --- a/osal/linux/MessageQueue.h +++ b/osal/linux/MessageQueue.h @@ -1,9 +1,9 @@ #ifndef MESSAGEQUEUE_H_ #define MESSAGEQUEUE_H_ -#include -#include -#include +#include "../../internalError/InternalErrorReporterIF.h" +#include "../../ipc/MessageQueueIF.h" +#include "../../ipc/MessageQueueMessage.h" #include /** diff --git a/osal/linux/Mutex.cpp b/osal/linux/Mutex.cpp index 36bb3ce4..dd8d3c5b 100644 --- a/osal/linux/Mutex.cpp +++ b/osal/linux/Mutex.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "Mutex.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../timemanager/Clock.h" const uint32_t MutexIF::NO_TIMEOUT = 0; uint8_t Mutex::count = 0; diff --git a/osal/linux/Mutex.h b/osal/linux/Mutex.h index d02d008f..9f9bf521 100644 --- a/osal/linux/Mutex.h +++ b/osal/linux/Mutex.h @@ -1,7 +1,7 @@ #ifndef OS_RTEMS_MUTEX_H_ #define OS_RTEMS_MUTEX_H_ -#include +#include "../../ipc/MutexIF.h" #include class Mutex : public MutexIF { diff --git a/osal/linux/MutexFactory.cpp b/osal/linux/MutexFactory.cpp index d769cc33..8c2faf88 100644 --- a/osal/linux/MutexFactory.cpp +++ b/osal/linux/MutexFactory.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "../../ipc/MutexFactory.h" +#include "Mutex.h" //TODO: Different variant than the lazy loading in QueueFactory. What's better and why? MutexFactory* MutexFactory::factoryInstance = new MutexFactory(); diff --git a/osal/linux/PeriodicPosixTask.cpp b/osal/linux/PeriodicPosixTask.cpp index 6149c84b..c08bb472 100644 --- a/osal/linux/PeriodicPosixTask.cpp +++ b/osal/linux/PeriodicPosixTask.cpp @@ -1,7 +1,7 @@ -#include -#include +#include "../../tasks/ExecutableObjectIF.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" #include -#include +#include "PeriodicPosixTask.h" PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, uint32_t period_, void(deadlineMissedFunc_)()): diff --git a/osal/linux/PeriodicPosixTask.h b/osal/linux/PeriodicPosixTask.h index bf1a995b..6737cee6 100644 --- a/osal/linux/PeriodicPosixTask.h +++ b/osal/linux/PeriodicPosixTask.h @@ -1,10 +1,10 @@ #ifndef FRAMEWORK_OSAL_LINUX_PERIODICPOSIXTASK_H_ #define FRAMEWORK_OSAL_LINUX_PERIODICPOSIXTASK_H_ -#include -#include -#include -#include +#include "../../tasks/PeriodicTaskIF.h" +#include "../../objectmanager/ObjectManagerIF.h" +#include "PosixThread.h" +#include "../../tasks/ExecutableObjectIF.h" #include class PeriodicPosixTask: public PosixThread, public PeriodicTaskIF { diff --git a/osal/linux/PosixThread.cpp b/osal/linux/PosixThread.cpp index bc3e62ed..ddb1f74f 100644 --- a/osal/linux/PosixThread.cpp +++ b/osal/linux/PosixThread.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "PosixThread.h" #include #include diff --git a/osal/linux/PosixThread.h b/osal/linux/PosixThread.h index e9d31728..7d8d349a 100644 --- a/osal/linux/PosixThread.h +++ b/osal/linux/PosixThread.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_OSAL_LINUX_POSIXTHREAD_H_ #define FRAMEWORK_OSAL_LINUX_POSIXTHREAD_H_ -#include +#include "../../returnvalues/HasReturnvaluesIF.h" #include #include #include diff --git a/osal/linux/QueueFactory.cpp b/osal/linux/QueueFactory.cpp index 268d0b99..afeca547 100644 --- a/osal/linux/QueueFactory.cpp +++ b/osal/linux/QueueFactory.cpp @@ -1,8 +1,8 @@ -#include +#include "../../ipc/QueueFactory.h" #include #include -#include -#include +#include "MessageQueue.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" #include QueueFactory* QueueFactory::factoryInstance = nullptr; diff --git a/osal/linux/TaskFactory.cpp b/osal/linux/TaskFactory.cpp index 219630a7..f507c767 100644 --- a/osal/linux/TaskFactory.cpp +++ b/osal/linux/TaskFactory.cpp @@ -1,7 +1,7 @@ -#include -#include -#include -#include +#include "FixedTimeslotTask.h" +#include "PeriodicPosixTask.h" +#include "../../tasks/TaskFactory.h" +#include "../../returnvalues/HasReturnvaluesIF.h" //TODO: Different variant than the lazy loading in QueueFactory. What's better and why? TaskFactory* TaskFactory::factoryInstance = new TaskFactory(); diff --git a/osal/linux/Timer.cpp b/osal/linux/Timer.cpp index 5e27c328..ee964baa 100644 --- a/osal/linux/Timer.cpp +++ b/osal/linux/Timer.cpp @@ -1,6 +1,6 @@ -#include +#include "../../serviceinterface/ServiceInterfaceStream.h" #include -#include +#include "Timer.h" Timer::Timer() { sigevent sigEvent; diff --git a/osal/rtems/Clock.cpp b/osal/rtems/Clock.cpp index 98198dd3..eeffd7f3 100644 --- a/osal/rtems/Clock.cpp +++ b/osal/rtems/Clock.cpp @@ -1,4 +1,4 @@ -#include +#include "../../timemanager/Clock.h" #include "RtemsBasic.h" #include diff --git a/osal/rtems/CpuUsage.cpp b/osal/rtems/CpuUsage.cpp index 61b66c3d..d49de4ad 100644 --- a/osal/rtems/CpuUsage.cpp +++ b/osal/rtems/CpuUsage.cpp @@ -1,6 +1,6 @@ #include "CpuUsage.h" -#include -#include +#include "../../serialize/SerialArrayListAdapter.h" +#include "../../serialize/SerializeAdapter.h" #include extern "C" { diff --git a/osal/rtems/CpuUsage.h b/osal/rtems/CpuUsage.h index eb03c5e3..f487e191 100644 --- a/osal/rtems/CpuUsage.h +++ b/osal/rtems/CpuUsage.h @@ -1,8 +1,8 @@ #ifndef CPUUSAGE_H_ #define CPUUSAGE_H_ -#include -#include +#include "../../container/FixedArrayList.h" +#include "../../serialize/SerializeIF.h" #include class CpuUsage : public SerializeIF { diff --git a/osal/rtems/InternalErrorCodes.cpp b/osal/rtems/InternalErrorCodes.cpp index dbe3172e..9346cf15 100644 --- a/osal/rtems/InternalErrorCodes.cpp +++ b/osal/rtems/InternalErrorCodes.cpp @@ -1,4 +1,4 @@ -#include +#include "../../osal/InternalErrorCodes.h" #include ReturnValue_t InternalErrorCodes::translate(uint8_t code) { diff --git a/osal/rtems/Interrupt.h b/osal/rtems/Interrupt.h index c4c21911..2152e2f0 100644 --- a/osal/rtems/Interrupt.h +++ b/osal/rtems/Interrupt.h @@ -1,7 +1,7 @@ #ifndef OS_RTEMS_INTERRUPT_H_ #define OS_RTEMS_INTERRUPT_H_ -#include +#include "../../returnvalues/HasReturnvaluesIF.h" #include #include diff --git a/osal/rtems/MessageQueue.cpp b/osal/rtems/MessageQueue.cpp index de148fdc..700db444 100644 --- a/osal/rtems/MessageQueue.cpp +++ b/osal/rtems/MessageQueue.cpp @@ -1,4 +1,4 @@ -#include +#include "../../serviceinterface/ServiceInterfaceStream.h" #include "MessageQueue.h" #include "RtemsBasic.h" #include diff --git a/osal/rtems/MessageQueue.h b/osal/rtems/MessageQueue.h index 9bdce7ca..c6fc62d5 100644 --- a/osal/rtems/MessageQueue.h +++ b/osal/rtems/MessageQueue.h @@ -10,9 +10,9 @@ #ifndef MESSAGEQUEUE_H_ #define MESSAGEQUEUE_H_ -#include -#include -#include +#include "../../internalError/InternalErrorReporterIF.h" +#include "../../ipc/MessageQueueIF.h" +#include "../../ipc/MessageQueueMessage.h" #include "RtemsBasic.h" /** diff --git a/osal/rtems/MultiObjectTask.cpp b/osal/rtems/MultiObjectTask.cpp index bb8c2c81..3c4886a5 100644 --- a/osal/rtems/MultiObjectTask.cpp +++ b/osal/rtems/MultiObjectTask.cpp @@ -5,8 +5,8 @@ * @author baetz */ -#include -#include +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../tasks/ExecutableObjectIF.h" #include "MultiObjectTask.h" MultiObjectTask::MultiObjectTask(const char *name, rtems_task_priority setPriority, diff --git a/osal/rtems/MultiObjectTask.h b/osal/rtems/MultiObjectTask.h index 64b09c52..28d05fb1 100644 --- a/osal/rtems/MultiObjectTask.h +++ b/osal/rtems/MultiObjectTask.h @@ -7,8 +7,8 @@ #ifndef MULTIOBJECTTASK_H_ #define MULTIOBJECTTASK_H_ -#include -#include +#include "../../objectmanager/ObjectManagerIF.h" +#include "../../tasks/PeriodicTaskIF.h" #include "TaskBase.h" #include diff --git a/osal/rtems/Mutex.cpp b/osal/rtems/Mutex.cpp index d094e1dc..d8babcde 100644 --- a/osal/rtems/Mutex.cpp +++ b/osal/rtems/Mutex.cpp @@ -1,5 +1,5 @@ #include "Mutex.h" -#include +#include "../../serviceinterface/ServiceInterfaceStream.h" const uint32_t MutexIF::NO_TIMEOUT = RTEMS_NO_TIMEOUT; uint8_t Mutex::count = 0; diff --git a/osal/rtems/Mutex.h b/osal/rtems/Mutex.h index 19b34e7f..340bb16b 100644 --- a/osal/rtems/Mutex.h +++ b/osal/rtems/Mutex.h @@ -1,7 +1,7 @@ #ifndef OS_RTEMS_MUTEX_H_ #define OS_RTEMS_MUTEX_H_ -#include +#include "../../ipc/MutexIF.h" #include "RtemsBasic.h" class Mutex : public MutexIF { diff --git a/osal/rtems/MutexFactory.cpp b/osal/rtems/MutexFactory.cpp index d7bd16bc..ea594789 100644 --- a/osal/rtems/MutexFactory.cpp +++ b/osal/rtems/MutexFactory.cpp @@ -1,4 +1,4 @@ -#include +#include "../../ipc/MutexFactory.h" #include "Mutex.h" #include "RtemsBasic.h" diff --git a/osal/rtems/PollingTask.cpp b/osal/rtems/PollingTask.cpp index 03ba0951..04191515 100644 --- a/osal/rtems/PollingTask.cpp +++ b/osal/rtems/PollingTask.cpp @@ -1,9 +1,9 @@ -#include -#include -#include -#include -#include -#include +#include "../../devicehandlers/FixedSequenceSlot.h" +#include "../../objectmanager/SystemObjectIF.h" +#include "PollingTask.h" +#include "RtemsBasic.h" +#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" #include #include #include diff --git a/osal/rtems/PollingTask.h b/osal/rtems/PollingTask.h index 82ec65a2..199c34e7 100644 --- a/osal/rtems/PollingTask.h +++ b/osal/rtems/PollingTask.h @@ -1,8 +1,8 @@ #ifndef POLLINGTASK_H_ #define POLLINGTASK_H_ -#include -#include +#include "../../devicehandlers/FixedSlotSequence.h" +#include "../../tasks/FixedTimeslotTaskIF.h" #include "TaskBase.h" class PollingTask: public TaskBase, public FixedTimeslotTaskIF { diff --git a/osal/rtems/QueueFactory.cpp b/osal/rtems/QueueFactory.cpp index 8cc9905c..fce55a0e 100644 --- a/osal/rtems/QueueFactory.cpp +++ b/osal/rtems/QueueFactory.cpp @@ -1,4 +1,4 @@ -#include +#include "../../ipc/QueueFactory.h" #include "MessageQueue.h" #include "RtemsBasic.h" diff --git a/osal/rtems/RtemsBasic.h b/osal/rtems/RtemsBasic.h index f7ab8614..78e0d46e 100644 --- a/osal/rtems/RtemsBasic.h +++ b/osal/rtems/RtemsBasic.h @@ -1,7 +1,7 @@ #ifndef OS_RTEMS_RTEMSBASIC_H_ #define OS_RTEMS_RTEMSBASIC_H_ -#include +#include "../../returnvalues/HasReturnvaluesIF.h" #include #include #include diff --git a/osal/rtems/TaskBase.cpp b/osal/rtems/TaskBase.cpp index ad795645..adf6ee70 100644 --- a/osal/rtems/TaskBase.cpp +++ b/osal/rtems/TaskBase.cpp @@ -1,4 +1,4 @@ -#include +#include "../../serviceinterface/ServiceInterfaceStream.h" #include "TaskBase.h" const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE=RTEMS_MINIMUM_STACK_SIZE; diff --git a/osal/rtems/TaskBase.h b/osal/rtems/TaskBase.h index b9c1192a..410d9110 100644 --- a/osal/rtems/TaskBase.h +++ b/osal/rtems/TaskBase.h @@ -2,7 +2,7 @@ #define TASKBASE_H_ #include "RtemsBasic.h" -#include +#include "../../tasks/PeriodicTaskIF.h" /** * @brief This is the basic task handling class for rtems. diff --git a/osal/rtems/TaskFactory.cpp b/osal/rtems/TaskFactory.cpp index 2bee19c7..bab48a44 100644 --- a/osal/rtems/TaskFactory.cpp +++ b/osal/rtems/TaskFactory.cpp @@ -1,9 +1,9 @@ -#include +#include "../../tasks/TaskFactory.h" #include "MultiObjectTask.h" #include "PollingTask.h" #include "InitTask.h" #include "RtemsBasic.h" -#include +#include "../../returnvalues/HasReturnvaluesIF.h" //TODO: Different variant than the lazy loading in QueueFactory. What's better and why? TaskFactory* TaskFactory::factoryInstance = new TaskFactory(); diff --git a/parameters/HasParametersIF.h b/parameters/HasParametersIF.h index fbb69445..71212b57 100644 --- a/parameters/HasParametersIF.h +++ b/parameters/HasParametersIF.h @@ -1,8 +1,8 @@ #ifndef HASPARAMETERSIF_H_ #define HASPARAMETERSIF_H_ -#include -#include +#include "ParameterWrapper.h" +#include "../returnvalues/HasReturnvaluesIF.h" #include typedef uint32_t ParameterId_t; diff --git a/parameters/ParameterHelper.cpp b/parameters/ParameterHelper.cpp index f896f00f..8543515f 100644 --- a/parameters/ParameterHelper.cpp +++ b/parameters/ParameterHelper.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "../objectmanager/ObjectManagerIF.h" +#include "ParameterHelper.h" +#include "ParameterMessage.h" ParameterHelper::ParameterHelper(ReceivesParameterMessagesIF* owner) : owner(owner), storage(NULL) { diff --git a/parameters/ParameterHelper.h b/parameters/ParameterHelper.h index e2fefdba..d887bf1d 100644 --- a/parameters/ParameterHelper.h +++ b/parameters/ParameterHelper.h @@ -1,8 +1,8 @@ #ifndef PARAMETERHELPER_H_ #define PARAMETERHELPER_H_ -#include -#include +#include "ParameterMessage.h" +#include "ReceivesParameterMessagesIF.h" class ParameterHelper { public: diff --git a/parameters/ParameterMessage.cpp b/parameters/ParameterMessage.cpp index 1c7d6911..7e0ed114 100644 --- a/parameters/ParameterMessage.cpp +++ b/parameters/ParameterMessage.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "ParameterMessage.h" +#include "../objectmanager/ObjectManagerIF.h" ParameterId_t ParameterMessage::getParameterId(const CommandMessage* message) { return message->getParameter(); diff --git a/parameters/ParameterMessage.h b/parameters/ParameterMessage.h index 0f286675..7cb02d96 100644 --- a/parameters/ParameterMessage.h +++ b/parameters/ParameterMessage.h @@ -1,9 +1,9 @@ #ifndef PARAMETERMESSAGE_H_ #define PARAMETERMESSAGE_H_ -#include -#include -#include +#include "../ipc/CommandMessage.h" +#include "HasParametersIF.h" +#include "../storagemanager/StorageManagerIF.h" class ParameterMessage { private: diff --git a/parameters/ParameterWrapper.cpp b/parameters/ParameterWrapper.cpp index bbf1e8a3..56f56426 100644 --- a/parameters/ParameterWrapper.cpp +++ b/parameters/ParameterWrapper.cpp @@ -1,4 +1,4 @@ -#include +#include "ParameterWrapper.h" ParameterWrapper::ParameterWrapper() : pointsToStream(false), type(Type::UNKNOWN_TYPE), rows(0), columns(0), data( diff --git a/parameters/ParameterWrapper.h b/parameters/ParameterWrapper.h index a00c997c..b18fe2b9 100644 --- a/parameters/ParameterWrapper.h +++ b/parameters/ParameterWrapper.h @@ -1,11 +1,11 @@ #ifndef PARAMETERWRAPPER_H_ #define PARAMETERWRAPPER_H_ -#include -#include -#include +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../serialize/SerializeAdapter.h" +#include "../serialize/SerializeIF.h" #include -#include +#include "../globalfunctions/Type.h" class ParameterWrapper: public SerializeIF { friend class DataPoolParameterWrapper; diff --git a/parameters/ReceivesParameterMessagesIF.h b/parameters/ReceivesParameterMessagesIF.h index 9bcd226d..1fcbd4b3 100644 --- a/parameters/ReceivesParameterMessagesIF.h +++ b/parameters/ReceivesParameterMessagesIF.h @@ -2,8 +2,8 @@ #define RECEIVESPARAMETERMESSAGESIF_H_ -#include -#include +#include "HasParametersIF.h" +#include "../ipc/MessageQueueSenderIF.h" class ReceivesParameterMessagesIF : public HasParametersIF { public: diff --git a/power/Fuse.cpp b/power/Fuse.cpp index db24100b..9986ab6b 100644 --- a/power/Fuse.cpp +++ b/power/Fuse.cpp @@ -1,9 +1,9 @@ -#include -#include -#include -#include -#include -#include +#include "../monitoring/LimitViolationReporter.h" +#include "../monitoring/MonitoringMessageContent.h" +#include "../objectmanager/ObjectManagerIF.h" +#include "Fuse.h" +#include "../serialize/SerialFixedArrayListAdapter.h" +#include "../ipc/QueueFactory.h" object_id_t Fuse::powerSwitchId = 0; diff --git a/power/Fuse.h b/power/Fuse.h index 4e22e3ed..279642be 100644 --- a/power/Fuse.h +++ b/power/Fuse.h @@ -1,14 +1,14 @@ #ifndef FUSE_H_ #define FUSE_H_ -#include -#include -#include -#include -#include -#include -#include -#include +#include "../datapool/DataSet.h" +#include "../datapool/PIDReader.h" +#include "../devicehandlers/HealthDevice.h" +#include "../monitoring/AbsLimitMonitor.h" +#include "PowerComponentIF.h" +#include "PowerSwitchIF.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../parameters/ParameterHelper.h" #include namespace Factory { diff --git a/power/PowerComponent.cpp b/power/PowerComponent.cpp index cd116a86..6012ad4c 100644 --- a/power/PowerComponent.cpp +++ b/power/PowerComponent.cpp @@ -5,7 +5,7 @@ * @author baetz */ -#include +#include "PowerComponent.h" PowerComponent::PowerComponent() : deviceObjectId(0), switchId1(0xFF), switchId2(0xFF), doIHaveTwoSwitches( diff --git a/power/PowerComponent.h b/power/PowerComponent.h index 61ab3674..6d1c9c06 100644 --- a/power/PowerComponent.h +++ b/power/PowerComponent.h @@ -1,8 +1,8 @@ #ifndef POWERCOMPONENT_H_ #define POWERCOMPONENT_H_ -#include -#include +#include "../objectmanager/SystemObjectIF.h" +#include "PowerComponentIF.h" class PowerComponent: public PowerComponentIF { public: diff --git a/power/PowerComponentIF.h b/power/PowerComponentIF.h index f2aa70ae..c2e3a6a5 100644 --- a/power/PowerComponentIF.h +++ b/power/PowerComponentIF.h @@ -1,8 +1,8 @@ #ifndef POWERCOMPONENTIF_H_ #define POWERCOMPONENTIF_H_ -#include -#include +#include "../serialize/SerializeIF.h" +#include "../parameters/HasParametersIF.h" class PowerComponentIF : public SerializeIF, public HasParametersIF { public: diff --git a/power/PowerSensor.cpp b/power/PowerSensor.cpp index 5433acc9..50cb6acd 100644 --- a/power/PowerSensor.cpp +++ b/power/PowerSensor.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "PowerSensor.h" +#include "../ipc/QueueFactory.h" PowerSensor::PowerSensor(object_id_t setId, VariableIds ids, DefaultLimits limits, SensorEvents events, uint16_t confirmationCount) : diff --git a/power/PowerSensor.h b/power/PowerSensor.h index 922560d0..0f973e45 100644 --- a/power/PowerSensor.h +++ b/power/PowerSensor.h @@ -1,14 +1,14 @@ #ifndef POWERSENSOR_H_ #define POWERSENSOR_H_ -#include -#include -#include -#include -#include -#include -#include -#include +#include "../datapool/DataSet.h" +#include "../datapool/PIDReader.h" +#include "../datapool/PoolVariable.h" +#include "../devicehandlers/HealthDevice.h" +#include "../monitoring/LimitMonitor.h" +#include "../parameters/ParameterHelper.h" +#include "../objectmanager/SystemObject.h" +#include "../ipc/MessageQueueIF.h" class PowerController; diff --git a/power/PowerSwitchIF.h b/power/PowerSwitchIF.h index 1c4c06f7..40220fb6 100644 --- a/power/PowerSwitchIF.h +++ b/power/PowerSwitchIF.h @@ -8,8 +8,8 @@ #ifndef POWERSWITCHIF_H_ #define POWERSWITCHIF_H_ -#include -#include +#include "../events/Event.h" +#include "../returnvalues/HasReturnvaluesIF.h" /** * This interface defines a connection to a device that is capable of turning on and off * switches of devices identified by a switch ID. diff --git a/power/PowerSwitcher.cpp b/power/PowerSwitcher.cpp index 6b06bf73..6296a04c 100644 --- a/power/PowerSwitcher.cpp +++ b/power/PowerSwitcher.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "../objectmanager/ObjectManagerIF.h" +#include "PowerSwitcher.h" +#include "../serviceinterface/ServiceInterfaceStream.h" PowerSwitcher::PowerSwitcher(uint8_t setSwitch1, uint8_t setSwitch2, PowerSwitcher::State_t setStartState) : diff --git a/power/PowerSwitcher.h b/power/PowerSwitcher.h index 5b2789e9..0f1c02de 100644 --- a/power/PowerSwitcher.h +++ b/power/PowerSwitcher.h @@ -1,8 +1,8 @@ #ifndef POWERSWITCHER_H_ #define POWERSWITCHER_H_ -#include -#include -#include +#include "PowerSwitchIF.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../timemanager/Countdown.h" class PowerSwitcher : public HasReturnvaluesIF { public: diff --git a/pus/CService200ModeCommanding.cpp b/pus/CService200ModeCommanding.cpp index fd6da67e..32f7e5a7 100644 --- a/pus/CService200ModeCommanding.cpp +++ b/pus/CService200ModeCommanding.cpp @@ -1,119 +1,119 @@ -#include -#include - -#include -#include -#include -#include - -CService200ModeCommanding::CService200ModeCommanding(object_id_t objectId, - uint16_t apid, uint8_t serviceId): - CommandingServiceBase(objectId, apid, serviceId, - NUMBER_OF_PARALLEL_COMMANDS,COMMAND_TIMEOUT_SECONDS) {} - -CService200ModeCommanding::~CService200ModeCommanding() {} - -ReturnValue_t CService200ModeCommanding::isValidSubservice(uint8_t subservice) { - switch(subservice) { - case(Subservice::COMMAND_MODE_COMMAND): - case(Subservice::COMMAND_MODE_READ): - case(Subservice::COMMAND_MODE_ANNCOUNCE): - return RETURN_OK; - default: - return AcceptsTelecommandsIF::INVALID_SUBSERVICE; - } -} - - -ReturnValue_t CService200ModeCommanding::getMessageQueueAndObject( - uint8_t subservice, const uint8_t *tcData, size_t tcDataLen, - MessageQueueId_t *id, object_id_t *objectId) { - if(tcDataLen < sizeof(object_id_t)) { - return CommandingServiceBase::INVALID_TC; - } - SerializeAdapter::deSerialize(objectId, &tcData, &tcDataLen, - SerializeIF::Endianness::BIG); - - return checkInterfaceAndAcquireMessageQueue(id,objectId); -} - -ReturnValue_t CService200ModeCommanding::checkInterfaceAndAcquireMessageQueue( - MessageQueueId_t* messageQueueToSet, object_id_t* objectId) { - HasModesIF * destination = objectManager->get(*objectId); - if(destination == nullptr) { - return CommandingServiceBase::INVALID_OBJECT; - - } - - *messageQueueToSet = destination->getCommandQueue(); - return HasReturnvaluesIF::RETURN_OK; -} - - -ReturnValue_t CService200ModeCommanding::prepareCommand( - CommandMessage* message,uint8_t subservice, const uint8_t *tcData, - size_t tcDataLen, uint32_t *state, object_id_t objectId) { - ModePacket modeCommandPacket; - ReturnValue_t result = modeCommandPacket.deSerialize(&tcData, - &tcDataLen, SerializeIF::Endianness::BIG); - if (result != RETURN_OK) { - return result; - } - - ModeMessage::setModeMessage(dynamic_cast(message), - ModeMessage::CMD_MODE_COMMAND, modeCommandPacket.getMode(), - modeCommandPacket.getSubmode()); - return result; -} - - -ReturnValue_t CService200ModeCommanding::handleReply( - const CommandMessage* reply, Command_t previousCommand, - uint32_t *state, CommandMessage* optionalNextCommand, - object_id_t objectId, bool *isStep) { - Command_t replyId = reply->getCommand(); - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; - switch(replyId) { - case(ModeMessage::REPLY_MODE_REPLY): { - result = prepareModeReply(reply, objectId); - break; - } - case(ModeMessage::REPLY_WRONG_MODE_REPLY): { - result = prepareWrongModeReply(reply, objectId); - break; - } - case(ModeMessage::REPLY_CANT_REACH_MODE): { - result = prepareCantReachModeReply(reply, objectId); - break; - } - case(ModeMessage::REPLY_MODE_INFO): - result = INVALID_REPLY; - break; - default: - result = RETURN_FAILED; - } - return result; -} - -ReturnValue_t CService200ModeCommanding::prepareModeReply( - const CommandMessage *reply, object_id_t objectId) { - ModePacket modeReplyPacket(objectId, - ModeMessage::getMode(reply), - ModeMessage::getSubmode(reply)); - return sendTmPacket(Subservice::REPLY_MODE_REPLY, &modeReplyPacket); -} - -ReturnValue_t CService200ModeCommanding::prepareWrongModeReply( - const CommandMessage *reply, object_id_t objectId) { - ModePacket wrongModeReply(objectId, ModeMessage::getMode(reply), - ModeMessage::getSubmode(reply)); - return sendTmPacket(Subservice::REPLY_WRONG_MODE_REPLY, &wrongModeReply); -} - -ReturnValue_t CService200ModeCommanding::prepareCantReachModeReply( - const CommandMessage *reply, object_id_t objectId) { - CantReachModePacket cantReachModePacket(objectId, - ModeMessage::getCantReachModeReason(reply)); - return sendTmPacket(Subservice::REPLY_CANT_REACH_MODE, - &cantReachModePacket); -} +#include "CService200ModeCommanding.h" +#include "servicepackets/Service200Packets.h" + +#include "../modes/HasModesIF.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../serialize/SerialLinkedListAdapter.h" +#include "../modes/ModeMessage.h" + +CService200ModeCommanding::CService200ModeCommanding(object_id_t objectId, + uint16_t apid, uint8_t serviceId): + CommandingServiceBase(objectId, apid, serviceId, + NUMBER_OF_PARALLEL_COMMANDS,COMMAND_TIMEOUT_SECONDS) {} + +CService200ModeCommanding::~CService200ModeCommanding() {} + +ReturnValue_t CService200ModeCommanding::isValidSubservice(uint8_t subservice) { + switch(subservice) { + case(Subservice::COMMAND_MODE_COMMAND): + case(Subservice::COMMAND_MODE_READ): + case(Subservice::COMMAND_MODE_ANNCOUNCE): + return RETURN_OK; + default: + return AcceptsTelecommandsIF::INVALID_SUBSERVICE; + } +} + + +ReturnValue_t CService200ModeCommanding::getMessageQueueAndObject( + uint8_t subservice, const uint8_t *tcData, size_t tcDataLen, + MessageQueueId_t *id, object_id_t *objectId) { + if(tcDataLen < sizeof(object_id_t)) { + return CommandingServiceBase::INVALID_TC; + } + SerializeAdapter::deSerialize(objectId, &tcData, &tcDataLen, + SerializeIF::Endianness::BIG); + + return checkInterfaceAndAcquireMessageQueue(id,objectId); +} + +ReturnValue_t CService200ModeCommanding::checkInterfaceAndAcquireMessageQueue( + MessageQueueId_t* messageQueueToSet, object_id_t* objectId) { + HasModesIF * destination = objectManager->get(*objectId); + if(destination == nullptr) { + return CommandingServiceBase::INVALID_OBJECT; + + } + + *messageQueueToSet = destination->getCommandQueue(); + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t CService200ModeCommanding::prepareCommand( + CommandMessage* message,uint8_t subservice, const uint8_t *tcData, + size_t tcDataLen, uint32_t *state, object_id_t objectId) { + ModePacket modeCommandPacket; + ReturnValue_t result = modeCommandPacket.deSerialize(&tcData, + &tcDataLen, SerializeIF::Endianness::BIG); + if (result != RETURN_OK) { + return result; + } + + ModeMessage::setModeMessage(dynamic_cast(message), + ModeMessage::CMD_MODE_COMMAND, modeCommandPacket.getMode(), + modeCommandPacket.getSubmode()); + return result; +} + + +ReturnValue_t CService200ModeCommanding::handleReply( + const CommandMessage* reply, Command_t previousCommand, + uint32_t *state, CommandMessage* optionalNextCommand, + object_id_t objectId, bool *isStep) { + Command_t replyId = reply->getCommand(); + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + switch(replyId) { + case(ModeMessage::REPLY_MODE_REPLY): { + result = prepareModeReply(reply, objectId); + break; + } + case(ModeMessage::REPLY_WRONG_MODE_REPLY): { + result = prepareWrongModeReply(reply, objectId); + break; + } + case(ModeMessage::REPLY_CANT_REACH_MODE): { + result = prepareCantReachModeReply(reply, objectId); + break; + } + case(ModeMessage::REPLY_MODE_INFO): + result = INVALID_REPLY; + break; + default: + result = RETURN_FAILED; + } + return result; +} + +ReturnValue_t CService200ModeCommanding::prepareModeReply( + const CommandMessage *reply, object_id_t objectId) { + ModePacket modeReplyPacket(objectId, + ModeMessage::getMode(reply), + ModeMessage::getSubmode(reply)); + return sendTmPacket(Subservice::REPLY_MODE_REPLY, &modeReplyPacket); +} + +ReturnValue_t CService200ModeCommanding::prepareWrongModeReply( + const CommandMessage *reply, object_id_t objectId) { + ModePacket wrongModeReply(objectId, ModeMessage::getMode(reply), + ModeMessage::getSubmode(reply)); + return sendTmPacket(Subservice::REPLY_WRONG_MODE_REPLY, &wrongModeReply); +} + +ReturnValue_t CService200ModeCommanding::prepareCantReachModeReply( + const CommandMessage *reply, object_id_t objectId) { + CantReachModePacket cantReachModePacket(objectId, + ModeMessage::getCantReachModeReason(reply)); + return sendTmPacket(Subservice::REPLY_CANT_REACH_MODE, + &cantReachModePacket); +} diff --git a/pus/CService200ModeCommanding.h b/pus/CService200ModeCommanding.h index ede61a84..89347dbd 100644 --- a/pus/CService200ModeCommanding.h +++ b/pus/CService200ModeCommanding.h @@ -1,85 +1,85 @@ -#ifndef FRAMEWORK_PUS_CSERVICE200MODECOMMANDING_H_ -#define FRAMEWORK_PUS_CSERVICE200MODECOMMANDING_H_ - -#include - -/** - * @brief Custom PUS service to set mode of all objects implementing HasModesIF - * - * Examples: Device Handlers, Assemblies or Subsystems. - * Full Documentation: ECSS-E-ST-70-41C or ECSS-E-70-41A - * Dissertation Baetz p. 115, 116, 165-167. - * - * This is a gateway service. It relays device commands using the software bus. - * @ingroup pus_services - */ -class CService200ModeCommanding: public CommandingServiceBase { -public: - static constexpr uint8_t NUMBER_OF_PARALLEL_COMMANDS = 4; - static constexpr uint16_t COMMAND_TIMEOUT_SECONDS = 60; - - CService200ModeCommanding(object_id_t objectId, - uint16_t apid, uint8_t serviceId); - virtual~ CService200ModeCommanding(); - -protected: - //! CommandingServiceBase (CSB) abstract functions. See CSB documentation. - ReturnValue_t isValidSubservice(uint8_t subservice) override; - ReturnValue_t getMessageQueueAndObject(uint8_t subservice, - const uint8_t *tcData, size_t tcDataLen, MessageQueueId_t *id, - object_id_t *objectId) override; - ReturnValue_t prepareCommand(CommandMessage* message, - uint8_t subservice, const uint8_t *tcData, size_t tcDataLen, - uint32_t *state, object_id_t objectId) override; - ReturnValue_t handleReply(const CommandMessage* reply, - Command_t previousCommand, uint32_t *state, - CommandMessage* optionalNextCommand, object_id_t objectId, - bool *isStep) override; - -private: - ReturnValue_t checkAndAcquireTargetID(object_id_t* objectIdToSet, - const uint8_t* tcData, uint32_t tcDataLen); - ReturnValue_t checkInterfaceAndAcquireMessageQueue( - MessageQueueId_t* MessageQueueToSet, object_id_t* objectId); - - ReturnValue_t prepareModeReply(const CommandMessage *reply, - object_id_t objectId); - ReturnValue_t prepareWrongModeReply(const CommandMessage *reply, - object_id_t objectId); - ReturnValue_t prepareCantReachModeReply(const CommandMessage *reply, - object_id_t objectId); - - enum Subservice { //!< [EXPORT] : [COMMENT] Mode Commanding Subservices - //!< [EXPORT] : [COMMAND] Command assembly, subsystem or device mode - COMMAND_MODE_COMMAND = 1, - //!< [EXPORT] : [COMMAND] Command to set the specified Mode, - //! regardless of external control flag - COMMAND_MODE_COMMAND_FORCED = 2, - //!< [EXPORT] : [COMMAND] Read the current mode and - //! reply with a REPLY_MODE_REPLY - COMMAND_MODE_READ = 3, - //!< [EXPORT] : [COMMAND] Trigger an ModeInfo Event. - //! This command does NOT have a reply - COMMAND_MODE_ANNCOUNCE = 4, - //!< [EXPORT] : [COMMAND] Trigger a ModeInfo Event and to send this - //! command to every child. This command does NOT have a reply. - COMMAND_MODE_ANNOUNCE_RECURSIVELY = 5, - //!< [EXPORT] : [REPLY] Reply to a CMD_MODE_COMMAND or CMD_MODE_READ - REPLY_MODE_REPLY = 6, - //!< [EXPORT] : [REPLY] Reply in case a mode command can't be executed. - REPLY_CANT_REACH_MODE = 7, - //!< [EXPORT] : [REPLY] Reply to a CMD_MODE_COMMAND, indicating that a - //! mode was commanded and a transition started but was aborted, - //! the parameters contain the mode that was reached - REPLY_WRONG_MODE_REPLY = 8 - }; - - enum modeParameters { - MODE_OFF = 0, - MODE_ON = 1, - MODE_NORMAL = 2, - MODE_RAW = 3 - }; -}; - -#endif /* FRAMEWORK_PUS_CSERVICE200MODECOMMANDING_H_ */ +#ifndef FRAMEWORK_PUS_CSERVICE200MODECOMMANDING_H_ +#define FRAMEWORK_PUS_CSERVICE200MODECOMMANDING_H_ + +#include "../tmtcservices/CommandingServiceBase.h" + +/** + * @brief Custom PUS service to set mode of all objects implementing HasModesIF + * + * Examples: Device Handlers, Assemblies or Subsystems. + * Full Documentation: ECSS-E-ST-70-41C or ECSS-E-70-41A + * Dissertation Baetz p. 115, 116, 165-167. + * + * This is a gateway service. It relays device commands using the software bus. + * @ingroup pus_services + */ +class CService200ModeCommanding: public CommandingServiceBase { +public: + static constexpr uint8_t NUMBER_OF_PARALLEL_COMMANDS = 4; + static constexpr uint16_t COMMAND_TIMEOUT_SECONDS = 60; + + CService200ModeCommanding(object_id_t objectId, + uint16_t apid, uint8_t serviceId); + virtual~ CService200ModeCommanding(); + +protected: + //! CommandingServiceBase (CSB) abstract functions. See CSB documentation. + ReturnValue_t isValidSubservice(uint8_t subservice) override; + ReturnValue_t getMessageQueueAndObject(uint8_t subservice, + const uint8_t *tcData, size_t tcDataLen, MessageQueueId_t *id, + object_id_t *objectId) override; + ReturnValue_t prepareCommand(CommandMessage* message, + uint8_t subservice, const uint8_t *tcData, size_t tcDataLen, + uint32_t *state, object_id_t objectId) override; + ReturnValue_t handleReply(const CommandMessage* reply, + Command_t previousCommand, uint32_t *state, + CommandMessage* optionalNextCommand, object_id_t objectId, + bool *isStep) override; + +private: + ReturnValue_t checkAndAcquireTargetID(object_id_t* objectIdToSet, + const uint8_t* tcData, uint32_t tcDataLen); + ReturnValue_t checkInterfaceAndAcquireMessageQueue( + MessageQueueId_t* MessageQueueToSet, object_id_t* objectId); + + ReturnValue_t prepareModeReply(const CommandMessage *reply, + object_id_t objectId); + ReturnValue_t prepareWrongModeReply(const CommandMessage *reply, + object_id_t objectId); + ReturnValue_t prepareCantReachModeReply(const CommandMessage *reply, + object_id_t objectId); + + enum Subservice { //!< [EXPORT] : [COMMENT] Mode Commanding Subservices + //!< [EXPORT] : [COMMAND] Command assembly, subsystem or device mode + COMMAND_MODE_COMMAND = 1, + //!< [EXPORT] : [COMMAND] Command to set the specified Mode, + //! regardless of external control flag + COMMAND_MODE_COMMAND_FORCED = 2, + //!< [EXPORT] : [COMMAND] Read the current mode and + //! reply with a REPLY_MODE_REPLY + COMMAND_MODE_READ = 3, + //!< [EXPORT] : [COMMAND] Trigger an ModeInfo Event. + //! This command does NOT have a reply + COMMAND_MODE_ANNCOUNCE = 4, + //!< [EXPORT] : [COMMAND] Trigger a ModeInfo Event and to send this + //! command to every child. This command does NOT have a reply. + COMMAND_MODE_ANNOUNCE_RECURSIVELY = 5, + //!< [EXPORT] : [REPLY] Reply to a CMD_MODE_COMMAND or CMD_MODE_READ + REPLY_MODE_REPLY = 6, + //!< [EXPORT] : [REPLY] Reply in case a mode command can't be executed. + REPLY_CANT_REACH_MODE = 7, + //!< [EXPORT] : [REPLY] Reply to a CMD_MODE_COMMAND, indicating that a + //! mode was commanded and a transition started but was aborted, + //! the parameters contain the mode that was reached + REPLY_WRONG_MODE_REPLY = 8 + }; + + enum modeParameters { + MODE_OFF = 0, + MODE_ON = 1, + MODE_NORMAL = 2, + MODE_RAW = 3 + }; +}; + +#endif /* FRAMEWORK_PUS_CSERVICE200MODECOMMANDING_H_ */ diff --git a/pus/Service1TelecommandVerification.cpp b/pus/Service1TelecommandVerification.cpp index 4ce2ce54..570005c5 100644 --- a/pus/Service1TelecommandVerification.cpp +++ b/pus/Service1TelecommandVerification.cpp @@ -1,12 +1,12 @@ -#include -#include +#include "Service1TelecommandVerification.h" +#include "servicepackets/Service1Packets.h" -#include -#include -#include -#include -#include -#include +#include "../ipc/QueueFactory.h" +#include "../tmtcservices/PusVerificationReport.h" +#include "/tmtcpacketTmPacketStored.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../tmtcservices/AcceptsTelemetryIF.h" +#include "../serviceinterface/ServiceInterfaceStream.h" Service1TelecommandVerification::Service1TelecommandVerification( diff --git a/pus/Service1TelecommandVerification.h b/pus/Service1TelecommandVerification.h index 1d4b6719..37562d1c 100644 --- a/pus/Service1TelecommandVerification.h +++ b/pus/Service1TelecommandVerification.h @@ -1,12 +1,12 @@ #ifndef MISSION_PUS_SERVICE1TELECOMMANDVERIFICATION_H_ #define MISSION_PUS_SERVICE1TELECOMMANDVERIFICATION_H_ -#include -#include -#include -#include -#include -#include +#include "../objectmanager/SystemObject.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../tasks/ExecutableObjectIF.h" +#include "../tmtcservices/AcceptsVerifyMessageIF.h" +#include "../tmtcservices/PusVerificationReport.h" +#include "../ipc/MessageQueueIF.h" /** * @brief Verify TC acceptance, start, progress and execution. diff --git a/pus/Service2DeviceAccess.cpp b/pus/Service2DeviceAccess.cpp index 1d5f21eb..2093a617 100644 --- a/pus/Service2DeviceAccess.cpp +++ b/pus/Service2DeviceAccess.cpp @@ -1,167 +1,167 @@ -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -Service2DeviceAccess::Service2DeviceAccess(object_id_t objectId, - uint16_t apid, uint8_t serviceId, uint8_t numberOfParallelCommands, - uint16_t commandTimeoutSeconds): - CommandingServiceBase(objectId, apid, serviceId, - numberOfParallelCommands, commandTimeoutSeconds) {} - -Service2DeviceAccess::~Service2DeviceAccess() {} - - -ReturnValue_t Service2DeviceAccess::isValidSubservice(uint8_t subservice) { - switch(static_cast(subservice)){ - case Subservice::RAW_COMMANDING: - case Subservice::TOGGLE_WIRETAPPING: - return HasReturnvaluesIF::RETURN_OK; - default: - sif::error << "Invalid Subservice" << std::endl; - return AcceptsTelecommandsIF::INVALID_SUBSERVICE; - } -} - -ReturnValue_t Service2DeviceAccess::getMessageQueueAndObject( - uint8_t subservice, const uint8_t* tcData, size_t tcDataLen, - MessageQueueId_t* id, object_id_t* objectId) { - if(tcDataLen < sizeof(object_id_t)) { - return CommandingServiceBase::INVALID_TC; - } - SerializeAdapter::deSerialize(objectId, &tcData, - &tcDataLen, SerializeIF::Endianness::BIG); - - ReturnValue_t result = checkInterfaceAndAcquireMessageQueue(id,objectId); - return result; -} - -ReturnValue_t Service2DeviceAccess::checkInterfaceAndAcquireMessageQueue( - MessageQueueId_t * messageQueueToSet, object_id_t *objectId) { - DeviceHandlerIF* possibleTarget = - objectManager->get(*objectId); - if(possibleTarget == nullptr) { - return CommandingServiceBase::INVALID_OBJECT; - } - *messageQueueToSet = possibleTarget->getCommandQueue(); - return HasReturnvaluesIF::RETURN_OK; -} - - -ReturnValue_t Service2DeviceAccess::prepareCommand(CommandMessage* message, - uint8_t subservice, const uint8_t* tcData, size_t tcDataLen, - uint32_t* state, object_id_t objectId) { - switch(static_cast(subservice)){ - case Subservice::RAW_COMMANDING: { - return prepareRawCommand(dynamic_cast(message), - tcData, tcDataLen); - } - break; - case Subservice::TOGGLE_WIRETAPPING: { - return prepareWiretappingCommand(dynamic_cast(message), - tcData, tcDataLen); - } - break; - default: - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -ReturnValue_t Service2DeviceAccess::prepareRawCommand( - CommandMessage* messageToSet, const uint8_t *tcData,size_t tcDataLen) { - RawCommand RawCommand(tcData,tcDataLen); - // store command into the Inter Process Communication Store - store_address_t storeAddress; - ReturnValue_t result = IPCStore->addData(&storeAddress, - RawCommand.getCommand(), RawCommand.getCommandSize()); - DeviceHandlerMessage::setDeviceHandlerRawCommandMessage(messageToSet, - storeAddress); - return result; -} - -ReturnValue_t Service2DeviceAccess::prepareWiretappingCommand( - CommandMessage *messageToSet, const uint8_t *tcData, - size_t tcDataLen) { - if(tcDataLen != WiretappingToggle::WIRETAPPING_COMMAND_SIZE) { - return CommandingServiceBase::INVALID_TC; - } - WiretappingToggle command; - ReturnValue_t result = command.deSerialize(&tcData, &tcDataLen, - SerializeIF::Endianness::BIG); - DeviceHandlerMessage::setDeviceHandlerWiretappingMessage(messageToSet, - command.getWiretappingMode()); - return result; -} - - -ReturnValue_t Service2DeviceAccess::handleReply(const CommandMessage* reply, - Command_t previousCommand, uint32_t* state, - CommandMessage* optionalNextCommand, object_id_t objectId, - bool* isStep) { - switch(reply->getCommand()) { - case CommandMessage::REPLY_COMMAND_OK: - return HasReturnvaluesIF::RETURN_OK; - case CommandMessage::REPLY_REJECTED: - return reply->getReplyRejectedReason(); - default: - return CommandingServiceBase::INVALID_REPLY; - } -} - -// All device handlers set service 2 as default raw receiver for wiretapping -// so we have to handle those unrequested messages. -void Service2DeviceAccess::handleUnrequestedReply(CommandMessage* reply) { - switch(reply->getCommand()) { - case DeviceHandlerMessage::REPLY_RAW_COMMAND: - sendWiretappingTm(reply, - static_cast(Subservice::WIRETAPPING_RAW_TC)); - break; - case DeviceHandlerMessage::REPLY_RAW_REPLY: - sendWiretappingTm(reply, - static_cast(Subservice::RAW_REPLY)); - break; - default: - sif::error << "Unknown message in Service2DeviceAccess::" - "handleUnrequestedReply with command ID " << - reply->getCommand() << std::endl; - break; - } - //Must be reached by all cases to clear message - reply->clear(); -} - -void Service2DeviceAccess::sendWiretappingTm(CommandMessage *reply, - uint8_t subservice) { - // Raw Wiretapping - // Get Address of Data from Message - store_address_t storeAddress = DeviceHandlerMessage::getStoreAddress(reply); - const uint8_t* data = nullptr; - size_t size = 0; - ReturnValue_t result = IPCStore->getData(storeAddress, &data, &size); - if(result != HasReturnvaluesIF::RETURN_OK){ - sif::error << "Service2DeviceAccess::sendWiretappingTm: Data Lost in " - "handleUnrequestedReply with failure ID "<< result - << std::endl; - return; - } - - // Init our dummy packet and correct endianness of object ID before - // sending it back. - WiretappingPacket TmPacket(DeviceHandlerMessage::getDeviceObjectId(reply), - data); - TmPacket.objectId = EndianConverter::convertBigEndian(TmPacket.objectId); - sendTmPacket(subservice, TmPacket.data,size, reinterpret_cast( - &TmPacket.objectId), sizeof(TmPacket.objectId)); -} - -MessageQueueId_t Service2DeviceAccess::getDeviceQueue() { - return commandQueue->getId(); -} - +#include "Service2DeviceAccess.h" +#include "servicepackets/Service2Packets.h" + +#include "../devicehandlers/DeviceHandlerIF.h" +#include "../storagemanager/StorageManagerIF.h" +#include "../devicehandlers/DeviceHandlerMessage.h" +#include "../serialize/EndianConverter.h" +#include "../action/ActionMessage.h" +#include "../serialize/SerializeAdapter.h" +#include "../serialize/SerialLinkedListAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" + +Service2DeviceAccess::Service2DeviceAccess(object_id_t objectId, + uint16_t apid, uint8_t serviceId, uint8_t numberOfParallelCommands, + uint16_t commandTimeoutSeconds): + CommandingServiceBase(objectId, apid, serviceId, + numberOfParallelCommands, commandTimeoutSeconds) {} + +Service2DeviceAccess::~Service2DeviceAccess() {} + + +ReturnValue_t Service2DeviceAccess::isValidSubservice(uint8_t subservice) { + switch(static_cast(subservice)){ + case Subservice::RAW_COMMANDING: + case Subservice::TOGGLE_WIRETAPPING: + return HasReturnvaluesIF::RETURN_OK; + default: + sif::error << "Invalid Subservice" << std::endl; + return AcceptsTelecommandsIF::INVALID_SUBSERVICE; + } +} + +ReturnValue_t Service2DeviceAccess::getMessageQueueAndObject( + uint8_t subservice, const uint8_t* tcData, size_t tcDataLen, + MessageQueueId_t* id, object_id_t* objectId) { + if(tcDataLen < sizeof(object_id_t)) { + return CommandingServiceBase::INVALID_TC; + } + SerializeAdapter::deSerialize(objectId, &tcData, + &tcDataLen, SerializeIF::Endianness::BIG); + + ReturnValue_t result = checkInterfaceAndAcquireMessageQueue(id,objectId); + return result; +} + +ReturnValue_t Service2DeviceAccess::checkInterfaceAndAcquireMessageQueue( + MessageQueueId_t * messageQueueToSet, object_id_t *objectId) { + DeviceHandlerIF* possibleTarget = + objectManager->get(*objectId); + if(possibleTarget == nullptr) { + return CommandingServiceBase::INVALID_OBJECT; + } + *messageQueueToSet = possibleTarget->getCommandQueue(); + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t Service2DeviceAccess::prepareCommand(CommandMessage* message, + uint8_t subservice, const uint8_t* tcData, size_t tcDataLen, + uint32_t* state, object_id_t objectId) { + switch(static_cast(subservice)){ + case Subservice::RAW_COMMANDING: { + return prepareRawCommand(dynamic_cast(message), + tcData, tcDataLen); + } + break; + case Subservice::TOGGLE_WIRETAPPING: { + return prepareWiretappingCommand(dynamic_cast(message), + tcData, tcDataLen); + } + break; + default: + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +ReturnValue_t Service2DeviceAccess::prepareRawCommand( + CommandMessage* messageToSet, const uint8_t *tcData,size_t tcDataLen) { + RawCommand RawCommand(tcData,tcDataLen); + // store command into the Inter Process Communication Store + store_address_t storeAddress; + ReturnValue_t result = IPCStore->addData(&storeAddress, + RawCommand.getCommand(), RawCommand.getCommandSize()); + DeviceHandlerMessage::setDeviceHandlerRawCommandMessage(messageToSet, + storeAddress); + return result; +} + +ReturnValue_t Service2DeviceAccess::prepareWiretappingCommand( + CommandMessage *messageToSet, const uint8_t *tcData, + size_t tcDataLen) { + if(tcDataLen != WiretappingToggle::WIRETAPPING_COMMAND_SIZE) { + return CommandingServiceBase::INVALID_TC; + } + WiretappingToggle command; + ReturnValue_t result = command.deSerialize(&tcData, &tcDataLen, + SerializeIF::Endianness::BIG); + DeviceHandlerMessage::setDeviceHandlerWiretappingMessage(messageToSet, + command.getWiretappingMode()); + return result; +} + + +ReturnValue_t Service2DeviceAccess::handleReply(const CommandMessage* reply, + Command_t previousCommand, uint32_t* state, + CommandMessage* optionalNextCommand, object_id_t objectId, + bool* isStep) { + switch(reply->getCommand()) { + case CommandMessage::REPLY_COMMAND_OK: + return HasReturnvaluesIF::RETURN_OK; + case CommandMessage::REPLY_REJECTED: + return reply->getReplyRejectedReason(); + default: + return CommandingServiceBase::INVALID_REPLY; + } +} + +// All device handlers set service 2 as default raw receiver for wiretapping +// so we have to handle those unrequested messages. +void Service2DeviceAccess::handleUnrequestedReply(CommandMessage* reply) { + switch(reply->getCommand()) { + case DeviceHandlerMessage::REPLY_RAW_COMMAND: + sendWiretappingTm(reply, + static_cast(Subservice::WIRETAPPING_RAW_TC)); + break; + case DeviceHandlerMessage::REPLY_RAW_REPLY: + sendWiretappingTm(reply, + static_cast(Subservice::RAW_REPLY)); + break; + default: + sif::error << "Unknown message in Service2DeviceAccess::" + "handleUnrequestedReply with command ID " << + reply->getCommand() << std::endl; + break; + } + //Must be reached by all cases to clear message + reply->clear(); +} + +void Service2DeviceAccess::sendWiretappingTm(CommandMessage *reply, + uint8_t subservice) { + // Raw Wiretapping + // Get Address of Data from Message + store_address_t storeAddress = DeviceHandlerMessage::getStoreAddress(reply); + const uint8_t* data = nullptr; + size_t size = 0; + ReturnValue_t result = IPCStore->getData(storeAddress, &data, &size); + if(result != HasReturnvaluesIF::RETURN_OK){ + sif::error << "Service2DeviceAccess::sendWiretappingTm: Data Lost in " + "handleUnrequestedReply with failure ID "<< result + << std::endl; + return; + } + + // Init our dummy packet and correct endianness of object ID before + // sending it back. + WiretappingPacket TmPacket(DeviceHandlerMessage::getDeviceObjectId(reply), + data); + TmPacket.objectId = EndianConverter::convertBigEndian(TmPacket.objectId); + sendTmPacket(subservice, TmPacket.data,size, reinterpret_cast( + &TmPacket.objectId), sizeof(TmPacket.objectId)); +} + +MessageQueueId_t Service2DeviceAccess::getDeviceQueue() { + return commandQueue->getId(); +} + diff --git a/pus/Service2DeviceAccess.h b/pus/Service2DeviceAccess.h index 1a0bede0..f6aa8b52 100644 --- a/pus/Service2DeviceAccess.h +++ b/pus/Service2DeviceAccess.h @@ -1,92 +1,92 @@ -#ifndef FRAMEWORK_PUS_SERVICE2DEVICEACCESS_H_ -#define FRAMEWORK_PUS_SERVICE2DEVICEACCESS_H_ - -#include -#include -#include - -/** - * @brief Raw Commanding and Wiretapping of devices. - * @details - * Full Documentation: ECSS-E-ST-70-41C or ECSS-E-70-41A - * Dissertation Baetz p. 115, 116, 165-167. - * - * This service provides the capability to communicate with devices in their - * native protocols with raw commands through the DeviceHandlerIF. - * - * This is a gateway service. It relays device commands to the software bus. - * This service is very closely tied to the CommandingServiceBase - * template class. - * - * There are 4 adaption points for component implementation through the - * CommandingServiceBase. - * - * This service employs custom subservices exclusively. This includes a - * wiretapping subservice to monitor all traffic between target devices and - * this service. - * - * - TC[2,128]: Raw Commanding - * - TC[2,129]: Toggle Wiretapping - * - TM[2,130]: Wiretapping Packet TM - * - TM[2,131]: Wiretapping Packet TC - * @ingroup pus_services - */ -class Service2DeviceAccess : public CommandingServiceBase, - public AcceptsDeviceResponsesIF -{ -public: - Service2DeviceAccess(object_id_t objectId, uint16_t apid, - uint8_t serviceId, uint8_t numberOfParallelCommands = 4, - uint16_t commandTimeoutSeconds = 60); - virtual ~Service2DeviceAccess(); - -protected: - //! CommandingServiceBase (CSB) abstract functions. See CSB documentation. - ReturnValue_t isValidSubservice(uint8_t subservice) override; - ReturnValue_t getMessageQueueAndObject(uint8_t subservice, - const uint8_t *tcData, size_t tcDataLen, MessageQueueId_t *id, - object_id_t *objectId) override; - ReturnValue_t prepareCommand(CommandMessage* message, uint8_t subservice, - const uint8_t *tcData, size_t tcDataLen, uint32_t *state, - object_id_t objectId) override; - ReturnValue_t handleReply(const CommandMessage* reply, - Command_t previousCommand, uint32_t *state, - CommandMessage* optionalNextCommand, object_id_t objectId, - bool *isStep) override; - - /** - * @brief Generates TM packets containing either the TC wiretapping - * packets or the TM wiretapping packets. - * Note that for service 2, all telemetry will be treated as an - * unrequested reply regardless of wiretapping mode. - * @param reply - */ - void handleUnrequestedReply(CommandMessage* reply) override; - - MessageQueueId_t getDeviceQueue() override; -private: - /** - * Generates TM packets for Wiretapping Service - * @param reply - * @param subservice - */ - void sendWiretappingTm(CommandMessage* reply,uint8_t subservice); - - ReturnValue_t checkInterfaceAndAcquireMessageQueue( - MessageQueueId_t* messageQueueToSet, object_id_t* objectId); - - ReturnValue_t prepareRawCommand(CommandMessage* messageToSet, - const uint8_t* tcData, size_t tcDataLen); - ReturnValue_t prepareWiretappingCommand(CommandMessage* messageToSet, - const uint8_t* tcData, size_t tcDataLen); - - enum class Subservice { - RAW_COMMANDING = 128, //!< [EXPORT] : [COMMAND] Command in device native protocol - TOGGLE_WIRETAPPING = 129, //!< [EXPORT] : [COMMAND] Toggle wiretapping of raw communication - RAW_REPLY = 130, //!< [EXPORT] : [REPLY] Includes wiretapping TM and normal TM raw replies from device - WIRETAPPING_RAW_TC = 131 //!< [EXPORT] : [REPLY] Wiretapping packets of commands built by device handler - }; -}; - - -#endif /* MISSION_PUS_DEVICE2DEVICECOMMANDING_H_ */ +#ifndef FRAMEWORK_PUS_SERVICE2DEVICEACCESS_H_ +#define FRAMEWORK_PUS_SERVICE2DEVICEACCESS_H_ + +#include "../objectmanager/SystemObjectIF.h" +#include "../devicehandlers/AcceptsDeviceResponsesIF.h" +#include "../tmtcservices/CommandingServiceBase.h" + +/** + * @brief Raw Commanding and Wiretapping of devices. + * @details + * Full Documentation: ECSS-E-ST-70-41C or ECSS-E-70-41A + * Dissertation Baetz p. 115, 116, 165-167. + * + * This service provides the capability to communicate with devices in their + * native protocols with raw commands through the DeviceHandlerIF. + * + * This is a gateway service. It relays device commands to the software bus. + * This service is very closely tied to the CommandingServiceBase + * template class. + * + * There are 4 adaption points for component implementation through the + * CommandingServiceBase. + * + * This service employs custom subservices exclusively. This includes a + * wiretapping subservice to monitor all traffic between target devices and + * this service. + * + * - TC[2,128]: Raw Commanding + * - TC[2,129]: Toggle Wiretapping + * - TM[2,130]: Wiretapping Packet TM + * - TM[2,131]: Wiretapping Packet TC + * @ingroup pus_services + */ +class Service2DeviceAccess : public CommandingServiceBase, + public AcceptsDeviceResponsesIF +{ +public: + Service2DeviceAccess(object_id_t objectId, uint16_t apid, + uint8_t serviceId, uint8_t numberOfParallelCommands = 4, + uint16_t commandTimeoutSeconds = 60); + virtual ~Service2DeviceAccess(); + +protected: + //! CommandingServiceBase (CSB) abstract functions. See CSB documentation. + ReturnValue_t isValidSubservice(uint8_t subservice) override; + ReturnValue_t getMessageQueueAndObject(uint8_t subservice, + const uint8_t *tcData, size_t tcDataLen, MessageQueueId_t *id, + object_id_t *objectId) override; + ReturnValue_t prepareCommand(CommandMessage* message, uint8_t subservice, + const uint8_t *tcData, size_t tcDataLen, uint32_t *state, + object_id_t objectId) override; + ReturnValue_t handleReply(const CommandMessage* reply, + Command_t previousCommand, uint32_t *state, + CommandMessage* optionalNextCommand, object_id_t objectId, + bool *isStep) override; + + /** + * @brief Generates TM packets containing either the TC wiretapping + * packets or the TM wiretapping packets. + * Note that for service 2, all telemetry will be treated as an + * unrequested reply regardless of wiretapping mode. + * @param reply + */ + void handleUnrequestedReply(CommandMessage* reply) override; + + MessageQueueId_t getDeviceQueue() override; +private: + /** + * Generates TM packets for Wiretapping Service + * @param reply + * @param subservice + */ + void sendWiretappingTm(CommandMessage* reply,uint8_t subservice); + + ReturnValue_t checkInterfaceAndAcquireMessageQueue( + MessageQueueId_t* messageQueueToSet, object_id_t* objectId); + + ReturnValue_t prepareRawCommand(CommandMessage* messageToSet, + const uint8_t* tcData, size_t tcDataLen); + ReturnValue_t prepareWiretappingCommand(CommandMessage* messageToSet, + const uint8_t* tcData, size_t tcDataLen); + + enum class Subservice { + RAW_COMMANDING = 128, //!< [EXPORT] : [COMMAND] Command in device native protocol + TOGGLE_WIRETAPPING = 129, //!< [EXPORT] : [COMMAND] Toggle wiretapping of raw communication + RAW_REPLY = 130, //!< [EXPORT] : [REPLY] Includes wiretapping TM and normal TM raw replies from device + WIRETAPPING_RAW_TC = 131 //!< [EXPORT] : [REPLY] Wiretapping packets of commands built by device handler + }; +}; + + +#endif /* MISSION_PUS_DEVICE2DEVICECOMMANDING_H_ */ diff --git a/pus/Service5EventReporting.cpp b/pus/Service5EventReporting.cpp index 1dfbe229..831f92c1 100644 --- a/pus/Service5EventReporting.cpp +++ b/pus/Service5EventReporting.cpp @@ -1,10 +1,10 @@ -#include -#include +#include "Service5EventReporting.h" +#include "servicepackets/Service5Packets.h" -#include -#include -#include -#include +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../events/EventManagerIF.h" +#include "../ipc/QueueFactory.h" +#include "/tmtcpacketTmPacketStored.h" Service5EventReporting::Service5EventReporting(object_id_t objectId, diff --git a/pus/Service5EventReporting.h b/pus/Service5EventReporting.h index 79b7c5e7..0b6ee9a8 100644 --- a/pus/Service5EventReporting.h +++ b/pus/Service5EventReporting.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_PUS_SERVICE5EVENTREPORTING_H_ #define FRAMEWORK_PUS_SERVICE5EVENTREPORTING_H_ -#include -#include +#include "../tmtcservices/PusServiceBase.h" +#include "../events/EventMessage.h" /** * @brief Report on-board events like information or errors diff --git a/pus/Service8FunctionManagement.cpp b/pus/Service8FunctionManagement.cpp index 50102b04..2c2e590b 100644 --- a/pus/Service8FunctionManagement.cpp +++ b/pus/Service8FunctionManagement.cpp @@ -1,142 +1,142 @@ -#include -#include - -#include -#include -#include -#include -#include - -Service8FunctionManagement::Service8FunctionManagement(object_id_t object_id, - uint16_t apid, uint8_t serviceId, uint8_t numParallelCommands, - uint16_t commandTimeoutSeconds): - CommandingServiceBase(object_id, apid, serviceId, numParallelCommands, - commandTimeoutSeconds) {} - -Service8FunctionManagement::~Service8FunctionManagement() {} - - -ReturnValue_t Service8FunctionManagement::isValidSubservice( - uint8_t subservice) { - switch(static_cast(subservice)) { - case Subservice::DIRECT_COMMANDING: - return HasReturnvaluesIF::RETURN_OK; - default: - return AcceptsTelecommandsIF::INVALID_SUBSERVICE; - } -} - -ReturnValue_t Service8FunctionManagement::getMessageQueueAndObject( - uint8_t subservice, const uint8_t* tcData, size_t tcDataLen, - MessageQueueId_t* id, object_id_t* objectId) { - if(tcDataLen < sizeof(object_id_t)) { - return CommandingServiceBase::INVALID_TC; - } - SerializeAdapter::deSerialize(objectId, &tcData, - &tcDataLen, SerializeIF::Endianness::BIG); - - return checkInterfaceAndAcquireMessageQueue(id,objectId); -} - -ReturnValue_t Service8FunctionManagement::checkInterfaceAndAcquireMessageQueue( - MessageQueueId_t* messageQueueToSet, object_id_t* objectId) { - // check HasActionIF property of target - HasActionsIF* possibleTarget = objectManager->get(*objectId); - if(possibleTarget == nullptr){ - return CommandingServiceBase::INVALID_OBJECT; - } - *messageQueueToSet = possibleTarget->getCommandQueue(); - return HasReturnvaluesIF::RETURN_OK; -} - - -ReturnValue_t Service8FunctionManagement::prepareCommand( - CommandMessage* message, uint8_t subservice, const uint8_t* tcData, - size_t tcDataLen, uint32_t* state, object_id_t objectId) { - return prepareDirectCommand(dynamic_cast(message), - tcData, tcDataLen); -} - -ReturnValue_t Service8FunctionManagement::prepareDirectCommand( - CommandMessage *message, const uint8_t *tcData, size_t tcDataLen) { - if(tcDataLen < sizeof(object_id_t) + sizeof(ActionId_t)) { - sif::debug << "Service8FunctionManagement::prepareDirectCommand:" - << " TC size smaller thant minimum size of direct command." - << std::endl; - return CommandingServiceBase::INVALID_TC; - } - - // Create direct command instance by extracting data from Telecommand - DirectCommand command(tcData, tcDataLen); - - // store additional parameters into the IPC Store - store_address_t parameterAddress; - ReturnValue_t result = IPCStore->addData(¶meterAddress, - command.getParameters(),command.getParametersSize()); - - // setCommand expects a Command Message, an Action ID and a store adress - // pointing to additional parameters - ActionMessage::setCommand(message,command.getActionId(),parameterAddress); - return result; -} - - -ReturnValue_t Service8FunctionManagement::handleReply( - const CommandMessage* reply, Command_t previousCommand, - uint32_t* state, CommandMessage* optionalNextCommand, - object_id_t objectId, bool* isStep) { - Command_t replyId = reply->getCommand(); - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; - ActionId_t actionId = ActionMessage::getActionId(reply); - ReturnValue_t returnCode = ActionMessage::getReturnCode(reply); - - switch(replyId) { - case ActionMessage::COMPLETION_SUCCESS: { - DirectReply completionReply(objectId, actionId,returnCode); - result = CommandingServiceBase::EXECUTION_COMPLETE; - break; - } - case ActionMessage::STEP_SUCCESS: { - *isStep = true; - result = HasReturnvaluesIF::RETURN_OK; - break; - } - case ActionMessage::DATA_REPLY: { - result = handleDataReply(reply, objectId, actionId); - break; - } - case ActionMessage::STEP_FAILED: - *isStep = true; - /*No break, falls through*/ - case ActionMessage::COMPLETION_FAILED: - result = ActionMessage::getReturnCode(reply); - break; - default: - result = INVALID_REPLY; - } - return result; -} - -ReturnValue_t Service8FunctionManagement::handleDataReply( - const CommandMessage* reply, object_id_t objectId, - ActionId_t actionId) { - store_address_t storeId = ActionMessage::getStoreId(reply); - size_t size = 0; - const uint8_t * buffer = nullptr; - ReturnValue_t result = IPCStore->getData(storeId, &buffer, &size); - if(result != RETURN_OK) { - sif::error << "Service 8: Could not retrieve data for data reply" - << std::endl; - return result; - } - DataReply dataReply(objectId, actionId, buffer, size); - result = sendTmPacket(static_cast( - Subservice::DIRECT_COMMANDING_DATA_REPLY), &dataReply); - - auto deletionResult = IPCStore->deleteData(storeId); - if(deletionResult != HasReturnvaluesIF::RETURN_OK) { - sif::warning << "Service8FunctionManagement::handleReply: Deletion" - << " of data in pool failed." << std::endl; - } - return result; -} +#include "Service8FunctionManagement.h" +#include "servicepackets/Service8Packets.h" + +#include "../objectmanager/SystemObjectIF.h" +#include "../action/HasActionsIF.h" +#include "../devicehandlers/DeviceHandlerIF.h" +#include "../serialize/SerializeAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" + +Service8FunctionManagement::Service8FunctionManagement(object_id_t object_id, + uint16_t apid, uint8_t serviceId, uint8_t numParallelCommands, + uint16_t commandTimeoutSeconds): + CommandingServiceBase(object_id, apid, serviceId, numParallelCommands, + commandTimeoutSeconds) {} + +Service8FunctionManagement::~Service8FunctionManagement() {} + + +ReturnValue_t Service8FunctionManagement::isValidSubservice( + uint8_t subservice) { + switch(static_cast(subservice)) { + case Subservice::DIRECT_COMMANDING: + return HasReturnvaluesIF::RETURN_OK; + default: + return AcceptsTelecommandsIF::INVALID_SUBSERVICE; + } +} + +ReturnValue_t Service8FunctionManagement::getMessageQueueAndObject( + uint8_t subservice, const uint8_t* tcData, size_t tcDataLen, + MessageQueueId_t* id, object_id_t* objectId) { + if(tcDataLen < sizeof(object_id_t)) { + return CommandingServiceBase::INVALID_TC; + } + SerializeAdapter::deSerialize(objectId, &tcData, + &tcDataLen, SerializeIF::Endianness::BIG); + + return checkInterfaceAndAcquireMessageQueue(id,objectId); +} + +ReturnValue_t Service8FunctionManagement::checkInterfaceAndAcquireMessageQueue( + MessageQueueId_t* messageQueueToSet, object_id_t* objectId) { + // check HasActionIF property of target + HasActionsIF* possibleTarget = objectManager->get(*objectId); + if(possibleTarget == nullptr){ + return CommandingServiceBase::INVALID_OBJECT; + } + *messageQueueToSet = possibleTarget->getCommandQueue(); + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t Service8FunctionManagement::prepareCommand( + CommandMessage* message, uint8_t subservice, const uint8_t* tcData, + size_t tcDataLen, uint32_t* state, object_id_t objectId) { + return prepareDirectCommand(dynamic_cast(message), + tcData, tcDataLen); +} + +ReturnValue_t Service8FunctionManagement::prepareDirectCommand( + CommandMessage *message, const uint8_t *tcData, size_t tcDataLen) { + if(tcDataLen < sizeof(object_id_t) + sizeof(ActionId_t)) { + sif::debug << "Service8FunctionManagement::prepareDirectCommand:" + << " TC size smaller thant minimum size of direct command." + << std::endl; + return CommandingServiceBase::INVALID_TC; + } + + // Create direct command instance by extracting data from Telecommand + DirectCommand command(tcData, tcDataLen); + + // store additional parameters into the IPC Store + store_address_t parameterAddress; + ReturnValue_t result = IPCStore->addData(¶meterAddress, + command.getParameters(),command.getParametersSize()); + + // setCommand expects a Command Message, an Action ID and a store adress + // pointing to additional parameters + ActionMessage::setCommand(message,command.getActionId(),parameterAddress); + return result; +} + + +ReturnValue_t Service8FunctionManagement::handleReply( + const CommandMessage* reply, Command_t previousCommand, + uint32_t* state, CommandMessage* optionalNextCommand, + object_id_t objectId, bool* isStep) { + Command_t replyId = reply->getCommand(); + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + ActionId_t actionId = ActionMessage::getActionId(reply); + ReturnValue_t returnCode = ActionMessage::getReturnCode(reply); + + switch(replyId) { + case ActionMessage::COMPLETION_SUCCESS: { + DirectReply completionReply(objectId, actionId,returnCode); + result = CommandingServiceBase::EXECUTION_COMPLETE; + break; + } + case ActionMessage::STEP_SUCCESS: { + *isStep = true; + result = HasReturnvaluesIF::RETURN_OK; + break; + } + case ActionMessage::DATA_REPLY: { + result = handleDataReply(reply, objectId, actionId); + break; + } + case ActionMessage::STEP_FAILED: + *isStep = true; + /*No break, falls through*/ + case ActionMessage::COMPLETION_FAILED: + result = ActionMessage::getReturnCode(reply); + break; + default: + result = INVALID_REPLY; + } + return result; +} + +ReturnValue_t Service8FunctionManagement::handleDataReply( + const CommandMessage* reply, object_id_t objectId, + ActionId_t actionId) { + store_address_t storeId = ActionMessage::getStoreId(reply); + size_t size = 0; + const uint8_t * buffer = nullptr; + ReturnValue_t result = IPCStore->getData(storeId, &buffer, &size); + if(result != RETURN_OK) { + sif::error << "Service 8: Could not retrieve data for data reply" + << std::endl; + return result; + } + DataReply dataReply(objectId, actionId, buffer, size); + result = sendTmPacket(static_cast( + Subservice::DIRECT_COMMANDING_DATA_REPLY), &dataReply); + + auto deletionResult = IPCStore->deleteData(storeId); + if(deletionResult != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "Service8FunctionManagement::handleReply: Deletion" + << " of data in pool failed." << std::endl; + } + return result; +} diff --git a/pus/Service8FunctionManagement.h b/pus/Service8FunctionManagement.h index e2c7a84f..b5ebcda8 100644 --- a/pus/Service8FunctionManagement.h +++ b/pus/Service8FunctionManagement.h @@ -1,67 +1,67 @@ -#ifndef FRAMEWORK_PUS_SERVICE8FUNCTIONMANAGEMENT_H_ -#define FRAMEWORK_PUS_SERVICE8FUNCTIONMANAGEMENT_H_ - -#include -#include - -/** - * @brief Functional commanding. - * Full Documentation: ECSS-E-ST-70-41C p.64, p. 451 - * Dissertation Baetz p. 115, 116, 165-167 - * - * This service provides the capability to perform functions of an - * application process and provides high-level commanding as opposed to the - * Raw Access provided by Service 2. Examples for these functions can include - * control and operation of payload or the AOCS subsystem. - * This service will be the primary means to control the spacecraft as it is - * considered safer than the Raw Access provided - * by Service 2 and is generally sufficient for most tasks. - * - * This is a gateway service. It relays device commands using the software bus. - * This service is very closely tied to the Commanding Service Base template - * class. There is constant interaction between this Service Base und a - * subclass like this service. - * - * Service Capability: - * - TC[8,128]: Direct Commanding - * - TM[8,130]: Direct Commanding Data Reply - * - * @ingroup pus_services - */ -class Service8FunctionManagement : public CommandingServiceBase -{ -public: - Service8FunctionManagement(object_id_t objectId, uint16_t apid, - uint8_t serviceId, uint8_t numParallelCommands = 4, - uint16_t commandTimeoutSeconds = 60); - virtual ~Service8FunctionManagement(); - -protected: - /* CSB abstract functions implementation . See CSB documentation. */ - ReturnValue_t isValidSubservice(uint8_t subservice) override; - ReturnValue_t getMessageQueueAndObject(uint8_t subservice, - const uint8_t *tcData, size_t tcDataLen, MessageQueueId_t *id, - object_id_t *objectId) override; - ReturnValue_t prepareCommand(CommandMessage* message, - uint8_t subservice, const uint8_t *tcData, size_t tcDataLen, - uint32_t *state, object_id_t objectId) override; - ReturnValue_t handleReply(const CommandMessage* reply, - Command_t previousCommand, uint32_t *state, - CommandMessage* optionalNextCommand, object_id_t objectId, - bool *isStep) override; - -private: - enum class Subservice { - DIRECT_COMMANDING = 128, //!< [EXPORT] : [COMMAND] Functional commanding - DIRECT_COMMANDING_DATA_REPLY = 130, //!< [EXPORT] : [REPLY] Data reply - }; - - ReturnValue_t checkInterfaceAndAcquireMessageQueue( - MessageQueueId_t* messageQueueToSet, object_id_t* objectId); - ReturnValue_t prepareDirectCommand(CommandMessage* message, - const uint8_t* tcData, size_t tcDataLen); - ReturnValue_t handleDataReply(const CommandMessage* reply, - object_id_t objectId, ActionId_t actionId); -}; - -#endif /* FRAMEWORK_PUS_SERVICE8FUNCTIONMANAGEMENT_H_ */ +#ifndef FRAMEWORK_PUS_SERVICE8FUNCTIONMANAGEMENT_H_ +#define FRAMEWORK_PUS_SERVICE8FUNCTIONMANAGEMENT_H_ + +#include "../action/ActionMessage.h" +#include "../tmtcservices/CommandingServiceBase.h" + +/** + * @brief Functional commanding. + * Full Documentation: ECSS-E-ST-70-41C p.64, p. 451 + * Dissertation Baetz p. 115, 116, 165-167 + * + * This service provides the capability to perform functions of an + * application process and provides high-level commanding as opposed to the + * Raw Access provided by Service 2. Examples for these functions can include + * control and operation of payload or the AOCS subsystem. + * This service will be the primary means to control the spacecraft as it is + * considered safer than the Raw Access provided + * by Service 2 and is generally sufficient for most tasks. + * + * This is a gateway service. It relays device commands using the software bus. + * This service is very closely tied to the Commanding Service Base template + * class. There is constant interaction between this Service Base und a + * subclass like this service. + * + * Service Capability: + * - TC[8,128]: Direct Commanding + * - TM[8,130]: Direct Commanding Data Reply + * + * @ingroup pus_services + */ +class Service8FunctionManagement : public CommandingServiceBase +{ +public: + Service8FunctionManagement(object_id_t objectId, uint16_t apid, + uint8_t serviceId, uint8_t numParallelCommands = 4, + uint16_t commandTimeoutSeconds = 60); + virtual ~Service8FunctionManagement(); + +protected: + /* CSB abstract functions implementation . See CSB documentation. */ + ReturnValue_t isValidSubservice(uint8_t subservice) override; + ReturnValue_t getMessageQueueAndObject(uint8_t subservice, + const uint8_t *tcData, size_t tcDataLen, MessageQueueId_t *id, + object_id_t *objectId) override; + ReturnValue_t prepareCommand(CommandMessage* message, + uint8_t subservice, const uint8_t *tcData, size_t tcDataLen, + uint32_t *state, object_id_t objectId) override; + ReturnValue_t handleReply(const CommandMessage* reply, + Command_t previousCommand, uint32_t *state, + CommandMessage* optionalNextCommand, object_id_t objectId, + bool *isStep) override; + +private: + enum class Subservice { + DIRECT_COMMANDING = 128, //!< [EXPORT] : [COMMAND] Functional commanding + DIRECT_COMMANDING_DATA_REPLY = 130, //!< [EXPORT] : [REPLY] Data reply + }; + + ReturnValue_t checkInterfaceAndAcquireMessageQueue( + MessageQueueId_t* messageQueueToSet, object_id_t* objectId); + ReturnValue_t prepareDirectCommand(CommandMessage* message, + const uint8_t* tcData, size_t tcDataLen); + ReturnValue_t handleDataReply(const CommandMessage* reply, + object_id_t objectId, ActionId_t actionId); +}; + +#endif /* FRAMEWORK_PUS_SERVICE8FUNCTIONMANAGEMENT_H_ */ diff --git a/pus/servicepackets/Service1Packets.h b/pus/servicepackets/Service1Packets.h index b01942c6..dbd31028 100644 --- a/pus/servicepackets/Service1Packets.h +++ b/pus/servicepackets/Service1Packets.h @@ -8,8 +8,8 @@ #ifndef MISSION_PUS_SERVICEPACKETS_SERVICE1PACKETS_H_ #define MISSION_PUS_SERVICEPACKETS_SERVICE1PACKETS_H_ -#include -#include +#include "../../serialize/SerializeAdapter.h" +#include "../../tmtcservices/VerificationCodes.h" /** * @brief FailureReport class to serialize a failure report diff --git a/pus/servicepackets/Service200Packets.h b/pus/servicepackets/Service200Packets.h index 1b5bf236..efcf65fc 100644 --- a/pus/servicepackets/Service200Packets.h +++ b/pus/servicepackets/Service200Packets.h @@ -1,63 +1,63 @@ -#ifndef FRAMEWORK_PUS_SERVICEPACKETS_SERVICE200PACKETS_H_ -#define FRAMEWORK_PUS_SERVICEPACKETS_SERVICE200PACKETS_H_ - -#include -#include -#include - -/** - * @brief Subservice 1, 2, 3, 4, 5 - * @ingroup spacepackets - */ -class ModePacket : public SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 1, 2, 6 -public: - - ModePacket() { - setLinks(); - } - - ModePacket(object_id_t objectId, Mode_t mode, Submode_t submode) : - objectId(objectId), mode(mode), submode(submode) { - setLinks(); - } - - Mode_t getMode() { - return mode.entry; - } - - Submode_t getSubmode() { - return submode.entry; - } - - // Forbid copying, pointers are used. - ModePacket(const ModePacket&) = delete; - ModePacket& operator=(const ModePacket&) = delete; -private: - - void setLinks() { - setStart(&objectId); - objectId.setNext(&mode); - mode.setNext(&submode); - } - SerializeElement objectId; //!< [EXPORT] : [COMMENT] Target or source object - SerializeElement mode; //!< [EXPORT] : [COMMENT] 0: MODE_OFF, 1: MODE_ON, 2: MODE_NORMAL, 3: MODE_RAW - SerializeElement submode; //!< [EXPORT] : [COMMENT] Usually 0, device specific submode possible -}; - -/** - * @brief Subservice 7 - * @ingroup spacepackets - */ -class CantReachModePacket: public SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 7 -public: - CantReachModePacket(object_id_t objectId, ReturnValue_t reason): - objectId(objectId), reason(reason) { - setStart(&this->objectId); - this->objectId.setNext(&this->reason); - } - - SerializeElement objectId; //!< [EXPORT] : [COMMENT] Reply source object - SerializeElement reason; //!< [EXPORT] : [COMMENT] Reason the mode could not be reached -}; - -#endif /* FRAMEWORK_PUS_SERVICEPACKETS_SERVICE200PACKETS_H_ */ +#ifndef FRAMEWORK_PUS_SERVICEPACKETS_SERVICE200PACKETS_H_ +#define FRAMEWORK_PUS_SERVICEPACKETS_SERVICE200PACKETS_H_ + +#include "../../serialize/SerialLinkedListAdapter.h" +#include "../../modes/ModeMessage.h" +#include "../../serialize/SerializeIF.h" + +/** + * @brief Subservice 1, 2, 3, 4, 5 + * @ingroup spacepackets + */ +class ModePacket : public SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 1, 2, 6 +public: + + ModePacket() { + setLinks(); + } + + ModePacket(object_id_t objectId, Mode_t mode, Submode_t submode) : + objectId(objectId), mode(mode), submode(submode) { + setLinks(); + } + + Mode_t getMode() { + return mode.entry; + } + + Submode_t getSubmode() { + return submode.entry; + } + + // Forbid copying, pointers are used. + ModePacket(const ModePacket&) = delete; + ModePacket& operator=(const ModePacket&) = delete; +private: + + void setLinks() { + setStart(&objectId); + objectId.setNext(&mode); + mode.setNext(&submode); + } + SerializeElement objectId; //!< [EXPORT] : [COMMENT] Target or source object + SerializeElement mode; //!< [EXPORT] : [COMMENT] 0: MODE_OFF, 1: MODE_ON, 2: MODE_NORMAL, 3: MODE_RAW + SerializeElement submode; //!< [EXPORT] : [COMMENT] Usually 0, device specific submode possible +}; + +/** + * @brief Subservice 7 + * @ingroup spacepackets + */ +class CantReachModePacket: public SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 7 +public: + CantReachModePacket(object_id_t objectId, ReturnValue_t reason): + objectId(objectId), reason(reason) { + setStart(&this->objectId); + this->objectId.setNext(&this->reason); + } + + SerializeElement objectId; //!< [EXPORT] : [COMMENT] Reply source object + SerializeElement reason; //!< [EXPORT] : [COMMENT] Reason the mode could not be reached +}; + +#endif /* FRAMEWORK_PUS_SERVICEPACKETS_SERVICE200PACKETS_H_ */ diff --git a/pus/servicepackets/Service2Packets.h b/pus/servicepackets/Service2Packets.h index f292611e..d4f3fb17 100644 --- a/pus/servicepackets/Service2Packets.h +++ b/pus/servicepackets/Service2Packets.h @@ -1,76 +1,76 @@ -#ifndef FRAMEWORK_PUS_SERVICEPACKETS_SERVICE2PACKETS_H_ -#define FRAMEWORK_PUS_SERVICEPACKETS_SERVICE2PACKETS_H_ - -#include -#include -#include -#include - -/** - * @brief Subservice 128 - * @ingroup spacepackets - */ -class RawCommand { //!< [EXPORT] : [SUBSERVICE] 128 -public: - RawCommand(const uint8_t* buffer, size_t size) { - // Deserialize Adapter to get correct endianness - SerializeAdapter::deSerialize(&objectId, &buffer, &size, - SerializeIF::Endianness::BIG); - commandBuffer = buffer; - // size is decremented by AutoSerializeAdapter, - // remaining size is data size - dataSize = size; - } - object_id_t getObjectId() const { - return objectId; - } - - const uint8_t* getCommand() { - return commandBuffer; - } - - size_t getCommandSize() const { - return dataSize; - } -private: - object_id_t objectId = 0; - const uint8_t* commandBuffer = nullptr; //!< [EXPORT] : [MAXSIZE] 256 Bytes - size_t dataSize = 0; //!< [EXPORT] : [IGNORE] -}; - - -/** - * @brief Subservice 129: Command packet to set wiretapping mode - * @ingroup spacepackets - */ -class WiretappingToggle: public SerialLinkedListAdapter{ //!< [EXPORT] : [SUBSERVICE] 129 -public: - static const size_t WIRETAPPING_COMMAND_SIZE = 5; - WiretappingToggle(){ - setStart(&objectId); - objectId.setNext(&wiretappingMode); - } - - uint8_t getWiretappingMode() const { - return wiretappingMode.entry; - } -private: - SerializeElement objectId; - SerializeElement wiretappingMode; //!< [EXPORT] : [INPUT] Mode 0: OFF, Mode 1: RAW -}; - - -/** - * @brief Subservices 130 and 131: TM packets - * @ingroup spacepackets - */ -class WiretappingPacket { //!< [EXPORT] : [SUBSERVICE] 130, 131 -public: - object_id_t objectId; //!< [EXPORT] : [COMMENT] Object ID of source object - const uint8_t* data; //!< [EXPORT] : [MAXSIZE] Raw Command Max. Size - WiretappingPacket(object_id_t objectId, const uint8_t* buffer): - objectId(objectId), data(buffer) { - } -}; - -#endif /* FRAMEWORK_PUS_SERVICEPACKETS_SERVICE2PACKETS_H_ */ +#ifndef FRAMEWORK_PUS_SERVICEPACKETS_SERVICE2PACKETS_H_ +#define FRAMEWORK_PUS_SERVICEPACKETS_SERVICE2PACKETS_H_ + +#include "../../action/ActionMessage.h" +#include "../../objectmanager/SystemObjectIF.h" +#include "../../serialize/SerialLinkedListAdapter.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +/** + * @brief Subservice 128 + * @ingroup spacepackets + */ +class RawCommand { //!< [EXPORT] : [SUBSERVICE] 128 +public: + RawCommand(const uint8_t* buffer, size_t size) { + // Deserialize Adapter to get correct endianness + SerializeAdapter::deSerialize(&objectId, &buffer, &size, + SerializeIF::Endianness::BIG); + commandBuffer = buffer; + // size is decremented by AutoSerializeAdapter, + // remaining size is data size + dataSize = size; + } + object_id_t getObjectId() const { + return objectId; + } + + const uint8_t* getCommand() { + return commandBuffer; + } + + size_t getCommandSize() const { + return dataSize; + } +private: + object_id_t objectId = 0; + const uint8_t* commandBuffer = nullptr; //!< [EXPORT] : [MAXSIZE] 256 Bytes + size_t dataSize = 0; //!< [EXPORT] : [IGNORE] +}; + + +/** + * @brief Subservice 129: Command packet to set wiretapping mode + * @ingroup spacepackets + */ +class WiretappingToggle: public SerialLinkedListAdapter{ //!< [EXPORT] : [SUBSERVICE] 129 +public: + static const size_t WIRETAPPING_COMMAND_SIZE = 5; + WiretappingToggle(){ + setStart(&objectId); + objectId.setNext(&wiretappingMode); + } + + uint8_t getWiretappingMode() const { + return wiretappingMode.entry; + } +private: + SerializeElement objectId; + SerializeElement wiretappingMode; //!< [EXPORT] : [INPUT] Mode 0: OFF, Mode 1: RAW +}; + + +/** + * @brief Subservices 130 and 131: TM packets + * @ingroup spacepackets + */ +class WiretappingPacket { //!< [EXPORT] : [SUBSERVICE] 130, 131 +public: + object_id_t objectId; //!< [EXPORT] : [COMMENT] Object ID of source object + const uint8_t* data; //!< [EXPORT] : [MAXSIZE] Raw Command Max. Size + WiretappingPacket(object_id_t objectId, const uint8_t* buffer): + objectId(objectId), data(buffer) { + } +}; + +#endif /* FRAMEWORK_PUS_SERVICEPACKETS_SERVICE2PACKETS_H_ */ diff --git a/pus/servicepackets/Service5Packets.h b/pus/servicepackets/Service5Packets.h index 14219c93..9655608a 100644 --- a/pus/servicepackets/Service5Packets.h +++ b/pus/servicepackets/Service5Packets.h @@ -1,8 +1,8 @@ #ifndef MISSION_PUS_SERVICEPACKETS_SERVICE5PACKETS_H_ #define MISSION_PUS_SERVICEPACKETS_SERVICE5PACKETS_H_ -#include -#include +#include "../../serialize/SerializeAdapter.h" +#include "../../tmtcservices/VerificationCodes.h" /** diff --git a/pus/servicepackets/Service8Packets.h b/pus/servicepackets/Service8Packets.h index 8ea0d108..14f8b6e6 100644 --- a/pus/servicepackets/Service8Packets.h +++ b/pus/servicepackets/Service8Packets.h @@ -1,121 +1,121 @@ -#ifndef FRAMEWORK_PUS_SERVICEPACKETS_SERVICE8PACKETS_H_ -#define FRAMEWORK_PUS_SERVICEPACKETS_SERVICE8PACKETS_H_ - -#include -#include -#include -#include -#include -#include - - -/** - * @brief Subservice 128 - * @ingroup spacepackets - */ -class DirectCommand: public SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 128 -public: - - DirectCommand(const uint8_t* tcData, size_t size) { - SerializeAdapter::deSerialize(&objectId, &tcData, &size, - SerializeIF::Endianness::BIG); - SerializeAdapter::deSerialize(&actionId, &tcData, &size, - SerializeIF::Endianness::BIG); - parameterBuffer = tcData; - parametersSize = size; - } - - ActionId_t getActionId() const { - return actionId; - } - - object_id_t getObjectId() const { - return objectId; - } - - const uint8_t* getParameters() { - return parameterBuffer; - } - - uint32_t getParametersSize() const { - return parametersSize; - } - -private: - DirectCommand(const DirectCommand &command); - object_id_t objectId; - ActionId_t actionId; - uint32_t parametersSize; //!< [EXPORT] : [IGNORE] - const uint8_t * parameterBuffer; //!< [EXPORT] : [MAXSIZE] 65535 Bytes - -}; - - -/** - * @brief Subservice 130 - * Data reply (subservice 130) consists of - * 1. Target Object ID - * 2. Action ID - * 3. Data - * @ingroup spacepackets - */ -class DataReply: public SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 130 -public: - typedef uint16_t typeOfMaxDataSize; - static const uint16_t MAX_DATA_LENGTH = sizeof(typeOfMaxDataSize); - DataReply(object_id_t objectId_, ActionId_t actionId_, - const uint8_t * replyDataBuffer_ = NULL, uint16_t replyDataSize_ = 0): - objectId(objectId_), actionId(actionId_), replyData(replyDataBuffer_,replyDataSize_){ - setLinks(); - } - -private: - DataReply(const DataReply &reply); - void setLinks() { - setStart(&objectId); - objectId.setNext(&actionId); - actionId.setNext(&replyData); - } - SerializeElement objectId; - SerializeElement actionId; - SerializeElement> replyData; -}; - - -/** - * @brief Subservice 132 - * @details - * Not used yet. Telecommand Verification takes care of this. - * @ingroup spacepackets - */ -class DirectReply: public SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 132 -public: - typedef uint16_t typeOfMaxDataSize; - static const uint16_t MAX_DATA_LENGTH = sizeof(typeOfMaxDataSize); - - DirectReply(object_id_t objectId_, ActionId_t actionId_, ReturnValue_t returnCode_, - bool isStep_ = false, uint8_t step_ = 0): - isStep(isStep_), objectId(objectId_), actionId(actionId_), - returnCode(returnCode_),step(step_) { - setLinks(); - } -private: - - void setLinks() { - setStart(&objectId); - objectId.setNext(&actionId); - actionId.setNext(&returnCode); - if(isStep) { - returnCode.setNext(&step); - } - } - - bool isStep; //!< [EXPORT] : [IGNORE] - SerializeElement objectId; //!< [EXPORT] : [IGNORE] - SerializeElement actionId; //!< [EXPORT] : [IGNORE] - SerializeElement returnCode; //!< [EXPORT] : [IGNORE] - SerializeElement step; //!< [EXPORT] : [OPTIONAL] [IGNORE] - -}; - -#endif /* FRAMEWORK_PUS_SERVICEPACKETS_SERVICE8PACKETS_H_ */ +#ifndef FRAMEWORK_PUS_SERVICEPACKETS_SERVICE8PACKETS_H_ +#define FRAMEWORK_PUS_SERVICEPACKETS_SERVICE8PACKETS_H_ + +#include "../../action/ActionMessage.h" +#include "../../objectmanager/SystemObjectIF.h" +#include "../../serialize/SerialBufferAdapter.h" +#include "../../serialize/SerializeElement.h" +#include "../../serialize/SerialLinkedListAdapter.h" +#include "../../serialize/SerialFixedArrayListAdapter.h" + + +/** + * @brief Subservice 128 + * @ingroup spacepackets + */ +class DirectCommand: public SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 128 +public: + + DirectCommand(const uint8_t* tcData, size_t size) { + SerializeAdapter::deSerialize(&objectId, &tcData, &size, + SerializeIF::Endianness::BIG); + SerializeAdapter::deSerialize(&actionId, &tcData, &size, + SerializeIF::Endianness::BIG); + parameterBuffer = tcData; + parametersSize = size; + } + + ActionId_t getActionId() const { + return actionId; + } + + object_id_t getObjectId() const { + return objectId; + } + + const uint8_t* getParameters() { + return parameterBuffer; + } + + uint32_t getParametersSize() const { + return parametersSize; + } + +private: + DirectCommand(const DirectCommand &command); + object_id_t objectId; + ActionId_t actionId; + uint32_t parametersSize; //!< [EXPORT] : [IGNORE] + const uint8_t * parameterBuffer; //!< [EXPORT] : [MAXSIZE] 65535 Bytes + +}; + + +/** + * @brief Subservice 130 + * Data reply (subservice 130) consists of + * 1. Target Object ID + * 2. Action ID + * 3. Data + * @ingroup spacepackets + */ +class DataReply: public SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 130 +public: + typedef uint16_t typeOfMaxDataSize; + static const uint16_t MAX_DATA_LENGTH = sizeof(typeOfMaxDataSize); + DataReply(object_id_t objectId_, ActionId_t actionId_, + const uint8_t * replyDataBuffer_ = NULL, uint16_t replyDataSize_ = 0): + objectId(objectId_), actionId(actionId_), replyData(replyDataBuffer_,replyDataSize_){ + setLinks(); + } + +private: + DataReply(const DataReply &reply); + void setLinks() { + setStart(&objectId); + objectId.setNext(&actionId); + actionId.setNext(&replyData); + } + SerializeElement objectId; + SerializeElement actionId; + SerializeElement> replyData; +}; + + +/** + * @brief Subservice 132 + * @details + * Not used yet. Telecommand Verification takes care of this. + * @ingroup spacepackets + */ +class DirectReply: public SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 132 +public: + typedef uint16_t typeOfMaxDataSize; + static const uint16_t MAX_DATA_LENGTH = sizeof(typeOfMaxDataSize); + + DirectReply(object_id_t objectId_, ActionId_t actionId_, ReturnValue_t returnCode_, + bool isStep_ = false, uint8_t step_ = 0): + isStep(isStep_), objectId(objectId_), actionId(actionId_), + returnCode(returnCode_),step(step_) { + setLinks(); + } +private: + + void setLinks() { + setStart(&objectId); + objectId.setNext(&actionId); + actionId.setNext(&returnCode); + if(isStep) { + returnCode.setNext(&step); + } + } + + bool isStep; //!< [EXPORT] : [IGNORE] + SerializeElement objectId; //!< [EXPORT] : [IGNORE] + SerializeElement actionId; //!< [EXPORT] : [IGNORE] + SerializeElement returnCode; //!< [EXPORT] : [IGNORE] + SerializeElement step; //!< [EXPORT] : [OPTIONAL] [IGNORE] + +}; + +#endif /* FRAMEWORK_PUS_SERVICEPACKETS_SERVICE8PACKETS_H_ */ diff --git a/returnvalues/HasReturnvaluesIF.h b/returnvalues/HasReturnvaluesIF.h index d231f4ee..5fef91dd 100644 --- a/returnvalues/HasReturnvaluesIF.h +++ b/returnvalues/HasReturnvaluesIF.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_RETURNVALUES_HASRETURNVALUESIF_H_ #define FRAMEWORK_RETURNVALUES_HASRETURNVALUESIF_H_ -#include +#include "FwClassIds.h" #include #include diff --git a/rmap/RMAP.cpp b/rmap/RMAP.cpp index 4c95f6c9..4ab8b17b 100644 --- a/rmap/RMAP.cpp +++ b/rmap/RMAP.cpp @@ -1,7 +1,7 @@ -#include -#include -#include -#include +#include "../devicehandlers/DeviceCommunicationIF.h" +#include "rmapStructs.h" +#include "RMAP.h" +#include "RMAPChannelIF.h" #include ReturnValue_t RMAP::reset(RMAPCookie* cookie) { diff --git a/rmap/RMAP.h b/rmap/RMAP.h index 195574f8..d14320cb 100644 --- a/rmap/RMAP.h +++ b/rmap/RMAP.h @@ -1,8 +1,8 @@ #ifndef RMAPpp_H_ #define RMAPpp_H_ -#include -#include +#include "../returnvalues/HasReturnvaluesIF.h" +#include "RMAPCookie.h" //SHOULDTODO: clean up includes for RMAP, should be enough to include RMAP.h but right now it's quite chaotic... diff --git a/rmap/RMAPChannelIF.h b/rmap/RMAPChannelIF.h index 6549c8ef..dac4a722 100644 --- a/rmap/RMAPChannelIF.h +++ b/rmap/RMAPChannelIF.h @@ -1,8 +1,8 @@ #ifndef RMAPCHANNELIF_H_ #define RMAPCHANNELIF_H_ -#include -#include +#include "RMAPCookie.h" +#include "../returnvalues/HasReturnvaluesIF.h" class RMAPChannelIF { public: diff --git a/rmap/RMAPCookie.cpp b/rmap/RMAPCookie.cpp index 5bf2ba9f..597f066c 100644 --- a/rmap/RMAPCookie.cpp +++ b/rmap/RMAPCookie.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "RMAPChannelIF.h" +#include "RMAPCookie.h" #include diff --git a/rmap/RMAPCookie.h b/rmap/RMAPCookie.h index 4890c516..4c6081bd 100644 --- a/rmap/RMAPCookie.h +++ b/rmap/RMAPCookie.h @@ -1,8 +1,8 @@ #ifndef RMAPCOOKIE_H_ #define RMAPCOOKIE_H_ -#include -#include +#include "../devicehandlers/CookieIF.h" +#include "rmapStructs.h" class RMAPChannelIF; diff --git a/rmap/RmapDeviceCommunicationIF.cpp b/rmap/RmapDeviceCommunicationIF.cpp index 674d050d..db4a75b5 100644 --- a/rmap/RmapDeviceCommunicationIF.cpp +++ b/rmap/RmapDeviceCommunicationIF.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "RmapDeviceCommunicationIF.h" +#include "RMAP.h" //TODO Cast here are all potential bugs RmapDeviceCommunicationIF::~RmapDeviceCommunicationIF() { diff --git a/rmap/RmapDeviceCommunicationIF.h b/rmap/RmapDeviceCommunicationIF.h index 9d756ea2..dacc720b 100644 --- a/rmap/RmapDeviceCommunicationIF.h +++ b/rmap/RmapDeviceCommunicationIF.h @@ -1,7 +1,7 @@ #ifndef MISSION_RMAP_RMAPDEVICECOMMUNICATIONINTERFACE_H_ #define MISSION_RMAP_RMAPDEVICECOMMUNICATIONINTERFACE_H_ -#include +#include "../devicehandlers/DeviceCommunicationIF.h" /** * @brief This class is a implementation of a DeviceCommunicationIF for RMAP calls. It expects RMAPCookies or a derived class of RMAPCookies diff --git a/serialize/EndianConverter.h b/serialize/EndianConverter.h index cd5d5497..7461576d 100644 --- a/serialize/EndianConverter.h +++ b/serialize/EndianConverter.h @@ -1,7 +1,7 @@ #ifndef ENDIANSWAPPER_H_ #define ENDIANSWAPPER_H_ -#include +#include "../osal/Endiness.h" #include #include diff --git a/serialize/SerialArrayListAdapter.h b/serialize/SerialArrayListAdapter.h index 21c6951d..7576505a 100644 --- a/serialize/SerialArrayListAdapter.h +++ b/serialize/SerialArrayListAdapter.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_SERIALIZE_SERIALARRAYLISTADAPTER_H_ #define FRAMEWORK_SERIALIZE_SERIALARRAYLISTADAPTER_H_ -#include -#include +#include "../container/ArrayList.h" +#include "SerializeIF.h" #include /** diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index d4d8d1c7..5dd01f54 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -1,4 +1,4 @@ -#include +#include "SerialBufferAdapter.h" #include diff --git a/serialize/SerialBufferAdapter.h b/serialize/SerialBufferAdapter.h index 78d42b80..c27a5424 100644 --- a/serialize/SerialBufferAdapter.h +++ b/serialize/SerialBufferAdapter.h @@ -1,8 +1,8 @@ #ifndef SERIALBUFFERADAPTER_H_ #define SERIALBUFFERADAPTER_H_ -#include -#include +#include "SerializeIF.h" +#include "SerializeAdapter.h" /** * \ingroup serialize diff --git a/serialize/SerialFixedArrayListAdapter.h b/serialize/SerialFixedArrayListAdapter.h index a2e683bf..38e0d438 100644 --- a/serialize/SerialFixedArrayListAdapter.h +++ b/serialize/SerialFixedArrayListAdapter.h @@ -1,8 +1,8 @@ #ifndef SERIALFIXEDARRAYLISTADAPTER_H_ #define SERIALFIXEDARRAYLISTADAPTER_H_ -#include -#include +#include "../container/FixedArrayList.h" +#include "SerialArrayListAdapter.h" /** * \ingroup serialize diff --git a/serialize/SerialLinkedListAdapter.h b/serialize/SerialLinkedListAdapter.h index 7b10e331..5de8c242 100644 --- a/serialize/SerialLinkedListAdapter.h +++ b/serialize/SerialLinkedListAdapter.h @@ -7,10 +7,10 @@ #ifndef SERIALLINKEDLISTADAPTER_H_ #define SERIALLINKEDLISTADAPTER_H_ -#include -#include -#include -#include +#include "../container/SinglyLinkedList.h" +#include "SerializeAdapter.h" +#include "SerializeElement.h" +#include "SerializeIF.h" //This is where we need the SerializeAdapter! /** diff --git a/serialize/SerializeAdapter.h b/serialize/SerializeAdapter.h index ec727515..af5ec116 100644 --- a/serialize/SerializeAdapter.h +++ b/serialize/SerializeAdapter.h @@ -1,10 +1,10 @@ #ifndef SERIALIZEADAPTER_H_ #define SERIALIZEADAPTER_H_ -#include -#include -#include -#include +#include "../container/IsDerivedFrom.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "EndianConverter.h" +#include "SerializeIF.h" #include /** diff --git a/serialize/SerializeElement.h b/serialize/SerializeElement.h index 3941e9fb..ffedeff9 100644 --- a/serialize/SerializeElement.h +++ b/serialize/SerializeElement.h @@ -1,8 +1,8 @@ #ifndef SERIALIZEELEMENT_H_ #define SERIALIZEELEMENT_H_ -#include -#include +#include "../container/SinglyLinkedList.h" +#include "SerializeAdapter.h" #include /** diff --git a/serialize/SerializeIF.h b/serialize/SerializeIF.h index 14244a7a..9ed52d29 100644 --- a/serialize/SerializeIF.h +++ b/serialize/SerializeIF.h @@ -1,7 +1,7 @@ #ifndef SERIALIZEIF_H_ #define SERIALIZEIF_H_ -#include +#include "../returnvalues/HasReturnvaluesIF.h" #include /** diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 8c510eac..68fc4dec 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "../timemanager/Clock.h" +#include "ServiceInterfaceBuffer.h" #include #include @@ -127,7 +127,7 @@ std::string* ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { #ifdef UT699 -#include +#include "../osal/rtems/Interrupt.h" ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) { diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index 7a2ce2ee..c5d5b258 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ #define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ -#include +#include "../returnvalues/HasReturnvaluesIF.h" #include #include #include diff --git a/serviceinterface/ServiceInterfaceStream.cpp b/serviceinterface/ServiceInterfaceStream.cpp index 31bc7c73..5b7b9f00 100644 --- a/serviceinterface/ServiceInterfaceStream.cpp +++ b/serviceinterface/ServiceInterfaceStream.cpp @@ -1,4 +1,4 @@ -#include +#include "ServiceInterfaceStream.h" ServiceInterfaceStream::ServiceInterfaceStream(std::string setMessage, bool addCrToPreamble, bool buffered, bool errStream, uint16_t port) : diff --git a/serviceinterface/ServiceInterfaceStream.h b/serviceinterface/ServiceInterfaceStream.h index dc111459..76fa1bf2 100644 --- a/serviceinterface/ServiceInterfaceStream.h +++ b/serviceinterface/ServiceInterfaceStream.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ #define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ -#include +#include "ServiceInterfaceBuffer.h" #include #include diff --git a/storagemanager/LocalPool.h b/storagemanager/LocalPool.h index 3ddcc491..ad3deee1 100644 --- a/storagemanager/LocalPool.h +++ b/storagemanager/LocalPool.h @@ -7,11 +7,11 @@ #ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ #define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ -#include -#include -#include -#include -#include +#include "../objectmanager/SystemObject.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "StorageManagerIF.h" +#include "../objectmanager/ObjectManagerIF.h" +#include "../internalError/InternalErrorReporterIF.h" #include /** @@ -178,6 +178,6 @@ private: ReturnValue_t findEmpty(uint16_t pool_index, uint16_t* element); }; -#include +#include "LocalPool.tpp" #endif /* FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ */ diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index 67534cc5..0b101d66 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -2,8 +2,8 @@ #define POOLMANAGER_H_ -#include -#include +#include "LocalPool.h" +#include "../ipc/MutexHelper.h" /** * @brief The PoolManager class provides an intermediate data storage with diff --git a/storagemanager/StorageManagerIF.h b/storagemanager/StorageManagerIF.h index 101e0dcd..7c194d72 100644 --- a/storagemanager/StorageManagerIF.h +++ b/storagemanager/StorageManagerIF.h @@ -1,8 +1,8 @@ #ifndef STORAGEMANAGERIF_H_H #define STORAGEMANAGERIF_H_H -#include -#include +#include "../events/Event.h" +#include "../returnvalues/HasReturnvaluesIF.h" #include /** diff --git a/subsystem/Subsystem.cpp b/subsystem/Subsystem.cpp index fcf2e189..ff3ef634 100644 --- a/subsystem/Subsystem.cpp +++ b/subsystem/Subsystem.cpp @@ -1,10 +1,10 @@ -#include -#include -#include -#include -#include -#include -#include +#include "../health/HealthMessage.h" +#include "../objectmanager/ObjectManagerIF.h" +#include "../serialize/SerialArrayListAdapter.h" +#include "../serialize/SerialFixedArrayListAdapter.h" +#include "../serialize/SerializeElement.h" +#include "../serialize/SerialLinkedListAdapter.h" +#include "Subsystem.h" #include Subsystem::Subsystem(object_id_t setObjectId, object_id_t parent, diff --git a/subsystem/Subsystem.h b/subsystem/Subsystem.h index ca1020b9..a40b8028 100644 --- a/subsystem/Subsystem.h +++ b/subsystem/Subsystem.h @@ -1,13 +1,13 @@ #ifndef SUBSYSTEM_H_ #define SUBSYSTEM_H_ -#include -#include -#include -#include -#include -#include -#include +#include "../container/FixedArrayList.h" +#include "../container/FixedMap.h" +#include "../container/HybridIterator.h" +#include "../container/SinglyLinkedList.h" +#include "../serialize/SerialArrayListAdapter.h" +#include "modes/ModeDefinitions.h" +#include "SubsystemBase.h" class Subsystem: public SubsystemBase, public HasModeSequenceIF { public: diff --git a/subsystem/SubsystemBase.cpp b/subsystem/SubsystemBase.cpp index cceb2d41..56ae1062 100644 --- a/subsystem/SubsystemBase.cpp +++ b/subsystem/SubsystemBase.cpp @@ -1,7 +1,7 @@ -#include -#include -#include -#include +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "SubsystemBase.h" +#include "../ipc/QueueFactory.h" SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent, Mode_t initialMode, uint16_t commandQueueDepth) : diff --git a/subsystem/SubsystemBase.h b/subsystem/SubsystemBase.h index 3294c46d..61a7eaef 100644 --- a/subsystem/SubsystemBase.h +++ b/subsystem/SubsystemBase.h @@ -1,15 +1,15 @@ #ifndef SUBSYSTEMBASE_H_ #define SUBSYSTEMBASE_H_ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "../container/HybridIterator.h" +#include "../health/HasHealthIF.h" +#include "../health/HealthHelper.h" +#include "../modes/HasModesIF.h" +#include "../objectmanager/SystemObject.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "modes/HasModeSequenceIF.h" +#include "../tasks/ExecutableObjectIF.h" +#include "../ipc/MessageQueueIF.h" #include class SubsystemBase: public SystemObject, diff --git a/subsystem/modes/HasModeSequenceIF.h b/subsystem/modes/HasModeSequenceIF.h index e03de410..70b1667e 100644 --- a/subsystem/modes/HasModeSequenceIF.h +++ b/subsystem/modes/HasModeSequenceIF.h @@ -1,9 +1,9 @@ #ifndef HASMODESEQUENCEIF_H_ #define HASMODESEQUENCEIF_H_ -#include -#include -#include +#include "ModeDefinitions.h" +#include "ModeSequenceMessage.h" +#include "ModeStoreIF.h" class HasModeSequenceIF { diff --git a/subsystem/modes/ModeDefinitions.h b/subsystem/modes/ModeDefinitions.h index 153710af..a865ab0c 100644 --- a/subsystem/modes/ModeDefinitions.h +++ b/subsystem/modes/ModeDefinitions.h @@ -1,10 +1,10 @@ #ifndef MODEDEFINITIONS_H_ #define MODEDEFINITIONS_H_ -#include -#include -#include -#include +#include "../../modes/HasModesIF.h" +#include "../../objectmanager/SystemObjectIF.h" +#include "../../serialize/SerializeIF.h" +#include "../../serialize/SerialLinkedListAdapter.h" class ModeListEntry: public SerializeIF, public LinkedElement { public: ModeListEntry() : diff --git a/subsystem/modes/ModeSequenceMessage.cpp b/subsystem/modes/ModeSequenceMessage.cpp index 31661739..33019f58 100644 --- a/subsystem/modes/ModeSequenceMessage.cpp +++ b/subsystem/modes/ModeSequenceMessage.cpp @@ -1,8 +1,8 @@ -#include -#include -#include -#include -#include +#include "../../objectmanager/ObjectManagerIF.h" +#include "../../objectmanager/ObjectManagerIF.h" +#include "../../objectmanager/ObjectManagerIF.h" +#include "../../storagemanager/StorageManagerIF.h" +#include "ModeSequenceMessage.h" void ModeSequenceMessage::setModeSequenceMessage(CommandMessage* message, Command_t command, Mode_t sequence, store_address_t storeAddress) { diff --git a/subsystem/modes/ModeSequenceMessage.h b/subsystem/modes/ModeSequenceMessage.h index 830cf532..9f99cc99 100644 --- a/subsystem/modes/ModeSequenceMessage.h +++ b/subsystem/modes/ModeSequenceMessage.h @@ -1,9 +1,9 @@ #ifndef MODESEQUENCEMESSAGE_H_ #define MODESEQUENCEMESSAGE_H_ -#include -#include -#include +#include "../../ipc/CommandMessage.h" +#include "../../storagemanager/StorageManagerIF.h" +#include "ModeDefinitions.h" class ModeSequenceMessage { public: diff --git a/subsystem/modes/ModeStore.cpp b/subsystem/modes/ModeStore.cpp index 2aa02087..217e177c 100644 --- a/subsystem/modes/ModeStore.cpp +++ b/subsystem/modes/ModeStore.cpp @@ -1,4 +1,4 @@ -#include +#include "ModeStore.h" #ifdef USE_MODESTORE diff --git a/subsystem/modes/ModeStore.h b/subsystem/modes/ModeStore.h index cbc45b5a..0bf856a3 100644 --- a/subsystem/modes/ModeStore.h +++ b/subsystem/modes/ModeStore.h @@ -3,10 +3,10 @@ #ifdef USE_MODESTORE -#include -#include -#include -#include +#include "../../container/ArrayList.h" +#include "../../container/SinglyLinkedList.h" +#include "../../objectmanager/SystemObject.h" +#include "ModeStoreIF.h" class ModeStore: public ModeStoreIF, public SystemObject { public: diff --git a/subsystem/modes/ModeStoreIF.h b/subsystem/modes/ModeStoreIF.h index 7be7a5a7..e5cac3b2 100644 --- a/subsystem/modes/ModeStoreIF.h +++ b/subsystem/modes/ModeStoreIF.h @@ -3,10 +3,10 @@ #ifdef USE_MODESTORE -#include -#include -#include -#include +#include "../../container/ArrayList.h" +#include "../../container/SinglyLinkedList.h" +#include "../../returnvalues/HasReturnvaluesIF.h" +#include "ModeDefinitions.h" class ModeStoreIF { public: diff --git a/tasks/ExecutableObjectIF.h b/tasks/ExecutableObjectIF.h index d716cdfb..06b837db 100644 --- a/tasks/ExecutableObjectIF.h +++ b/tasks/ExecutableObjectIF.h @@ -3,7 +3,7 @@ class PeriodicTaskIF; -#include +#include "../returnvalues/HasReturnvaluesIF.h" #include /** diff --git a/tasks/FixedTimeslotTaskIF.h b/tasks/FixedTimeslotTaskIF.h index 3a3582fb..421978f0 100644 --- a/tasks/FixedTimeslotTaskIF.h +++ b/tasks/FixedTimeslotTaskIF.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_TASKS_FIXEDTIMESLOTTASKIF_H_ #define FRAMEWORK_TASKS_FIXEDTIMESLOTTASKIF_H_ -#include -#include +#include "../objectmanager/ObjectManagerIF.h" +#include "PeriodicTaskIF.h" /** * Following the same principle as the base class IF. This is the interface for a Fixed timeslot task diff --git a/tasks/PeriodicTaskIF.h b/tasks/PeriodicTaskIF.h index 6f490977..17a64b96 100644 --- a/tasks/PeriodicTaskIF.h +++ b/tasks/PeriodicTaskIF.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_TASK_PERIODICTASKIF_H_ #define FRAMEWORK_TASK_PERIODICTASKIF_H_ -#include -#include +#include "../objectmanager/SystemObjectIF.h" +#include "../timemanager/Clock.h" #include class ExecutableObjectIF; diff --git a/tasks/TaskFactory.h b/tasks/TaskFactory.h index 8a59adf1..cbf2272c 100644 --- a/tasks/TaskFactory.h +++ b/tasks/TaskFactory.h @@ -2,8 +2,8 @@ #define FRAMEWORK_TASKS_TASKFACTORY_H_ #include -#include -#include +#include "FixedTimeslotTaskIF.h" +#include "Typedef.h" /** * Singleton Class that produces Tasks. diff --git a/tcdistribution/CCSDSDistributor.cpp b/tcdistribution/CCSDSDistributor.cpp index 878b8f7d..1ebb3185 100644 --- a/tcdistribution/CCSDSDistributor.cpp +++ b/tcdistribution/CCSDSDistributor.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "CCSDSDistributor.h" +#include "../tmtcpacket/SpacePacketBase.h" CCSDSDistributor::CCSDSDistributor( uint16_t setDefaultApid, object_id_t setObjectId ) : TcDistributor( setObjectId ), default_apid( setDefaultApid ), tcStore(NULL) { diff --git a/tcdistribution/CCSDSDistributor.h b/tcdistribution/CCSDSDistributor.h index 9dce34f2..bff72092 100644 --- a/tcdistribution/CCSDSDistributor.h +++ b/tcdistribution/CCSDSDistributor.h @@ -1,11 +1,11 @@ #ifndef CCSDSDISTRIBUTOR_H_ #define CCSDSDISTRIBUTOR_H_ -#include -#include -#include -#include -#include +#include "../objectmanager/ObjectManagerIF.h" +#include "../storagemanager/StorageManagerIF.h" +#include "CCSDSDistributorIF.h" +#include "TcDistributor.h" +#include "../tmtcservices/AcceptsTelecommandsIF.h" /** * An instantiation of the CCSDSDistributorIF. * It receives Space Packets, and selects a destination depending on the APID of the telecommands. diff --git a/tcdistribution/CCSDSDistributorIF.h b/tcdistribution/CCSDSDistributorIF.h index dc1263a9..be3c2811 100644 --- a/tcdistribution/CCSDSDistributorIF.h +++ b/tcdistribution/CCSDSDistributorIF.h @@ -1,8 +1,8 @@ #ifndef CCSDSDISTRIBUTORIF_H_ #define CCSDSDISTRIBUTORIF_H_ -#include -#include +#include "../tmtcservices/AcceptsTelecommandsIF.h" +#include "../ipc/MessageQueueSenderIF.h" /** * This is the Interface to a CCSDS Distributor. * On a CCSDS Distributor, Applications (in terms of CCSDS) may register themselves, diff --git a/tcdistribution/PUSDistributor.cpp b/tcdistribution/PUSDistributor.cpp index c214f674..f77eb99d 100644 --- a/tcdistribution/PUSDistributor.cpp +++ b/tcdistribution/PUSDistributor.cpp @@ -1,8 +1,8 @@ -#include -#include -#include -#include -#include +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "CCSDSDistributorIF.h" +#include "PUSDistributor.h" +#include "../tmtcpacket/pus/TcPacketStored.h" +#include "../tmtcservices/PusVerificationReport.h" PUSDistributor::PUSDistributor(uint16_t setApid, object_id_t setObjectId, object_id_t setPacketSource) : TcDistributor(setObjectId), checker(setApid), verifyChannel(), currentPacket(), tcStatus( diff --git a/tcdistribution/PUSDistributor.h b/tcdistribution/PUSDistributor.h index 8d774662..e9d4be8c 100644 --- a/tcdistribution/PUSDistributor.h +++ b/tcdistribution/PUSDistributor.h @@ -1,12 +1,12 @@ #ifndef PUSDISTRIBUTOR_H_ #define PUSDISTRIBUTOR_H_ -#include -#include -#include -#include -#include -#include +#include "../returnvalues/HasReturnvaluesIF.h" +#include "PUSDistributorIF.h" +#include "TcDistributor.h" +#include "TcPacketCheck.h" +#include "../tmtcservices/AcceptsTelecommandsIF.h" +#include "../tmtcservices/VerificationReporter.h" /** * This class accepts PUS Telecommands and forwards them to Application services. diff --git a/tcdistribution/PUSDistributorIF.h b/tcdistribution/PUSDistributorIF.h index bb101137..5e27b35c 100644 --- a/tcdistribution/PUSDistributorIF.h +++ b/tcdistribution/PUSDistributorIF.h @@ -1,8 +1,8 @@ #ifndef PUSDISTRIBUTORIF_H_ #define PUSDISTRIBUTORIF_H_ -#include -#include +#include "../tmtcservices/AcceptsTelecommandsIF.h" +#include "../ipc/MessageQueueSenderIF.h" /** * This interface allows PUS Services to register themselves at a PUS Distributor. * \ingroup tc_distribution diff --git a/tcdistribution/TcDistributor.cpp b/tcdistribution/TcDistributor.cpp index 57921459..49a996d9 100644 --- a/tcdistribution/TcDistributor.cpp +++ b/tcdistribution/TcDistributor.cpp @@ -1,8 +1,8 @@ -#include -#include -#include -#include -#include +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "TcDistributor.h" +#include "../tmtcservices/TmTcMessage.h" +#include "../ipc/QueueFactory.h" TcDistributor::TcDistributor(object_id_t set_object_id) : SystemObject(set_object_id), tcQueue(NULL) { diff --git a/tcdistribution/TcDistributor.h b/tcdistribution/TcDistributor.h index b80f08e6..fed1cb3e 100644 --- a/tcdistribution/TcDistributor.h +++ b/tcdistribution/TcDistributor.h @@ -1,12 +1,12 @@ #ifndef TCDISTRIBUTOR_H_ #define TCDISTRIBUTOR_H_ -#include -#include -#include -#include -#include -#include -#include +#include "../objectmanager/ObjectManagerIF.h" +#include "../objectmanager/SystemObject.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../storagemanager/StorageManagerIF.h" +#include "../tasks/ExecutableObjectIF.h" +#include "../tmtcservices/TmTcMessage.h" +#include "../ipc/MessageQueueIF.h" #include diff --git a/tcdistribution/TcPacketCheck.cpp b/tcdistribution/TcPacketCheck.cpp index 90a1167f..b5881083 100644 --- a/tcdistribution/TcPacketCheck.cpp +++ b/tcdistribution/TcPacketCheck.cpp @@ -1,8 +1,8 @@ -#include -#include -#include -#include -#include +#include "../globalfunctions/CRC.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../storagemanager/StorageManagerIF.h" +#include "TcPacketCheck.h" +#include "../tmtcservices/VerificationCodes.h" TcPacketCheck::TcPacketCheck( uint16_t set_apid ) : apid(set_apid) { } diff --git a/tcdistribution/TcPacketCheck.h b/tcdistribution/TcPacketCheck.h index 88810ed7..4ba269f5 100644 --- a/tcdistribution/TcPacketCheck.h +++ b/tcdistribution/TcPacketCheck.h @@ -1,9 +1,9 @@ #ifndef TCPACKETCHECK_H_ #define TCPACKETCHECK_H_ -#include -#include -#include +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../tmtcpacket/pus/TcPacketStored.h" +#include "../tmtcservices/PusVerificationReport.h" /** * This class performs a formal packet check for incoming PUS Telecommand Packets. * Currently, it only checks if the APID and CRC are correct. diff --git a/thermal/AbstractTemperatureSensor.cpp b/thermal/AbstractTemperatureSensor.cpp index be143410..45ebe4a2 100644 --- a/thermal/AbstractTemperatureSensor.cpp +++ b/thermal/AbstractTemperatureSensor.cpp @@ -1,5 +1,5 @@ #include "AbstractTemperatureSensor.h" -#include +#include "../ipc/QueueFactory.h" AbstractTemperatureSensor::AbstractTemperatureSensor(object_id_t setObjectid, ThermalModuleIF *thermalModule) : diff --git a/thermal/AbstractTemperatureSensor.h b/thermal/AbstractTemperatureSensor.h index 75437dca..726ab9f4 100644 --- a/thermal/AbstractTemperatureSensor.h +++ b/thermal/AbstractTemperatureSensor.h @@ -1,12 +1,12 @@ #ifndef ABSTRACTSENSOR_H_ #define ABSTRACTSENSOR_H_ -#include -#include -#include -#include -#include -#include +#include "../health/HasHealthIF.h" +#include "../health/HealthHelper.h" +#include "../objectmanager/SystemObject.h" +#include "../tasks/ExecutableObjectIF.h" +#include "../parameters/ParameterHelper.h" +#include "../ipc/MessageQueueIF.h" #include "ThermalModuleIF.h" #include "tcsDefinitions.h" diff --git a/thermal/CoreComponent.h b/thermal/CoreComponent.h index f7e7aff8..48a49f7d 100644 --- a/thermal/CoreComponent.h +++ b/thermal/CoreComponent.h @@ -1,12 +1,12 @@ #ifndef MISSION_CONTROLLERS_TCS_CORECOMPONENT_H_ #define MISSION_CONTROLLERS_TCS_CORECOMPONENT_H_ -#include -#include -#include -#include -#include -#include +#include "../datapool/DataSet.h" +#include "../datapool/PoolVariable.h" +#include "ThermalComponentIF.h" +#include "AbstractTemperatureSensor.h" +#include "ThermalModule.h" +#include "ThermalMonitor.h" class CoreComponent: public ThermalComponentIF { public: diff --git a/thermal/Heater.cpp b/thermal/Heater.cpp index 29daa15d..1301e2e0 100644 --- a/thermal/Heater.cpp +++ b/thermal/Heater.cpp @@ -1,8 +1,8 @@ -#include +#include "../devicehandlers/DeviceHandlerFailureIsolation.h" #include "Heater.h" -#include -#include +#include "../power/Fuse.h" +#include "../ipc/QueueFactory.h" Heater::Heater(uint32_t objectId, uint8_t switch0, uint8_t switch1) : HealthDevice(objectId, 0), internalState(STATE_OFF), powerSwitcher( diff --git a/thermal/Heater.h b/thermal/Heater.h index 41004e03..63fe2066 100644 --- a/thermal/Heater.h +++ b/thermal/Heater.h @@ -1,11 +1,11 @@ #ifndef FRAMEWORK_THERMAL_HEATER_H_ #define FRAMEWORK_THERMAL_HEATER_H_ -#include -#include -#include -#include -#include +#include "../devicehandlers/HealthDevice.h" +#include "../parameters/ParameterHelper.h" +#include "../power/PowerSwitchIF.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../timemanager/Countdown.h" #include //class RedundantHeater; diff --git a/thermal/RedundantHeater.h b/thermal/RedundantHeater.h index 29791a9a..ab745a69 100644 --- a/thermal/RedundantHeater.h +++ b/thermal/RedundantHeater.h @@ -1,7 +1,7 @@ #ifndef REDUNDANTHEATER_H_ #define REDUNDANTHEATER_H_ -#include +#include "Heater.h" class RedundantHeater { public: diff --git a/thermal/TemperatureSensor.h b/thermal/TemperatureSensor.h index de280d87..356ca722 100644 --- a/thermal/TemperatureSensor.h +++ b/thermal/TemperatureSensor.h @@ -1,9 +1,9 @@ #ifndef TEMPERATURESENSOR_H_ #define TEMPERATURESENSOR_H_ -#include +#include "../datapool/DataSet.h" #include "AbstractTemperatureSensor.h" -#include +#include "../monitoring/LimitMonitor.h" template class TemperatureSensor: public AbstractTemperatureSensor { diff --git a/thermal/ThermalComponentIF.h b/thermal/ThermalComponentIF.h index ad8dbd0a..522d4e44 100644 --- a/thermal/ThermalComponentIF.h +++ b/thermal/ThermalComponentIF.h @@ -1,10 +1,10 @@ #ifndef THERMALCOMPONENTIF_H_ #define THERMALCOMPONENTIF_H_ -#include -#include -#include -#include +#include "../events/Event.h" +#include "../parameters/HasParametersIF.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../objectmanager/SystemObjectIF.h" class ThermalComponentIF : public HasParametersIF { public: diff --git a/thermal/ThermalModule.cpp b/thermal/ThermalModule.cpp index 24a4c90d..c573008e 100644 --- a/thermal/ThermalModule.cpp +++ b/thermal/ThermalModule.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "../monitoring/LimitViolationReporter.h" +#include "../monitoring/MonitoringMessageContent.h" #include "ThermalModule.h" #include "AbstractTemperatureSensor.h" diff --git a/thermal/ThermalModule.h b/thermal/ThermalModule.h index d8ac7d73..19ab9a54 100644 --- a/thermal/ThermalModule.h +++ b/thermal/ThermalModule.h @@ -1,10 +1,10 @@ #ifndef THERMALMODULE_H_ #define THERMALMODULE_H_ -#include -#include -#include -#include +#include "../datapool/DataSet.h" +#include "../datapool/PoolVariable.h" +#include "../devicehandlers/HealthDevice.h" +#include "../events/EventReportingProxyIF.h" #include "ThermalModuleIF.h" #include #include "tcsDefinitions.h" diff --git a/thermal/ThermalMonitor.cpp b/thermal/ThermalMonitor.cpp index 773fa084..11abfbe5 100644 --- a/thermal/ThermalMonitor.cpp +++ b/thermal/ThermalMonitor.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "ThermalMonitor.h" +#include "ThermalComponentIF.h" +#include "../monitoring/MonitoringIF.h" ThermalMonitor::~ThermalMonitor() { } diff --git a/thermal/ThermalMonitor.h b/thermal/ThermalMonitor.h index 6aca55ab..5c6806c1 100644 --- a/thermal/ThermalMonitor.h +++ b/thermal/ThermalMonitor.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_THERMAL_THERMALMONITOR_H_ #define FRAMEWORK_THERMAL_THERMALMONITOR_H_ -#include -#include +#include "../monitoring/MonitorReporter.h" +#include "ThermalComponentIF.h" class ThermalMonitor: public MonitorReporter { public: diff --git a/timemanager/CCSDSTime.cpp b/timemanager/CCSDSTime.cpp index 71b2539d..eddbb97b 100644 --- a/timemanager/CCSDSTime.cpp +++ b/timemanager/CCSDSTime.cpp @@ -1,4 +1,4 @@ -#include +#include "CCSDSTime.h" #include #include #include diff --git a/timemanager/CCSDSTime.h b/timemanager/CCSDSTime.h index 92060d5d..8563cf0f 100644 --- a/timemanager/CCSDSTime.h +++ b/timemanager/CCSDSTime.h @@ -3,8 +3,8 @@ // COULDDO: have calls in Clock.h which return time quality and use timespec accordingly -#include -#include +#include "Clock.h" +#include "../returnvalues/HasReturnvaluesIF.h" #include bool operator<(const timeval& lhs, const timeval& rhs); diff --git a/timemanager/Clock.h b/timemanager/Clock.h index 121c63df..6f6a97da 100644 --- a/timemanager/Clock.h +++ b/timemanager/Clock.h @@ -1,9 +1,9 @@ #ifndef FRAMEWORK_TIMEMANAGER_CLOCK_H_ #define FRAMEWORK_TIMEMANAGER_CLOCK_H_ -#include -#include -#include +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../ipc/MutexFactory.h" +#include "../globalfunctions/timevalOperations.h" #include #include diff --git a/timemanager/Countdown.cpp b/timemanager/Countdown.cpp index e6565914..d5695730 100644 --- a/timemanager/Countdown.cpp +++ b/timemanager/Countdown.cpp @@ -6,7 +6,7 @@ */ -#include +#include "Countdown.h" Countdown::Countdown(uint32_t initialTimeout) : startTime(0), timeout(initialTimeout) { } diff --git a/timemanager/Countdown.h b/timemanager/Countdown.h index 57a11f91..b86d9fe0 100644 --- a/timemanager/Countdown.h +++ b/timemanager/Countdown.h @@ -8,7 +8,7 @@ #ifndef COUNTDOWN_H_ #define COUNTDOWN_H_ -#include +#include "Clock.h" class Countdown { private: diff --git a/timemanager/Stopwatch.cpp b/timemanager/Stopwatch.cpp index 52118d58..00373bd7 100644 --- a/timemanager/Stopwatch.cpp +++ b/timemanager/Stopwatch.cpp @@ -1,57 +1,57 @@ -#include -#include -#include - -Stopwatch::Stopwatch(bool displayOnDestruction, - StopwatchDisplayMode displayMode): displayOnDestruction( - displayOnDestruction), displayMode(displayMode) { - // Measures start time on initialization. - Clock::getClock_timeval(&startTime); -} - -void Stopwatch::start() { - Clock::getClock_timeval(&startTime); -} - -dur_millis_t Stopwatch::stop() { - stopInternal(); - return elapsedTime.tv_sec * 1000 + elapsedTime.tv_usec / 1000; -} - -dur_seconds_t Stopwatch::stopSeconds() { - stopInternal(); - return timevalOperations::toDouble(elapsedTime); -} - -void Stopwatch::display() { - if(displayMode == StopwatchDisplayMode::MILLIS) { - sif::info << "Stopwatch: Operation took " << (elapsedTime.tv_sec * 1000 + - elapsedTime.tv_usec / 1000) << " milliseconds" << std::endl; - } - else if(displayMode == StopwatchDisplayMode::SECONDS) { - sif::info <<"Stopwatch: Operation took " << std::setprecision(3) - << std::fixed << timevalOperations::toDouble(elapsedTime) - << " seconds" << std::endl; - } -} - -Stopwatch::~Stopwatch() { - if(displayOnDestruction) { - stopInternal(); - display(); - } -} - -void Stopwatch::setDisplayMode(StopwatchDisplayMode displayMode) { - this->displayMode = displayMode; -} - -StopwatchDisplayMode Stopwatch::getDisplayMode() const { - return displayMode; -} - -void Stopwatch::stopInternal() { - timeval endTime; - Clock::getClock_timeval(&endTime); - elapsedTime = endTime - startTime; -} +#include "Stopwatch.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include + +Stopwatch::Stopwatch(bool displayOnDestruction, + StopwatchDisplayMode displayMode): displayOnDestruction( + displayOnDestruction), displayMode(displayMode) { + // Measures start time on initialization. + Clock::getClock_timeval(&startTime); +} + +void Stopwatch::start() { + Clock::getClock_timeval(&startTime); +} + +dur_millis_t Stopwatch::stop() { + stopInternal(); + return elapsedTime.tv_sec * 1000 + elapsedTime.tv_usec / 1000; +} + +dur_seconds_t Stopwatch::stopSeconds() { + stopInternal(); + return timevalOperations::toDouble(elapsedTime); +} + +void Stopwatch::display() { + if(displayMode == StopwatchDisplayMode::MILLIS) { + sif::info << "Stopwatch: Operation took " << (elapsedTime.tv_sec * 1000 + + elapsedTime.tv_usec / 1000) << " milliseconds" << std::endl; + } + else if(displayMode == StopwatchDisplayMode::SECONDS) { + sif::info <<"Stopwatch: Operation took " << std::setprecision(3) + << std::fixed << timevalOperations::toDouble(elapsedTime) + << " seconds" << std::endl; + } +} + +Stopwatch::~Stopwatch() { + if(displayOnDestruction) { + stopInternal(); + display(); + } +} + +void Stopwatch::setDisplayMode(StopwatchDisplayMode displayMode) { + this->displayMode = displayMode; +} + +StopwatchDisplayMode Stopwatch::getDisplayMode() const { + return displayMode; +} + +void Stopwatch::stopInternal() { + timeval endTime; + Clock::getClock_timeval(&endTime); + elapsedTime = endTime - startTime; +} diff --git a/timemanager/Stopwatch.h b/timemanager/Stopwatch.h index 630202cc..f216b7e1 100644 --- a/timemanager/Stopwatch.h +++ b/timemanager/Stopwatch.h @@ -1,71 +1,71 @@ -#ifndef FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ -#define FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ -#include - -enum class StopwatchDisplayMode { - MILLIS, - SECONDS -}; - -/** - * @brief Simple Stopwatch implementation to measure elapsed time - * @details - * This class can be used to measure elapsed times. It also displays elapsed - * times automatically on destruction if not explicitely deactivated in the - * constructor. The default time format is the elapsed time in miliseconds - * in seconds as a double. - * @author R. Mueller - */ -class Stopwatch { -public: - /** - * Default constructor. Call "Stopwatch stopwatch" without brackets if - * no parameters are required! - * @param displayOnDestruction If set to true, displays measured time on - * object destruction - * @param displayMode Display format is either MS rounded or MS as double - * format - * @param outputPrecision If using double format, specify precision here. - */ - Stopwatch(bool displayOnDestruction = true, StopwatchDisplayMode displayMode - = StopwatchDisplayMode::MILLIS); - virtual~ Stopwatch(); - - /** - * Caches the start time - */ - void start(); - - /** - * Calculates the elapsed time since start and returns it - * @return elapsed time in milliseconds (rounded) - */ - dur_millis_t stop(); - /** - * Calculates the elapsed time since start and returns it - * @return elapsed time in seconds (double precision) - */ - dur_seconds_t stopSeconds(); - - /** - * Displays the elapsed times on the osstream, depending on internal display - * mode. - */ - void display(); - - StopwatchDisplayMode getDisplayMode() const; - void setDisplayMode(StopwatchDisplayMode displayMode); - bool displayOnDestruction = true; -private: - timeval startTime {0, 0}; - timeval elapsedTime {0, 0}; - - StopwatchDisplayMode displayMode = StopwatchDisplayMode::MILLIS; - - void stopInternal(); -}; - - - - -#endif /* FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ */ +#ifndef FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ +#define FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ +#include "Clock.h" + +enum class StopwatchDisplayMode { + MILLIS, + SECONDS +}; + +/** + * @brief Simple Stopwatch implementation to measure elapsed time + * @details + * This class can be used to measure elapsed times. It also displays elapsed + * times automatically on destruction if not explicitely deactivated in the + * constructor. The default time format is the elapsed time in miliseconds + * in seconds as a double. + * @author R. Mueller + */ +class Stopwatch { +public: + /** + * Default constructor. Call "Stopwatch stopwatch" without brackets if + * no parameters are required! + * @param displayOnDestruction If set to true, displays measured time on + * object destruction + * @param displayMode Display format is either MS rounded or MS as double + * format + * @param outputPrecision If using double format, specify precision here. + */ + Stopwatch(bool displayOnDestruction = true, StopwatchDisplayMode displayMode + = StopwatchDisplayMode::MILLIS); + virtual~ Stopwatch(); + + /** + * Caches the start time + */ + void start(); + + /** + * Calculates the elapsed time since start and returns it + * @return elapsed time in milliseconds (rounded) + */ + dur_millis_t stop(); + /** + * Calculates the elapsed time since start and returns it + * @return elapsed time in seconds (double precision) + */ + dur_seconds_t stopSeconds(); + + /** + * Displays the elapsed times on the osstream, depending on internal display + * mode. + */ + void display(); + + StopwatchDisplayMode getDisplayMode() const; + void setDisplayMode(StopwatchDisplayMode displayMode); + bool displayOnDestruction = true; +private: + timeval startTime {0, 0}; + timeval elapsedTime {0, 0}; + + StopwatchDisplayMode displayMode = StopwatchDisplayMode::MILLIS; + + void stopInternal(); +}; + + + + +#endif /* FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ */ diff --git a/timemanager/TimeMessage.cpp b/timemanager/TimeMessage.cpp index bf514317..5a9a416b 100644 --- a/timemanager/TimeMessage.cpp +++ b/timemanager/TimeMessage.cpp @@ -5,7 +5,7 @@ * @author baetz */ -#include +#include "TimeMessage.h" TimeMessage::TimeMessage() { this->messageSize += sizeof(timeval) + sizeof(uint32_t); diff --git a/timemanager/TimeMessage.h b/timemanager/TimeMessage.h index 95685fec..116002e6 100644 --- a/timemanager/TimeMessage.h +++ b/timemanager/TimeMessage.h @@ -8,8 +8,8 @@ #ifndef TIMEMESSAGE_H_ #define TIMEMESSAGE_H_ -#include -#include +#include "../ipc/MessageQueueMessage.h" +#include "Clock.h" #include class TimeMessage : public MessageQueueMessage { diff --git a/timemanager/TimeStamperIF.h b/timemanager/TimeStamperIF.h index 7ed45371..bdc5e7e3 100644 --- a/timemanager/TimeStamperIF.h +++ b/timemanager/TimeStamperIF.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_TIMEMANAGER_TIMESTAMPERIF_H_ #define FRAMEWORK_TIMEMANAGER_TIMESTAMPERIF_H_ -#include +#include "../returnvalues/HasReturnvaluesIF.h" /** * A class implementing this IF provides facilities to add a time stamp to the diff --git a/tmstorage/TmStoreBackendIF.h b/tmstorage/TmStoreBackendIF.h index 162bd766..a441808e 100644 --- a/tmstorage/TmStoreBackendIF.h +++ b/tmstorage/TmStoreBackendIF.h @@ -1,11 +1,11 @@ #ifndef PLATFORM_TMTCSERVICES_TMSTOREBACKENDIF_H_ #define PLATFORM_TMTCSERVICES_TMSTOREBACKENDIF_H_ -#include -#include -#include -#include -#include +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../objectmanager/SystemObjectIF.h" +#include "../parameters/HasParametersIF.h" +#include "../storagemanager/StorageManagerIF.h" +#include "../timemanager/Clock.h" class TmPacketInformation; class TmPacketMinimal; class SpacePacketBase; diff --git a/tmstorage/TmStoreFrontendIF.h b/tmstorage/TmStoreFrontendIF.h index 787c3597..e1bc3a14 100644 --- a/tmstorage/TmStoreFrontendIF.h +++ b/tmstorage/TmStoreFrontendIF.h @@ -1,9 +1,9 @@ #ifndef PLATFORM_TMTCSERVICES_TMSTOREFRONTENDIF_H_ #define PLATFORM_TMTCSERVICES_TMSTOREFRONTENDIF_H_ -#include -#include -#include +#include "../returnvalues/HasReturnvaluesIF.h" +#include "TmStorePackets.h" +#include "../ipc/MessageQueueSenderIF.h" class TmPacketMinimal; class SpacePacketBase; class TmStoreBackendIF; diff --git a/tmstorage/TmStoreMessage.cpp b/tmstorage/TmStoreMessage.cpp index e908b923..d2efd403 100644 --- a/tmstorage/TmStoreMessage.cpp +++ b/tmstorage/TmStoreMessage.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "../objectmanager/ObjectManagerIF.h" +#include "TmStoreMessage.h" TmStoreMessage::~TmStoreMessage() { diff --git a/tmstorage/TmStoreMessage.h b/tmstorage/TmStoreMessage.h index 0883063c..66fdefa5 100644 --- a/tmstorage/TmStoreMessage.h +++ b/tmstorage/TmStoreMessage.h @@ -1,10 +1,10 @@ #ifndef FRAMEWORK_TMSTORAGE_TMSTOREMESSAGE_H_ #define FRAMEWORK_TMSTORAGE_TMSTOREMESSAGE_H_ -#include -#include -#include -#include +#include "../ipc/CommandMessage.h" +#include "../storagemanager/StorageManagerIF.h" +#include "TmStorePackets.h" +#include "../objectmanager/SystemObjectIF.h" class TmStoreMessage: public CommandMessage { public: static ReturnValue_t setEnableStoringMessage(CommandMessage* cmd, diff --git a/tmstorage/TmStorePackets.h b/tmstorage/TmStorePackets.h index 16768e68..e88e741a 100644 --- a/tmstorage/TmStorePackets.h +++ b/tmstorage/TmStorePackets.h @@ -1,14 +1,14 @@ #ifndef FRAMEWORK_TMSTORAGE_TMSTOREPACKETS_H_ #define FRAMEWORK_TMSTORAGE_TMSTOREPACKETS_H_ -#include -#include -#include -#include -#include -#include -#include -#include +#include "../serialize/SerialFixedArrayListAdapter.h" +#include "../serialize/SerializeElement.h" +#include "../serialize/SerialLinkedListAdapter.h" +#include "../serialize/SerialBufferAdapter.h" +#include "../tmtcpacket/pus/TmPacketMinimal.h" +#include "../timemanager/TimeStamperIF.h" +#include "../timemanager/CCSDSTime.h" +#include "../globalfunctions/timevalOperations.h" class ServiceSubservice: public SerialLinkedListAdapter { public: diff --git a/tmtcpacket/SpacePacket.cpp b/tmtcpacket/SpacePacket.cpp index d9bc08fa..b8ba27e9 100644 --- a/tmtcpacket/SpacePacket.cpp +++ b/tmtcpacket/SpacePacket.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "ccsds_header.h" +#include "SpacePacket.h" #include SpacePacket::SpacePacket( uint16_t packetDataLength, bool isTelecommand, uint16_t apid, uint16_t sequenceCount ): diff --git a/tmtcpacket/SpacePacket.h b/tmtcpacket/SpacePacket.h index f2d45752..49dd5ae5 100644 --- a/tmtcpacket/SpacePacket.h +++ b/tmtcpacket/SpacePacket.h @@ -1,7 +1,7 @@ #ifndef SPACEPACKET_H_ #define SPACEPACKET_H_ -#include +#include "SpacePacketBase.h" /** * The SpacePacket class is a representation of a simple CCSDS Space Packet diff --git a/tmtcpacket/SpacePacketBase.cpp b/tmtcpacket/SpacePacketBase.cpp index 13c062d8..a37e024b 100644 --- a/tmtcpacket/SpacePacketBase.cpp +++ b/tmtcpacket/SpacePacketBase.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "SpacePacketBase.h" #include SpacePacketBase::SpacePacketBase( const uint8_t* set_address ) { diff --git a/tmtcpacket/SpacePacketBase.h b/tmtcpacket/SpacePacketBase.h index cc68f714..ef3ad79d 100644 --- a/tmtcpacket/SpacePacketBase.h +++ b/tmtcpacket/SpacePacketBase.h @@ -1,7 +1,7 @@ #ifndef SPACEPACKETBASE_H_ #define SPACEPACKETBASE_H_ -#include +#include "ccsds_header.h" /** * \defgroup tmtcpackets Space Packets diff --git a/tmtcpacket/packetmatcher/ApidMatcher.h b/tmtcpacket/packetmatcher/ApidMatcher.h index 3080ffef..4f196ac9 100644 --- a/tmtcpacket/packetmatcher/ApidMatcher.h +++ b/tmtcpacket/packetmatcher/ApidMatcher.h @@ -1,9 +1,9 @@ #ifndef FRAMEWORK_TMTCPACKET_PACKETMATCHER_APIDMATCHER_H_ #define FRAMEWORK_TMTCPACKET_PACKETMATCHER_APIDMATCHER_H_ -#include -#include -#include +#include "../../globalfunctions/matching/SerializeableMatcherIF.h" +#include "../../serialize/SerializeAdapter.h" +#include "../../tmtcpacket/pus/TmPacketMinimal.h" class ApidMatcher: public SerializeableMatcherIF { private: diff --git a/tmtcpacket/packetmatcher/PacketMatchTree.cpp b/tmtcpacket/packetmatcher/PacketMatchTree.cpp index d8f61ffb..a4579657 100644 --- a/tmtcpacket/packetmatcher/PacketMatchTree.cpp +++ b/tmtcpacket/packetmatcher/PacketMatchTree.cpp @@ -1,7 +1,7 @@ -#include -#include -#include -#include +#include "ApidMatcher.h" +#include "PacketMatchTree.h" +#include "ServiceMatcher.h" +#include "SubserviceMatcher.h" PacketMatchTree::PacketMatchTree(Node* root) : MatchTree(root, 2), factoryBackend(0, POOL_SIZES, diff --git a/tmtcpacket/packetmatcher/PacketMatchTree.h b/tmtcpacket/packetmatcher/PacketMatchTree.h index a6c0c61e..86fb087e 100644 --- a/tmtcpacket/packetmatcher/PacketMatchTree.h +++ b/tmtcpacket/packetmatcher/PacketMatchTree.h @@ -1,10 +1,10 @@ #ifndef FRAMEWORK_TMTCPACKET_PACKETMATCHER_PACKETMATCHTREE_H_ #define FRAMEWORK_TMTCPACKET_PACKETMATCHER_PACKETMATCHTREE_H_ -#include -#include -#include -#include +#include "../../container/PlacementFactory.h" +#include "../../globalfunctions/matching/MatchTree.h" +#include "../../storagemanager/LocalPool.h" +#include "../../tmtcpacket/pus/TmPacketMinimal.h" class PacketMatchTree: public MatchTree, public HasReturnvaluesIF { public: diff --git a/tmtcpacket/packetmatcher/ServiceMatcher.h b/tmtcpacket/packetmatcher/ServiceMatcher.h index f6e9e360..eba23d75 100644 --- a/tmtcpacket/packetmatcher/ServiceMatcher.h +++ b/tmtcpacket/packetmatcher/ServiceMatcher.h @@ -1,9 +1,9 @@ #ifndef FRAMEWORK_TMTCPACKET_PACKETMATCHER_SERVICEMATCHER_H_ #define FRAMEWORK_TMTCPACKET_PACKETMATCHER_SERVICEMATCHER_H_ -#include -#include -#include +#include "../../globalfunctions/matching/SerializeableMatcherIF.h" +#include "../../serialize/SerializeAdapter.h" +#include "../../tmtcpacket/pus/TmPacketMinimal.h" class ServiceMatcher: public SerializeableMatcherIF { private: diff --git a/tmtcpacket/packetmatcher/SubserviceMatcher.h b/tmtcpacket/packetmatcher/SubserviceMatcher.h index 2e8b82b2..a9b6def8 100644 --- a/tmtcpacket/packetmatcher/SubserviceMatcher.h +++ b/tmtcpacket/packetmatcher/SubserviceMatcher.h @@ -1,9 +1,9 @@ #ifndef FRAMEWORK_TMTCPACKET_PACKETMATCHER_SUBSERVICEMATCHER_H_ #define FRAMEWORK_TMTCPACKET_PACKETMATCHER_SUBSERVICEMATCHER_H_ -#include -#include -#include +#include "../../globalfunctions/matching/SerializeableMatcherIF.h" +#include "../../serialize/SerializeAdapter.h" +#include "../../tmtcpacket/pus/TmPacketMinimal.h" class SubServiceMatcher: public SerializeableMatcherIF { public: diff --git a/tmtcpacket/pus/PacketTimestampInterpreterIF.h b/tmtcpacket/pus/PacketTimestampInterpreterIF.h index 6e19381a..dd0c0328 100644 --- a/tmtcpacket/pus/PacketTimestampInterpreterIF.h +++ b/tmtcpacket/pus/PacketTimestampInterpreterIF.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_TMTCPACKET_PUS_PACKETTIMESTAMPINTERPRETERIF_H_ #define FRAMEWORK_TMTCPACKET_PUS_PACKETTIMESTAMPINTERPRETERIF_H_ -#include +#include "../../returnvalues/HasReturnvaluesIF.h" class TmPacketMinimal; class PacketTimestampInterpreterIF { diff --git a/tmtcpacket/pus/TcPacketBase.cpp b/tmtcpacket/pus/TcPacketBase.cpp index 0f3bd52e..3815eb20 100644 --- a/tmtcpacket/pus/TcPacketBase.cpp +++ b/tmtcpacket/pus/TcPacketBase.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "../../globalfunctions/CRC.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "TcPacketBase.h" #include TcPacketBase::TcPacketBase(const uint8_t* set_data) : diff --git a/tmtcpacket/pus/TcPacketBase.h b/tmtcpacket/pus/TcPacketBase.h index e6e6bdad..dd63d2be 100644 --- a/tmtcpacket/pus/TcPacketBase.h +++ b/tmtcpacket/pus/TcPacketBase.h @@ -1,7 +1,7 @@ #ifndef TCPACKETBASE_H_ #define TCPACKETBASE_H_ -#include +#include "../../tmtcpacket/SpacePacketBase.h" /** * This struct defines a byte-wise structured PUS TC Data Field Header. diff --git a/tmtcpacket/pus/TcPacketStored.cpp b/tmtcpacket/pus/TcPacketStored.cpp index 0187b08f..216f89c9 100644 --- a/tmtcpacket/pus/TcPacketStored.cpp +++ b/tmtcpacket/pus/TcPacketStored.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "../../objectmanager/ObjectManagerIF.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "TcPacketStored.h" #include TcPacketStored::TcPacketStored(store_address_t setAddress) : diff --git a/tmtcpacket/pus/TcPacketStored.h b/tmtcpacket/pus/TcPacketStored.h index c57f0e0f..2d86f89b 100644 --- a/tmtcpacket/pus/TcPacketStored.h +++ b/tmtcpacket/pus/TcPacketStored.h @@ -1,8 +1,8 @@ #ifndef TCPACKETSTORED_H_ #define TCPACKETSTORED_H_ -#include -#include +#include "../../storagemanager/StorageManagerIF.h" +#include "TcPacketBase.h" /** * This class generates a ECSS PUS Telecommand packet within a given diff --git a/tmtcpacket/pus/TmPacketBase.cpp b/tmtcpacket/pus/TmPacketBase.cpp index a7bda5af..3c1a8ca4 100644 --- a/tmtcpacket/pus/TmPacketBase.cpp +++ b/tmtcpacket/pus/TmPacketBase.cpp @@ -1,8 +1,8 @@ -#include -#include -#include -#include -#include +#include "../../globalfunctions/CRC.h" +#include "../../objectmanager/ObjectManagerIF.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "TmPacketBase.h" +#include "../../timemanager/CCSDSTime.h" #include TmPacketBase::TmPacketBase(uint8_t* set_data) : diff --git a/tmtcpacket/pus/TmPacketBase.h b/tmtcpacket/pus/TmPacketBase.h index d03beba5..85ae4dac 100644 --- a/tmtcpacket/pus/TmPacketBase.h +++ b/tmtcpacket/pus/TmPacketBase.h @@ -1,10 +1,10 @@ #ifndef TMPACKETBASE_H_ #define TMPACKETBASE_H_ -#include -#include -#include -#include +#include "../../timemanager/TimeStamperIF.h" +#include "../../tmtcpacket/SpacePacketBase.h" +#include "../../timemanager/Clock.h" +#include "../../objectmanager/SystemObjectIF.h" namespace Factory{ void setStaticFrameworkObjectIds(); diff --git a/tmtcpacket/pus/TmPacketMinimal.cpp b/tmtcpacket/pus/TmPacketMinimal.cpp index 9df0fe5d..18e9dda1 100644 --- a/tmtcpacket/pus/TmPacketMinimal.cpp +++ b/tmtcpacket/pus/TmPacketMinimal.cpp @@ -1,7 +1,7 @@ -#include +#include "TmPacketMinimal.h" #include #include -#include +#include "PacketTimestampInterpreterIF.h" TmPacketMinimal::TmPacketMinimal(const uint8_t* set_data) : SpacePacketBase( set_data ) { this->tm_data = (TmPacketMinimalPointer*)set_data; diff --git a/tmtcpacket/pus/TmPacketMinimal.h b/tmtcpacket/pus/TmPacketMinimal.h index 7bfe0883..728acb15 100644 --- a/tmtcpacket/pus/TmPacketMinimal.h +++ b/tmtcpacket/pus/TmPacketMinimal.h @@ -2,8 +2,8 @@ #define FRAMEWORK_TMTCPACKET_PUS_TMPACKETMINIMAL_H_ -#include -#include +#include "../../tmtcpacket/SpacePacketBase.h" +#include "../../returnvalues/HasReturnvaluesIF.h" struct timeval; class PacketTimestampInterpreterIF; diff --git a/tmtcpacket/pus/TmPacketStored.cpp b/tmtcpacket/pus/TmPacketStored.cpp index 7c327581..4e4c9434 100644 --- a/tmtcpacket/pus/TmPacketStored.cpp +++ b/tmtcpacket/pus/TmPacketStored.cpp @@ -1,7 +1,7 @@ -#include -#include -#include -#include +#include "../../objectmanager/ObjectManagerIF.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "TmPacketStored.h" +#include "../../tmtcservices/TmTcMessage.h" #include TmPacketStored::TmPacketStored(store_address_t setAddress) : diff --git a/tmtcpacket/pus/TmPacketStored.h b/tmtcpacket/pus/TmPacketStored.h index eaa26ce7..8962d343 100644 --- a/tmtcpacket/pus/TmPacketStored.h +++ b/tmtcpacket/pus/TmPacketStored.h @@ -1,11 +1,11 @@ #ifndef TMPACKETSTORED_H_ #define TMPACKETSTORED_H_ -#include -#include -#include -#include -#include +#include "../../serialize/SerializeIF.h" +#include "../../storagemanager/StorageManagerIF.h" +#include "TmPacketBase.h" +#include "../../internalError/InternalErrorReporterIF.h" +#include "../../ipc/MessageQueueSenderIF.h" /** * This class generates a ECSS PUS Telemetry packet within a given diff --git a/tmtcservices/AcceptsTelecommandsIF.h b/tmtcservices/AcceptsTelecommandsIF.h index 03a57aae..76d10a59 100644 --- a/tmtcservices/AcceptsTelecommandsIF.h +++ b/tmtcservices/AcceptsTelecommandsIF.h @@ -1,7 +1,7 @@ #ifndef ACCEPTSTELECOMMANDSIF_H_ #define ACCEPTSTELECOMMANDSIF_H_ -#include +#include "../ipc/MessageQueueSenderIF.h" /** * @brief This interface is implemented by classes that are sinks for diff --git a/tmtcservices/AcceptsTelemetryIF.h b/tmtcservices/AcceptsTelemetryIF.h index 8c00b5c6..2325dbe0 100644 --- a/tmtcservices/AcceptsTelemetryIF.h +++ b/tmtcservices/AcceptsTelemetryIF.h @@ -1,7 +1,7 @@ #ifndef ACCEPTSTELEMETRYIF_H_ #define ACCEPTSTELEMETRYIF_H_ -#include +#include "../ipc/MessageQueueSenderIF.h" /** * @brief This interface is implemented by classes that are sinks for * Telemetry. diff --git a/tmtcservices/AcceptsVerifyMessageIF.h b/tmtcservices/AcceptsVerifyMessageIF.h index fe8bb288..c9318ab0 100644 --- a/tmtcservices/AcceptsVerifyMessageIF.h +++ b/tmtcservices/AcceptsVerifyMessageIF.h @@ -1,7 +1,7 @@ #ifndef ACCEPTSVERIFICATIONMESSAGEIF_H_ #define ACCEPTSVERIFICATIONMESSAGEIF_H_ -#include +#include "../ipc/MessageQueueSenderIF.h" class AcceptsVerifyMessageIF { public: diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index 330fd00f..0b33e3aa 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -1,12 +1,12 @@ -#include -#include -#include +#include "../tcdistribution/PUSDistributorIF.h" +#include "AcceptsTelemetryIF.h" +#include "../objectmanager/ObjectManagerIF.h" -#include -#include -#include -#include -#include +#include "CommandingServiceBase.h" +#include "TmTcMessage.h" +#include "../ipc/QueueFactory.h" +#include "../tmtcpacket/pus/TcPacketStored.h" +#include "../tmtcpacket/pus/TmPacketStored.h" object_id_t CommandingServiceBase::defaultPacketSource = objects::NO_OBJECT; object_id_t CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT; diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index b3a15985..c0453f2f 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -1,17 +1,17 @@ #ifndef FRAMEWORK_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ #define FRAMEWORK_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ -#include -#include -#include -#include -#include +#include "../objectmanager/SystemObject.h" +#include "../storagemanager/StorageManagerIF.h" +#include "../tasks/ExecutableObjectIF.h" +#include "../ipc/MessageQueueIF.h" +#include "AcceptsTelecommandsIF.h" -#include -#include -#include -#include -#include +#include "VerificationReporter.h" +#include "../ipc/CommandMessage.h" +#include "../container/FixedMap.h" +#include "../container/FIFO.h" +#include "../serialize/SerializeIF.h" class TcPacketStored; diff --git a/tmtcservices/PusServiceBase.cpp b/tmtcservices/PusServiceBase.cpp index 82e5ff5c..d35944a4 100644 --- a/tmtcservices/PusServiceBase.cpp +++ b/tmtcservices/PusServiceBase.cpp @@ -1,10 +1,10 @@ -#include -#include -#include -#include -#include -#include -#include +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../tcdistribution/PUSDistributorIF.h" +#include "AcceptsTelemetryIF.h" +#include "PusServiceBase.h" +#include "PusVerificationReport.h" +#include "TmTcMessage.h" +#include "../ipc/QueueFactory.h" object_id_t PusServiceBase::packetSource = 0; object_id_t PusServiceBase::packetDestination = 0; diff --git a/tmtcservices/PusServiceBase.h b/tmtcservices/PusServiceBase.h index 6d3d9bac..98d65efb 100644 --- a/tmtcservices/PusServiceBase.h +++ b/tmtcservices/PusServiceBase.h @@ -1,15 +1,15 @@ #ifndef FRAMEWORK_TMTCSERVICES_PUSSERVICEBASE_H_ #define FRAMEWORK_TMTCSERVICES_PUSSERVICEBASE_H_ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "../objectmanager/ObjectManagerIF.h" +#include "../objectmanager/SystemObject.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../tasks/ExecutableObjectIF.h" +#include "../tmtcpacket/pus/TcPacketStored.h" +#include "AcceptsTelecommandsIF.h" +#include "VerificationCodes.h" +#include "VerificationReporter.h" +#include "../ipc/MessageQueueIF.h" namespace Factory{ void setStaticFrameworkObjectIds(); diff --git a/tmtcservices/PusVerificationReport.cpp b/tmtcservices/PusVerificationReport.cpp index 07631801..b047576b 100644 --- a/tmtcservices/PusVerificationReport.cpp +++ b/tmtcservices/PusVerificationReport.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "../serialize/SerializeAdapter.h" +#include "PusVerificationReport.h" PusVerificationMessage::PusVerificationMessage() { } diff --git a/tmtcservices/PusVerificationReport.h b/tmtcservices/PusVerificationReport.h index ee84f0c1..b4739577 100644 --- a/tmtcservices/PusVerificationReport.h +++ b/tmtcservices/PusVerificationReport.h @@ -1,9 +1,9 @@ #ifndef PUSVERIFICATIONREPORT_H_ #define PUSVERIFICATIONREPORT_H_ -#include -#include -#include +#include "../ipc/MessageQueueMessage.h" +#include "../tmtcpacket/pus/TcPacketBase.h" +#include "VerificationCodes.h" class PusVerificationMessage: public MessageQueueMessage { private: diff --git a/tmtcservices/SourceSequenceCounter.h b/tmtcservices/SourceSequenceCounter.h index b92a5c84..1cc58758 100644 --- a/tmtcservices/SourceSequenceCounter.h +++ b/tmtcservices/SourceSequenceCounter.h @@ -7,7 +7,7 @@ #ifndef SOURCESEQUENCECOUNTER_H_ #define SOURCESEQUENCECOUNTER_H_ -#include +#include "../tmtcpacket/SpacePacketBase.h" class SourceSequenceCounter { private: diff --git a/tmtcservices/TmTcBridge.cpp b/tmtcservices/TmTcBridge.cpp index b55803cb..021b0d7b 100644 --- a/tmtcservices/TmTcBridge.cpp +++ b/tmtcservices/TmTcBridge.cpp @@ -1,211 +1,211 @@ -#include - -#include -#include -#include -#include - -TmTcBridge::TmTcBridge(object_id_t objectId, object_id_t tcDestination, - object_id_t tmStoreId, object_id_t tcStoreId): - SystemObject(objectId),tmStoreId(tmStoreId), tcStoreId(tcStoreId), - tcDestination(tcDestination) - -{ - tmTcReceptionQueue = QueueFactory::instance()-> - createMessageQueue(TMTC_RECEPTION_QUEUE_DEPTH); -} - -TmTcBridge::~TmTcBridge() {} - -ReturnValue_t TmTcBridge::setNumberOfSentPacketsPerCycle( - uint8_t sentPacketsPerCycle) { - if(sentPacketsPerCycle <= LIMIT_STORED_DATA_SENT_PER_CYCLE) { - this->sentPacketsPerCycle = sentPacketsPerCycle; - return RETURN_OK; - } - else { - sif::warning << "TmTcBridge::setNumberOfSentPacketsPerCycle: Number of " - << "packets sent per cycle exceeds limits. " - << "Keeping default value." << std::endl; - return RETURN_FAILED; - } -} - -ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored( - uint8_t maxNumberOfPacketsStored) { - if(maxNumberOfPacketsStored <= LIMIT_DOWNLINK_PACKETS_STORED) { - this->maxNumberOfPacketsStored = maxNumberOfPacketsStored; - return RETURN_OK; - } - else { - sif::warning << "TmTcBridge::setMaxNumberOfPacketsStored: Number of " - << "packets stored exceeds limits. " - << "Keeping default value." << std::endl; - return RETURN_FAILED; - } -} - -ReturnValue_t TmTcBridge::initialize() { - tcStore = objectManager->get(tcStoreId); - if (tcStore == nullptr) { - sif::error << "TmTcBridge::initialize: TC store invalid. Make sure" - "it is created and set up properly." << std::endl; - return ObjectManagerIF::CHILD_INIT_FAILED; - } - tmStore = objectManager->get(tmStoreId); - if (tmStore == nullptr) { - sif::error << "TmTcBridge::initialize: TM store invalid. Make sure" - "it is created and set up properly." << std::endl; - return ObjectManagerIF::CHILD_INIT_FAILED; - } - AcceptsTelecommandsIF* tcDistributor = - objectManager->get(tcDestination); - if (tcDistributor == nullptr) { - sif::error << "TmTcBridge::initialize: TC Distributor invalid" - << std::endl; - return ObjectManagerIF::CHILD_INIT_FAILED; - } - - tmTcReceptionQueue->setDefaultDestination(tcDistributor->getRequestQueue()); - return RETURN_OK; -} - -ReturnValue_t TmTcBridge::performOperation(uint8_t operationCode) { - ReturnValue_t result; - result = handleTc(); - if(result != RETURN_OK) { - sif::debug << "TmTcBridge::performOperation: " - << "Error handling TCs" << std::endl; - } - result = handleTm(); - if (result != RETURN_OK) { - sif::debug << "TmTcBridge::performOperation: " - << "Error handling TMs" << std::endl; - } - return result; -} - -ReturnValue_t TmTcBridge::handleTc() { - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t TmTcBridge::handleTm() { - ReturnValue_t result = handleTmQueue(); - if(result != RETURN_OK) { - sif::warning << "TmTcBridge: Reading TM Queue failed" << std::endl; - return RETURN_FAILED; - } - - if(tmStored and communicationLinkUp) { - result = handleStoredTm(); - } - return result; - -} - -ReturnValue_t TmTcBridge::handleTmQueue() { - TmTcMessage message; +#include "TmTcBridge.h" + +#include "../ipc/QueueFactory.h" +#include "AcceptsTelecommandsIF.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../globalfunctions/arrayprinter.h" + +TmTcBridge::TmTcBridge(object_id_t objectId, object_id_t tcDestination, + object_id_t tmStoreId, object_id_t tcStoreId): + SystemObject(objectId),tmStoreId(tmStoreId), tcStoreId(tcStoreId), + tcDestination(tcDestination) + +{ + tmTcReceptionQueue = QueueFactory::instance()-> + createMessageQueue(TMTC_RECEPTION_QUEUE_DEPTH); +} + +TmTcBridge::~TmTcBridge() {} + +ReturnValue_t TmTcBridge::setNumberOfSentPacketsPerCycle( + uint8_t sentPacketsPerCycle) { + if(sentPacketsPerCycle <= LIMIT_STORED_DATA_SENT_PER_CYCLE) { + this->sentPacketsPerCycle = sentPacketsPerCycle; + return RETURN_OK; + } + else { + sif::warning << "TmTcBridge::setNumberOfSentPacketsPerCycle: Number of " + << "packets sent per cycle exceeds limits. " + << "Keeping default value." << std::endl; + return RETURN_FAILED; + } +} + +ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored( + uint8_t maxNumberOfPacketsStored) { + if(maxNumberOfPacketsStored <= LIMIT_DOWNLINK_PACKETS_STORED) { + this->maxNumberOfPacketsStored = maxNumberOfPacketsStored; + return RETURN_OK; + } + else { + sif::warning << "TmTcBridge::setMaxNumberOfPacketsStored: Number of " + << "packets stored exceeds limits. " + << "Keeping default value." << std::endl; + return RETURN_FAILED; + } +} + +ReturnValue_t TmTcBridge::initialize() { + tcStore = objectManager->get(tcStoreId); + if (tcStore == nullptr) { + sif::error << "TmTcBridge::initialize: TC store invalid. Make sure" + "it is created and set up properly." << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + tmStore = objectManager->get(tmStoreId); + if (tmStore == nullptr) { + sif::error << "TmTcBridge::initialize: TM store invalid. Make sure" + "it is created and set up properly." << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + AcceptsTelecommandsIF* tcDistributor = + objectManager->get(tcDestination); + if (tcDistributor == nullptr) { + sif::error << "TmTcBridge::initialize: TC Distributor invalid" + << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + + tmTcReceptionQueue->setDefaultDestination(tcDistributor->getRequestQueue()); + return RETURN_OK; +} + +ReturnValue_t TmTcBridge::performOperation(uint8_t operationCode) { + ReturnValue_t result; + result = handleTc(); + if(result != RETURN_OK) { + sif::debug << "TmTcBridge::performOperation: " + << "Error handling TCs" << std::endl; + } + result = handleTm(); + if (result != RETURN_OK) { + sif::debug << "TmTcBridge::performOperation: " + << "Error handling TMs" << std::endl; + } + return result; +} + +ReturnValue_t TmTcBridge::handleTc() { + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t TmTcBridge::handleTm() { + ReturnValue_t result = handleTmQueue(); + if(result != RETURN_OK) { + sif::warning << "TmTcBridge: Reading TM Queue failed" << std::endl; + return RETURN_FAILED; + } + + if(tmStored and communicationLinkUp) { + result = handleStoredTm(); + } + return result; + +} + +ReturnValue_t TmTcBridge::handleTmQueue() { + TmTcMessage message; const uint8_t* data = nullptr; size_t size = 0; - for (ReturnValue_t result = tmTcReceptionQueue->receiveMessage(&message); - result == RETURN_OK; result = tmTcReceptionQueue->receiveMessage(&message)) - { - if(communicationLinkUp == false) { - result = storeDownlinkData(&message); - return result; - } - - result = tmStore->getData(message.getStorageId(), &data, &size); - if (result != HasReturnvaluesIF::RETURN_OK) { - continue; - } - - result = sendTm(data, size); - if (result != RETURN_OK) { - sif::warning << "TmTcBridge: Could not send TM packet" << std::endl; - tmStore->deleteData(message.getStorageId()); - return result; - - } - tmStore->deleteData(message.getStorageId()); - } - return RETURN_OK; -} - -ReturnValue_t TmTcBridge::storeDownlinkData(TmTcMessage *message) { - store_address_t storeId = 0; - - if(tmFifo.full()) { - sif::error << "TmTcBridge::storeDownlinkData: TM downlink max. number " - << "of stored packet IDs reached! " - << "Overwriting old data" << std::endl; - tmFifo.retrieve(&storeId); - tmStore->deleteData(storeId); - } - storeId = message->getStorageId(); - tmFifo.insert(storeId); - tmStored = true; - return RETURN_OK; -} - -ReturnValue_t TmTcBridge::handleStoredTm() { - uint8_t counter = 0; - ReturnValue_t result = RETURN_OK; - while(not tmFifo.empty() and counter < sentPacketsPerCycle) { - //info << "TMTC Bridge: Sending stored TM data. There are " - // << (int) fifo.size() << " left to send\r\n" << std::flush; - store_address_t storeId; + for (ReturnValue_t result = tmTcReceptionQueue->receiveMessage(&message); + result == RETURN_OK; result = tmTcReceptionQueue->receiveMessage(&message)) + { + if(communicationLinkUp == false) { + result = storeDownlinkData(&message); + return result; + } + + result = tmStore->getData(message.getStorageId(), &data, &size); + if (result != HasReturnvaluesIF::RETURN_OK) { + continue; + } + + result = sendTm(data, size); + if (result != RETURN_OK) { + sif::warning << "TmTcBridge: Could not send TM packet" << std::endl; + tmStore->deleteData(message.getStorageId()); + return result; + + } + tmStore->deleteData(message.getStorageId()); + } + return RETURN_OK; +} + +ReturnValue_t TmTcBridge::storeDownlinkData(TmTcMessage *message) { + store_address_t storeId = 0; + + if(tmFifo.full()) { + sif::error << "TmTcBridge::storeDownlinkData: TM downlink max. number " + << "of stored packet IDs reached! " + << "Overwriting old data" << std::endl; + tmFifo.retrieve(&storeId); + tmStore->deleteData(storeId); + } + storeId = message->getStorageId(); + tmFifo.insert(storeId); + tmStored = true; + return RETURN_OK; +} + +ReturnValue_t TmTcBridge::handleStoredTm() { + uint8_t counter = 0; + ReturnValue_t result = RETURN_OK; + while(not tmFifo.empty() and counter < sentPacketsPerCycle) { + //info << "TMTC Bridge: Sending stored TM data. There are " + // << (int) fifo.size() << " left to send\r\n" << std::flush; + store_address_t storeId; const uint8_t* data = nullptr; size_t size = 0; - tmFifo.retrieve(&storeId); - result = tmStore->getData(storeId, &data, &size); - - sendTm(data,size); - - if(result != RETURN_OK) { - sif::error << "TMTC Bridge: Could not send stored downlink data" - << std::endl; - result = RETURN_FAILED; - } - counter ++; - - if(tmFifo.empty()) { - tmStored = false; - } - tmStore->deleteData(storeId); - } - return result; -} - -void TmTcBridge::registerCommConnect() { - if(not communicationLinkUp) { - //info << "TMTC Bridge: Registered Comm Link Connect" << std::endl; - communicationLinkUp = true; - } -} - -void TmTcBridge::registerCommDisconnect() { - //info << "TMTC Bridge: Registered Comm Link Disconnect" << std::endl; - if(communicationLinkUp) { - communicationLinkUp = false; - } -} - -MessageQueueId_t TmTcBridge::getReportReceptionQueue(uint8_t virtualChannel) { - return tmTcReceptionQueue->getId(); -} - - -void TmTcBridge::printData(uint8_t * data, size_t dataLen) { - arrayprinter::print(data, dataLen); -} - -uint16_t TmTcBridge::getIdentifier() { - // This is no PUS service, so we just return 0 - return 0; -} - -MessageQueueId_t TmTcBridge::getRequestQueue() { - // Default implementation: Relay TC messages to TC distributor directly. - return tmTcReceptionQueue->getDefaultDestination(); -} + tmFifo.retrieve(&storeId); + result = tmStore->getData(storeId, &data, &size); + + sendTm(data,size); + + if(result != RETURN_OK) { + sif::error << "TMTC Bridge: Could not send stored downlink data" + << std::endl; + result = RETURN_FAILED; + } + counter ++; + + if(tmFifo.empty()) { + tmStored = false; + } + tmStore->deleteData(storeId); + } + return result; +} + +void TmTcBridge::registerCommConnect() { + if(not communicationLinkUp) { + //info << "TMTC Bridge: Registered Comm Link Connect" << std::endl; + communicationLinkUp = true; + } +} + +void TmTcBridge::registerCommDisconnect() { + //info << "TMTC Bridge: Registered Comm Link Disconnect" << std::endl; + if(communicationLinkUp) { + communicationLinkUp = false; + } +} + +MessageQueueId_t TmTcBridge::getReportReceptionQueue(uint8_t virtualChannel) { + return tmTcReceptionQueue->getId(); +} + + +void TmTcBridge::printData(uint8_t * data, size_t dataLen) { + arrayprinter::print(data, dataLen); +} + +uint16_t TmTcBridge::getIdentifier() { + // This is no PUS service, so we just return 0 + return 0; +} + +MessageQueueId_t TmTcBridge::getRequestQueue() { + // Default implementation: Relay TC messages to TC distributor directly. + return tmTcReceptionQueue->getDefaultDestination(); +} diff --git a/tmtcservices/TmTcBridge.h b/tmtcservices/TmTcBridge.h index 993cd5b9..32eaf7f2 100644 --- a/tmtcservices/TmTcBridge.h +++ b/tmtcservices/TmTcBridge.h @@ -1,154 +1,154 @@ -#ifndef FRAMEWORK_TMTCSERVICES_TMTCBRIDGE_H_ -#define FRAMEWORK_TMTCSERVICES_TMTCBRIDGE_H_ - -#include -#include -#include -#include -#include -#include - -#include -#include - -class TmTcBridge : public AcceptsTelemetryIF, - public AcceptsTelecommandsIF, - public ExecutableObjectIF, - public HasReturnvaluesIF, - public SystemObject { -public: - static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20; - static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15; - static constexpr uint8_t LIMIT_DOWNLINK_PACKETS_STORED = 20; - - static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5; - static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10; - - TmTcBridge(object_id_t objectId, object_id_t tcDestination, - object_id_t tmStoreId, object_id_t tcStoreId); - virtual ~TmTcBridge(); - - /** - * Set number of packets sent per performOperation().Please note that this - * value must be smaller than MAX_STORED_DATA_SENT_PER_CYCLE - * @param sentPacketsPerCycle - * @return -@c RETURN_OK if value was set successfully - * -@c RETURN_FAILED otherwise, stored value stays the same - */ - ReturnValue_t setNumberOfSentPacketsPerCycle(uint8_t sentPacketsPerCycle); - - /** - * Set number of packets sent per performOperation().Please note that this - * value must be smaller than MAX_DOWNLINK_PACKETS_STORED - * @param sentPacketsPerCycle - * @return -@c RETURN_OK if value was set successfully - * -@c RETURN_FAILED otherwise, stored value stays the same - */ - ReturnValue_t setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored); - - virtual void registerCommConnect(); - virtual void registerCommDisconnect(); - - /** - * Initializes necessary FSFW components for the TMTC Bridge - * @return - */ - virtual ReturnValue_t initialize() override; - - /** - * @brief Handles TMTC reception - */ - virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override; - - - /** AcceptsTelemetryIF override */ - virtual MessageQueueId_t getReportReceptionQueue( - uint8_t virtualChannel = 0) override; - - /** AcceptsTelecommandsIF override */ - virtual uint16_t getIdentifier() override; - virtual MessageQueueId_t getRequestQueue() override; - -protected: - //! Cached for initialize function. - object_id_t tmStoreId = objects::NO_OBJECT; - object_id_t tcStoreId = objects::NO_OBJECT; - object_id_t tcDestination = objects::NO_OBJECT; - - //! Used to send and receive TMTC messages. - //! The TmTcMessage class is used to transport messages between tasks. - MessageQueueIF* tmTcReceptionQueue = nullptr; - - StorageManagerIF* tmStore = nullptr; - StorageManagerIF* tcStore = nullptr; - - //! Used to specify whether communication link is up. Will be true - //! by default, so telemetry will be handled immediately. - bool communicationLinkUp = true; - bool tmStored = false; - - /** - * @brief Handle TC reception - * @details - * Default implementation provided, but is empty. - * In most cases, TC reception will be handled in a separate task anyway. - * @return - */ - virtual ReturnValue_t handleTc(); - - /** - * Handle Telemetry. Default implementation provided. - * Calls sendTm() - * @return - */ - virtual ReturnValue_t handleTm(); - - /** - * Read the TM Queue and send TM if necessary. - * Default implementation provided - * @return - */ - virtual ReturnValue_t handleTmQueue(); - - /** - * Send stored data if communication link is active - * @return - */ - virtual ReturnValue_t handleStoredTm(); - - /** - * Implemented by child class. Perform sending of Telemetry by implementing - * communication drivers or wrappers, e.g. serial communication or a socket - * call. - * @param data - * @param dataLen - * @return - */ - virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) = 0; - - /** - * Store data to be sent later if communication link is not up. - * @param message - * @return - */ - virtual ReturnValue_t storeDownlinkData(TmTcMessage * message); - - - /** - * Print data as hexidecimal array - * @param data - * @param dataLen - */ - void printData(uint8_t * data, size_t dataLen); - - /** - * This fifo can be used to store downlink data - * which can not be sent at the moment. - */ - FIFO tmFifo; - uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE; - uint8_t maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED; -}; - - -#endif /* FRAMEWORK_TMTCSERVICES_TMTCBRIDGE_H_ */ +#ifndef FRAMEWORK_TMTCSERVICES_TMTCBRIDGE_H_ +#define FRAMEWORK_TMTCSERVICES_TMTCBRIDGE_H_ + +#include "../objectmanager/SystemObject.h" +#include "AcceptsTelemetryIF.h" +#include "../tasks/ExecutableObjectIF.h" +#include "../ipc/MessageQueueIF.h" +#include "../storagemanager/StorageManagerIF.h" +#include "AcceptsTelecommandsIF.h" + +#include "../container/FIFO.h" +#include "TmTcMessage.h" + +class TmTcBridge : public AcceptsTelemetryIF, + public AcceptsTelecommandsIF, + public ExecutableObjectIF, + public HasReturnvaluesIF, + public SystemObject { +public: + static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20; + static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15; + static constexpr uint8_t LIMIT_DOWNLINK_PACKETS_STORED = 20; + + static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5; + static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10; + + TmTcBridge(object_id_t objectId, object_id_t tcDestination, + object_id_t tmStoreId, object_id_t tcStoreId); + virtual ~TmTcBridge(); + + /** + * Set number of packets sent per performOperation().Please note that this + * value must be smaller than MAX_STORED_DATA_SENT_PER_CYCLE + * @param sentPacketsPerCycle + * @return -@c RETURN_OK if value was set successfully + * -@c RETURN_FAILED otherwise, stored value stays the same + */ + ReturnValue_t setNumberOfSentPacketsPerCycle(uint8_t sentPacketsPerCycle); + + /** + * Set number of packets sent per performOperation().Please note that this + * value must be smaller than MAX_DOWNLINK_PACKETS_STORED + * @param sentPacketsPerCycle + * @return -@c RETURN_OK if value was set successfully + * -@c RETURN_FAILED otherwise, stored value stays the same + */ + ReturnValue_t setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored); + + virtual void registerCommConnect(); + virtual void registerCommDisconnect(); + + /** + * Initializes necessary FSFW components for the TMTC Bridge + * @return + */ + virtual ReturnValue_t initialize() override; + + /** + * @brief Handles TMTC reception + */ + virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override; + + + /** AcceptsTelemetryIF override */ + virtual MessageQueueId_t getReportReceptionQueue( + uint8_t virtualChannel = 0) override; + + /** AcceptsTelecommandsIF override */ + virtual uint16_t getIdentifier() override; + virtual MessageQueueId_t getRequestQueue() override; + +protected: + //! Cached for initialize function. + object_id_t tmStoreId = objects::NO_OBJECT; + object_id_t tcStoreId = objects::NO_OBJECT; + object_id_t tcDestination = objects::NO_OBJECT; + + //! Used to send and receive TMTC messages. + //! The TmTcMessage class is used to transport messages between tasks. + MessageQueueIF* tmTcReceptionQueue = nullptr; + + StorageManagerIF* tmStore = nullptr; + StorageManagerIF* tcStore = nullptr; + + //! Used to specify whether communication link is up. Will be true + //! by default, so telemetry will be handled immediately. + bool communicationLinkUp = true; + bool tmStored = false; + + /** + * @brief Handle TC reception + * @details + * Default implementation provided, but is empty. + * In most cases, TC reception will be handled in a separate task anyway. + * @return + */ + virtual ReturnValue_t handleTc(); + + /** + * Handle Telemetry. Default implementation provided. + * Calls sendTm() + * @return + */ + virtual ReturnValue_t handleTm(); + + /** + * Read the TM Queue and send TM if necessary. + * Default implementation provided + * @return + */ + virtual ReturnValue_t handleTmQueue(); + + /** + * Send stored data if communication link is active + * @return + */ + virtual ReturnValue_t handleStoredTm(); + + /** + * Implemented by child class. Perform sending of Telemetry by implementing + * communication drivers or wrappers, e.g. serial communication or a socket + * call. + * @param data + * @param dataLen + * @return + */ + virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) = 0; + + /** + * Store data to be sent later if communication link is not up. + * @param message + * @return + */ + virtual ReturnValue_t storeDownlinkData(TmTcMessage * message); + + + /** + * Print data as hexidecimal array + * @param data + * @param dataLen + */ + void printData(uint8_t * data, size_t dataLen); + + /** + * This fifo can be used to store downlink data + * which can not be sent at the moment. + */ + FIFO tmFifo; + uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE; + uint8_t maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED; +}; + + +#endif /* FRAMEWORK_TMTCSERVICES_TMTCBRIDGE_H_ */ diff --git a/tmtcservices/TmTcMessage.cpp b/tmtcservices/TmTcMessage.cpp index d437b41e..987bd232 100644 --- a/tmtcservices/TmTcMessage.cpp +++ b/tmtcservices/TmTcMessage.cpp @@ -1,4 +1,4 @@ -#include +#include "TmTcMessage.h" #include diff --git a/tmtcservices/TmTcMessage.h b/tmtcservices/TmTcMessage.h index 73f741fb..b5e1ff8d 100644 --- a/tmtcservices/TmTcMessage.h +++ b/tmtcservices/TmTcMessage.h @@ -1,8 +1,8 @@ #ifndef TMTCMESSAGE_H_ #define TMTCMESSAGE_H_ -#include -#include +#include "../ipc/MessageQueueMessage.h" +#include "../storagemanager/StorageManagerIF.h" /** * @brief This message class is used to pass Telecommand and Telemetry * packets between tasks. diff --git a/tmtcservices/VerificationReporter.cpp b/tmtcservices/VerificationReporter.cpp index 4484fb9b..43e712a2 100644 --- a/tmtcservices/VerificationReporter.cpp +++ b/tmtcservices/VerificationReporter.cpp @@ -1,7 +1,7 @@ -#include -#include -#include -#include +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "AcceptsVerifyMessageIF.h" +#include "PusVerificationReport.h" +#include "VerificationReporter.h" object_id_t VerificationReporter::messageReceiver = 0; diff --git a/tmtcservices/VerificationReporter.h b/tmtcservices/VerificationReporter.h index 370c44c8..29a273c5 100644 --- a/tmtcservices/VerificationReporter.h +++ b/tmtcservices/VerificationReporter.h @@ -1,8 +1,8 @@ #ifndef VERIFICATIONREPORTER_H_ #define VERIFICATIONREPORTER_H_ -#include -#include +#include "../objectmanager/ObjectManagerIF.h" +#include "PusVerificationReport.h" namespace Factory{ void setStaticFrameworkObjectIds(); From 9e0a90509629730ed1c5f316b6bdd4895dcba649 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 13 Aug 2020 20:58:49 +0200 Subject: [PATCH 225/653] Two paths gone wrong --- pus/Service1TelecommandVerification.cpp | 2 +- pus/Service5EventReporting.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pus/Service1TelecommandVerification.cpp b/pus/Service1TelecommandVerification.cpp index 570005c5..578eb02d 100644 --- a/pus/Service1TelecommandVerification.cpp +++ b/pus/Service1TelecommandVerification.cpp @@ -3,7 +3,7 @@ #include "../ipc/QueueFactory.h" #include "../tmtcservices/PusVerificationReport.h" -#include "/tmtcpacketTmPacketStored.h" +#include "../tmtcpacket/pus/TmPacketStored.h" #include "../serviceinterface/ServiceInterfaceStream.h" #include "../tmtcservices/AcceptsTelemetryIF.h" #include "../serviceinterface/ServiceInterfaceStream.h" diff --git a/pus/Service5EventReporting.cpp b/pus/Service5EventReporting.cpp index 831f92c1..829d04bd 100644 --- a/pus/Service5EventReporting.cpp +++ b/pus/Service5EventReporting.cpp @@ -4,7 +4,7 @@ #include "../serviceinterface/ServiceInterfaceStream.h" #include "../events/EventManagerIF.h" #include "../ipc/QueueFactory.h" -#include "/tmtcpacketTmPacketStored.h" +#include "../tmtcpacket/pus/TmPacketStored.h" Service5EventReporting::Service5EventReporting(object_id_t objectId, From 111f9dce7dc4babf632ce8353def90729555b504 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 16 Aug 2020 23:06:32 +0200 Subject: [PATCH 226/653] added host osal --- osal/host/Clock.cpp | 227 +++++++++++++++++++++++++++++++ osal/host/FixedTimeslotTask.cpp | 191 ++++++++++++++++++++++++++ osal/host/FixedTimeslotTask.h | 130 ++++++++++++++++++ osal/host/MessageQueue.cpp | 155 +++++++++++++++++++++ osal/host/MessageQueue.h | 230 ++++++++++++++++++++++++++++++++ osal/host/Mutex.cpp | 40 ++++++ osal/host/Mutex.h | 28 ++++ osal/host/MutexFactory.cpp | 28 ++++ osal/host/PeriodicTask.cpp | 176 ++++++++++++++++++++++++ osal/host/PeriodicTask.h | 123 +++++++++++++++++ osal/host/QueueFactory.cpp | 41 ++++++ osal/host/QueueMapManager.cpp | 51 +++++++ osal/host/QueueMapManager.h | 47 +++++++ osal/host/SemaphoreFactory.cpp | 42 ++++++ osal/host/TaskFactory.cpp | 55 ++++++++ 15 files changed, 1564 insertions(+) create mode 100644 osal/host/Clock.cpp create mode 100644 osal/host/FixedTimeslotTask.cpp create mode 100644 osal/host/FixedTimeslotTask.h create mode 100644 osal/host/MessageQueue.cpp create mode 100644 osal/host/MessageQueue.h create mode 100644 osal/host/Mutex.cpp create mode 100644 osal/host/Mutex.h create mode 100644 osal/host/MutexFactory.cpp create mode 100644 osal/host/PeriodicTask.cpp create mode 100644 osal/host/PeriodicTask.h create mode 100644 osal/host/QueueFactory.cpp create mode 100644 osal/host/QueueMapManager.cpp create mode 100644 osal/host/QueueMapManager.h create mode 100644 osal/host/SemaphoreFactory.cpp create mode 100644 osal/host/TaskFactory.cpp diff --git a/osal/host/Clock.cpp b/osal/host/Clock.cpp new file mode 100644 index 00000000..57f2572b --- /dev/null +++ b/osal/host/Clock.cpp @@ -0,0 +1,227 @@ +#include +#include + +#include +#if defined(WIN32) +#include +#elif defined(LINUX) +#include +#endif + +uint16_t Clock::leapSeconds = 0; +MutexIF* Clock::timeMutex = NULL; + +using SystemClock = std::chrono::system_clock; + +uint32_t Clock::getTicksPerSecond(void){ + sif::warning << "Clock::getTicksPerSecond: not implemented yet" << std::endl; + return 0; + //return CLOCKS_PER_SEC; + //uint32_t ticks = sysconf(_SC_CLK_TCK); + //return ticks; +} + +ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { + // do some magic with chrono + sif::warning << "Clock::setClock: not implemented yet" << std::endl; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::setClock(const timeval* time) { + // do some magic with chrono +#if defined(WIN32) + return HasReturnvaluesIF::RETURN_OK; +#elif defined(LINUX) + return HasReturnvaluesIF::RETURN_OK; +#else + +#endif + sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; +} + +ReturnValue_t Clock::getClock_timeval(timeval* time) { +#if defined(WIN32) + auto now = std::chrono::system_clock::now(); + auto secondsChrono = std::chrono::time_point_cast(now); + auto epoch = now.time_since_epoch(); + time->tv_sec = std::chrono::duration_cast(epoch).count(); + auto fraction = now - secondsChrono; + time->tv_usec = std::chrono::duration_cast( + fraction).count(); + return HasReturnvaluesIF::RETURN_OK; +#elif defined(LINUX) + timespec timeUnix; + int status = clock_gettime(CLOCK_REALTIME,&timeUnix); + if(status!=0){ + return HasReturnvaluesIF::RETURN_FAILED; + } + time->tv_sec = timeUnix.tv_sec; + time->tv_usec = timeUnix.tv_nsec / 1000.0; + return HasReturnvaluesIF::RETURN_OK; +#else + sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; +#endif + +} + +ReturnValue_t Clock::getClock_usecs(uint64_t* time) { + // do some magic with chrono + sif::warning << "Clock::gerClock_usecs: not implemented yet" << std::endl; + return HasReturnvaluesIF::RETURN_OK; +} + +timeval Clock::getUptime() { + timeval timeval; +#if defined(WIN32) + auto uptime = std::chrono::milliseconds(GetTickCount64()); + auto secondsChrono = std::chrono::duration_cast(uptime); + timeval.tv_sec = secondsChrono.count(); + auto fraction = uptime - secondsChrono; + timeval.tv_usec = std::chrono::duration_cast( + fraction).count(); +#elif defined(LINUX) + double uptimeSeconds; + if (std::ifstream("/proc/uptime", std::ios::in) >> uptimeSeconds) + { + // value is rounded down automatically + timeval.tv_sec = uptimeSeconds; + timeval.tv_usec = uptimeSeconds *(double) 1e6 - (timeval.tv_sec *1e6); + } +#else + sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; +#endif + return timeval; +} + +ReturnValue_t Clock::getUptime(timeval* uptime) { + *uptime = getUptime(); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) { + timeval uptime = getUptime(); + *uptimeMs = uptime.tv_sec * 1000 + uptime.tv_usec / 1000; + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { + // do some magic with chrono (C++20!) + // Right now, the library doesn't have the new features yet. + // so we work around that for now. + auto now = SystemClock::now(); + auto seconds = std::chrono::time_point_cast(now); + auto fraction = now - seconds; + time_t tt = SystemClock::to_time_t(now); + struct tm* timeInfo; + timeInfo = gmtime(&tt); + time->year = timeInfo->tm_year + 1900; + time->month = timeInfo->tm_mon+1; + time->day = timeInfo->tm_mday; + time->hour = timeInfo->tm_hour; + time->minute = timeInfo->tm_min; + time->second = timeInfo->tm_sec; + auto usecond = std::chrono::duration_cast(fraction); + time->usecond = usecond.count(); + + //sif::warning << "Clock::getDateAndTime: not implemented yet" << std::endl; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, + timeval* to) { + struct tm time_tm; + + time_tm.tm_year = from->year - 1900; + time_tm.tm_mon = from->month - 1; + time_tm.tm_mday = from->day; + + time_tm.tm_hour = from->hour; + time_tm.tm_min = from->minute; + time_tm.tm_sec = from->second; + + time_t seconds = mktime(&time_tm); + + to->tv_sec = seconds; + to->tv_usec = from->usecond; + //Fails in 2038.. + return HasReturnvaluesIF::RETURN_OK; + sif::warning << "Clock::convertTimeBla: not implemented yet" << std::endl; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) { + *JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. + / 3600.; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) { + //SHOULDDO: works not for dates in the past (might have less leap seconds) + if (timeMutex == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } + + uint16_t leapSeconds; + ReturnValue_t result = getLeapSeconds(&leapSeconds); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + timeval leapSeconds_timeval = { 0, 0 }; + leapSeconds_timeval.tv_sec = leapSeconds; + + //initial offset between UTC and TAI + timeval UTCtoTAI1972 = { 10, 0 }; + + timeval TAItoTT = { 32, 184000 }; + + *tt = utc + leapSeconds_timeval + UTCtoTAI1972 + TAItoTT; + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) { + if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){ + return HasReturnvaluesIF::RETURN_FAILED; + } + ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + leapSeconds = leapSeconds_; + + result = timeMutex->unlockMutex(); + return result; +} + +ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) { + if(timeMutex == nullptr){ + return HasReturnvaluesIF::RETURN_FAILED; + } + ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + *leapSeconds_ = leapSeconds; + + result = timeMutex->unlockMutex(); + return result; +} + +ReturnValue_t Clock::checkOrCreateClockMutex(){ + if(timeMutex == nullptr){ + MutexFactory* mutexFactory = MutexFactory::instance(); + if (mutexFactory == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + timeMutex = mutexFactory->createMutex(); + if (timeMutex == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/osal/host/FixedTimeslotTask.cpp b/osal/host/FixedTimeslotTask.cpp new file mode 100644 index 00000000..dac399f6 --- /dev/null +++ b/osal/host/FixedTimeslotTask.cpp @@ -0,0 +1,191 @@ +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#if defined(WIN32) +#include +#elif defined(LINUX) +#include +#endif + +FixedTimeslotTask::FixedTimeslotTask(const char *name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod setPeriod, + void (*setDeadlineMissedFunc)()) : + started(false), pollingSeqTable(setPeriod*1000), taskName(name), + period(setPeriod), deadlineMissedFunc(setDeadlineMissedFunc) { + // It is propably possible to set task priorities by using the native + // task handles for Windows / Linux + mainThread = std::thread(&FixedTimeslotTask::taskEntryPoint, this, this); +#if defined(WIN32) + /* List of possible priority classes: + * https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ + * nf-processthreadsapi-setpriorityclass + * And respective thread priority numbers: + * https://docs.microsoft.com/en-us/windows/ + * win32/procthread/scheduling-priorities */ + int result = SetPriorityClass( + reinterpret_cast(mainThread.native_handle()), + ABOVE_NORMAL_PRIORITY_CLASS); + if(result != 0) { + sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with code " + << GetLastError() << std::endl; + } + result = SetThreadPriority( + reinterpret_cast(mainThread.native_handle()), + THREAD_PRIORITY_NORMAL); + if(result != 0) { + sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with code " + << GetLastError() << std::endl; + } +#elif defined(LINUX) + // we can just copy and paste the code from linux here. +#endif +} + +FixedTimeslotTask::~FixedTimeslotTask(void) { + //Do not delete objects, we were responsible for ptrs only. + terminateThread = true; + if(mainThread.joinable()) { + mainThread.join(); + } + delete this; +} + +void FixedTimeslotTask::taskEntryPoint(void* argument) { + FixedTimeslotTask *originalTask(reinterpret_cast(argument)); + + if (not originalTask->started) { + // we have to suspend/block here until the task is started. + // if semaphores are implemented, use them here. + std::unique_lock lock(initMutex); + initCondition.wait(lock); + } + + this->taskFunctionality(); + sif::debug << "FixedTimeslotTask::taskEntryPoint: " + "Returned from taskFunctionality." << std::endl; +} + +ReturnValue_t FixedTimeslotTask::startTask() { + started = true; + + // Notify task to start. + std::lock_guard lock(initMutex); + initCondition.notify_one(); + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); + return HasReturnvaluesIF::RETURN_OK; +} + +void FixedTimeslotTask::taskFunctionality() { + // A local iterator for the Polling Sequence Table is created to + // find the start time for the first entry. + FixedSlotSequence::SlotListIter slotListIter = pollingSeqTable.current; + // Get start time for first entry. + chron_ms interval(slotListIter->pollingTimeMs); + auto currentStartTime { + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + }; + if(interval.count() > 0) { + delayForInterval(¤tStartTime, interval); + } + + /* Enter the loop that defines the task behavior. */ + for (;;) { + if(terminateThread.load()) { + break; + } + //The component for this slot is executed and the next one is chosen. + this->pollingSeqTable.executeAndAdvance(); + if (not pollingSeqTable.slotFollowsImmediately()) { + // we need to wait before executing the current slot + //this gives us the time to wait: + interval = chron_ms(this->pollingSeqTable.getIntervalToPreviousSlotMs()); + delayForInterval(¤tStartTime, interval); + //TODO deadline missed check + } + } +} + +ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, + uint32_t slotTimeMs, int8_t executionStep) { + if (objectManager->get(componentId) != nullptr) { + pollingSeqTable.addSlot(componentId, slotTimeMs, executionStep, this); + return HasReturnvaluesIF::RETURN_OK; + } + + sif::error << "Component " << std::hex << componentId << + " not found, not adding it to pst" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; +} + +ReturnValue_t FixedTimeslotTask::checkSequence() const { + return pollingSeqTable.checkSequence(); +} + +uint32_t FixedTimeslotTask::getPeriodMs() const { + return period * 1000; +} + +bool FixedTimeslotTask::delayForInterval(chron_ms * previousWakeTimeMs, + const chron_ms interval) { + bool shouldDelay = false; + //Get current wakeup time + auto currentStartTime = + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()); + /* Generate the tick time at which the task wants to wake. */ + auto nextTimeToWake_ms = (*previousWakeTimeMs) + interval; + + if (currentStartTime < *previousWakeTimeMs) { + /* The tick count has overflowed since this function was + lasted called. In this case the only time we should ever + actually delay is if the wake time has also overflowed, + and the wake time is greater than the tick time. When this + is the case it is as if neither time had overflowed. */ + if ((nextTimeToWake_ms < *previousWakeTimeMs) + && (nextTimeToWake_ms > currentStartTime)) { + shouldDelay = true; + } + } else { + /* The tick time has not overflowed. In this case we will + delay if either the wake time has overflowed, and/or the + tick time is less than the wake time. */ + if ((nextTimeToWake_ms < *previousWakeTimeMs) + || (nextTimeToWake_ms > currentStartTime)) { + shouldDelay = true; + } + } + + /* Update the wake time ready for the next call. */ + + (*previousWakeTimeMs) = nextTimeToWake_ms; + + if (shouldDelay) { + auto sleepTime = std::chrono::duration_cast( + nextTimeToWake_ms - currentStartTime); + std::this_thread::sleep_for(sleepTime); + return true; + } + //We are shifting the time in case the deadline was missed like rtems + (*previousWakeTimeMs) = currentStartTime; + return false; + +} + + + + diff --git a/osal/host/FixedTimeslotTask.h b/osal/host/FixedTimeslotTask.h new file mode 100644 index 00000000..b12cc6d3 --- /dev/null +++ b/osal/host/FixedTimeslotTask.h @@ -0,0 +1,130 @@ +#ifndef FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ +#define FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ + +#include +#include +#include +#include + +#include +#include +#include +#include + +class ExecutableObjectIF; + +/** + * @brief This class represents a task for periodic activities with multiple + * steps and strict timeslot requirements for these steps. + * @details + * @ingroup task_handling + */ +class FixedTimeslotTask: public FixedTimeslotTaskIF { +public: + /** + * @brief Standard constructor of the class. + * @details + * The class is initialized without allocated objects. These need to be + * added with #addComponent. + * @param priority + * @param stack_size + * @param setPeriod + * @param setDeadlineMissedFunc + * The function pointer to the deadline missed function that shall be + * assigned. + */ + FixedTimeslotTask(const char *name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod setPeriod, + void (*setDeadlineMissedFunc)()); + /** + * @brief Currently, the executed object's lifetime is not coupled with + * the task object's lifetime, so the destructor is empty. + */ + virtual ~FixedTimeslotTask(void); + + /** + * @brief The method to start the task. + * @details The method starts the task with the respective system call. + * Entry point is the taskEntryPoint method described below. + * The address of the task object is passed as an argument + * to the system call. + */ + ReturnValue_t startTask(void); + + /** + * Add timeslot to the polling sequence table. + * @param componentId + * @param slotTimeMs + * @param executionStep + * @return + */ + ReturnValue_t addSlot(object_id_t componentId, + uint32_t slotTimeMs, int8_t executionStep); + + ReturnValue_t checkSequence() const; + + uint32_t getPeriodMs() const; + + ReturnValue_t sleepFor(uint32_t ms); + +protected: + using chron_ms = std::chrono::milliseconds; + + bool started; + //!< Typedef for the List of objects. + typedef std::vector ObjectList; + std::thread mainThread; + std::atomic terminateThread = false; + + //! Polling sequence table which contains the object to execute + //! and information like the timeslots and the passed execution step. + FixedSlotSequence pollingSeqTable; + + std::condition_variable initCondition; + std::mutex initMutex; + std::string taskName; + /** + * @brief The period of the task. + * @details + * The period determines the frequency of the task's execution. + * It is expressed in clock ticks. + */ + TaskPeriod period; + + /** + * @brief The pointer to the deadline-missed function. + * @details + * This pointer stores the function that is executed if the task's deadline + * is missed. So, each may react individually on a timing failure. + * The pointer may be NULL, then nothing happens on missing the deadline. + * The deadline is equal to the next execution of the periodic task. + */ + void (*deadlineMissedFunc)(void); + /** + * @brief This is the function executed in the new task's context. + * @details + * It converts the argument back to the thread object type and copies the + * class instance to the task context. + * The taskFunctionality method is called afterwards. + * @param A pointer to the task object itself is passed as argument. + */ + + void taskEntryPoint(void* argument); + /** + * @brief The function containing the actual functionality of the task. + * @details + * The method sets and starts the task's period, then enters a loop that is + * repeated as long as the isRunning attribute is true. Within the loop, + * all performOperation methods of the added objects are called. Afterwards + * the checkAndRestartPeriod system call blocks the task until the next + * period. On missing the deadline, the deadlineMissedFunction is executed. + */ + void taskFunctionality(void); + + bool delayForInterval(chron_ms * previousWakeTimeMs, + const chron_ms interval); +}; + + + +#endif /* FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ */ diff --git a/osal/host/MessageQueue.cpp b/osal/host/MessageQueue.cpp new file mode 100644 index 00000000..7af5fbd9 --- /dev/null +++ b/osal/host/MessageQueue.cpp @@ -0,0 +1,155 @@ +#include +#include +#include +#include +#include + +MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize): + messageSize(maxMessageSize), messageDepth(messageDepth) { + queueLock = MutexFactory::instance()->createMutex(); + auto result = QueueMapManager::instance()->addMessageQueue(this, &mqId); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "MessageQueue: Could not be created" << std::endl; + } +} + +MessageQueue::~MessageQueue() { + MutexFactory::instance()->deleteMutex(queueLock); +} + +ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, bool ignoreFault) { + return sendMessageFrom(sendTo, message, this->getId(), ignoreFault); +} + +ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) { + return sendToDefaultFrom(message, this->getId()); +} + +ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message, + MessageQueueId_t sentFrom, bool ignoreFault) { + return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault); +} + +ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) { + if (this->lastPartner != 0) { + return sendMessageFrom(this->lastPartner, message, this->getId()); + } else { + return MessageQueueIF::NO_REPLY_PARTNER; + } +} + +ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + return sendMessageFromMessageQueue(sendTo, message, sentFrom, + ignoreFault); +} + +ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message, + MessageQueueId_t* receivedFrom) { + ReturnValue_t status = this->receiveMessage(message); + if(status == HasReturnvaluesIF::RETURN_OK) { + *receivedFrom = this->lastPartner; + } + return status; +} + +ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { + if(messageQueue.empty()) { + return MessageQueueIF::EMPTY; + } + // not sure this will work.. + //*message = std::move(messageQueue.front()); + MutexHelper mutexLock(queueLock, 20); + MessageQueueMessage* currentMessage = &messageQueue.front(); + std::copy(currentMessage->getBuffer(), + currentMessage->getBuffer() + messageSize, message->getBuffer()); + messageQueue.pop(); + // The last partner is the first uint32_t field in the message + this->lastPartner = message->getSender(); + return HasReturnvaluesIF::RETURN_OK; +} + +MessageQueueId_t MessageQueue::getLastPartner() const { + return lastPartner; +} + +ReturnValue_t MessageQueue::flush(uint32_t* count) { + *count = messageQueue.size(); + // Clears the queue. + messageQueue = std::queue(); + return HasReturnvaluesIF::RETURN_OK; +} + +MessageQueueId_t MessageQueue::getId() const { + return mqId; +} + +void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) { + defaultDestinationSet = true; + this->defaultDestination = defaultDestination; +} + +MessageQueueId_t MessageQueue::getDefaultDestination() const { + return defaultDestination; +} + +bool MessageQueue::isDefaultDestinationSet() const { + return defaultDestinationSet; +} + + +// static core function to send messages. +ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + if(message->getMessageSize() > message->getMaximumMessageSize()) { + // Actually, this should never happen or an error will be emitted + // in MessageQueueMessage. + // But I will still return a failure here. + return HasReturnvaluesIF::RETURN_FAILED; + } + MessageQueue* targetQueue = dynamic_cast( + QueueMapManager::instance()->getMessageQueue(sendTo)); + if(targetQueue == nullptr) { + if(not ignoreFault) { + InternalErrorReporterIF* internalErrorReporter = + objectManager->get( + objects::INTERNAL_ERROR_REPORTER); + if (internalErrorReporter != nullptr) { + internalErrorReporter->queueMessageNotSent(); + } + } + // TODO: Better returnvalue + return HasReturnvaluesIF::RETURN_FAILED; + } + + if(targetQueue->messageQueue.size() < targetQueue->messageDepth) { + MutexHelper mutexLock(targetQueue->queueLock, 20); + // not ideal, works for now though. + MessageQueueMessage* mqmMessage = + dynamic_cast(message); + if(message != nullptr) { + targetQueue->messageQueue.push(*mqmMessage); + } + else { + sif::error << "MessageQueue::sendMessageFromMessageQueue: Message" + "is not MessageQueueMessage!" << std::endl; + } + + } + else { + return MessageQueueIF::FULL; + } + message->setSender(sentFrom); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t MessageQueue::lockQueue(dur_millis_t lockTimeout) { + return queueLock->lockMutex(lockTimeout); +} + +ReturnValue_t MessageQueue::unlockQueue() { + return queueLock->unlockMutex(); +} diff --git a/osal/host/MessageQueue.h b/osal/host/MessageQueue.h new file mode 100644 index 00000000..7fc77f7a --- /dev/null +++ b/osal/host/MessageQueue.h @@ -0,0 +1,230 @@ +#ifndef FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ +#define FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ + +#include +#include +#include +#include +#include + +#include +#include + +/** + * @brief This class manages sending and receiving of + * message queue messages. + * @details + * Message queues are used to pass asynchronous messages between processes. + * They work like post boxes, where all incoming messages are stored in FIFO + * order. This class creates a new receiving queue and provides methods to fetch + * received messages. Being a child of MessageQueueSender, this class also + * provides methods to send a message to a user-defined or a default destination. + * In addition it also provides a reply method to answer to the queue it + * received its last message from. + * + * The MessageQueue should be used as "post box" for a single owning object. + * So all message queue communication is "n-to-one". + * For creating the queue, as well as sending and receiving messages, the class + * makes use of the operating system calls provided. + * + * Please keep in mind that FreeRTOS offers different calls for message queue + * operations if called from an ISR. + * For now, the system context needs to be switched manually. + * @ingroup osal + * @ingroup message_queue + */ +class MessageQueue : public MessageQueueIF { + friend class MessageQueueSenderIF; +public: + /** + * @brief The constructor initializes and configures the message queue. + * @details + * By making use of the according operating system call, a message queue is + * created and initialized. The message depth - the maximum number of + * messages to be buffered - may be set with the help of a parameter, + * whereas the message size is automatically set to the maximum message + * queue message size. The operating system sets the message queue id, or + * in case of failure, it is set to zero. + * @param message_depth + * The number of messages to be buffered before passing an error to the + * sender. Default is three. + * @param max_message_size + * With this parameter, the maximum message size can be adjusted. + * This should be left default. + */ + MessageQueue(size_t messageDepth = 3, + size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE); + + /** Copying message queues forbidden */ + MessageQueue(const MessageQueue&) = delete; + MessageQueue& operator=(const MessageQueue&) = delete; + + /** + * @brief The destructor deletes the formerly created message queue. + * @details This is accomplished by using the delete call provided + * by the operating system. + */ + virtual ~MessageQueue(); + + /** + * @brief This operation sends a message to the given destination. + * @details It directly uses the sendMessage call of the MessageQueueSender + * parent, but passes its queue id as "sentFrom" parameter. + * @param sendTo This parameter specifies the message queue id of the + * destination message queue. + * @param message A pointer to a previously created message, which is sent. + * @param ignoreFault If set to true, the internal software fault counter + * is not incremented if queue is full. + */ + ReturnValue_t sendMessage(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, bool ignoreFault = false) override; + /** + * @brief This operation sends a message to the default destination. + * @details As in the sendMessage method, this function uses the + * sendToDefault call of the MessageQueueSender parent class and adds its + * queue id as "sentFrom" information. + * @param message A pointer to a previously created message, which is sent. + */ + ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override; + /** + * @brief This operation sends a message to the last communication partner. + * @details This operation simplifies answering an incoming message by using + * the stored lastPartner information as destination. If there was no + * message received yet (i.e. lastPartner is zero), an error code is returned. + * @param message A pointer to a previously created message, which is sent. + */ + ReturnValue_t reply(MessageQueueMessageIF* message) override; + + /** + * @brief With the sendMessage call, a queue message is sent to a + * receiving queue. + * @details + * This method takes the message provided, adds the sentFrom information and + * passes it on to the destination provided with an operating system call. + * The OS's return value is returned. + * @param sendTo This parameter specifies the message queue id to send + * the message to. + * @param message This is a pointer to a previously created message, + * which is sent. + * @param sentFrom The sentFrom information can be set to inject the + * sender's queue id into the message. This variable is set to zero by + * default. + * @param ignoreFault If set to true, the internal software fault counter + * is not incremented if queue is full. + */ + virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE, + bool ignoreFault = false) override; + + /** + * @brief The sendToDefault method sends a queue message to the default + * destination. + * @details + * In all other aspects, it works identical to the sendMessage method. + * @param message This is a pointer to a previously created message, + * which is sent. + * @param sentFrom The sentFrom information can be set to inject the + * sender's queue id into the message. This variable is set to zero by + * default. + */ + virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message, + MessageQueueId_t sentFrom = NO_QUEUE, + bool ignoreFault = false) override; + + /** + * @brief This function reads available messages from the message queue + * and returns the sender. + * @details + * It works identically to the other receiveMessage call, but in addition + * returns the sender's queue id. + * @param message A pointer to a message in which the received data is stored. + * @param receivedFrom A pointer to a queue id in which the sender's id is stored. + */ + ReturnValue_t receiveMessage(MessageQueueMessageIF* message, + MessageQueueId_t *receivedFrom) override; + + /** + * @brief This function reads available messages from the message queue. + * @details + * If data is available it is stored in the passed message pointer. + * The message's original content is overwritten and the sendFrom + * information is stored in the lastPartner attribute. Else, the lastPartner + * information remains untouched, the message's content is cleared and the + * function returns immediately. + * @param message A pointer to a message in which the received data is stored. + */ + ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override; + /** + * Deletes all pending messages in the queue. + * @param count The number of flushed messages. + * @return RETURN_OK on success. + */ + ReturnValue_t flush(uint32_t* count) override; + /** + * @brief This method returns the message queue id of the last + * communication partner. + */ + MessageQueueId_t getLastPartner() const override; + /** + * @brief This method returns the message queue id of this class's + * message queue. + */ + MessageQueueId_t getId() const override; + + /** + * @brief This method is a simple setter for the default destination. + */ + void setDefaultDestination(MessageQueueId_t defaultDestination) override; + /** + * @brief This method is a simple getter for the default destination. + */ + MessageQueueId_t getDefaultDestination() const override; + + bool isDefaultDestinationSet() const override; + + ReturnValue_t lockQueue(dur_millis_t lockTimeout); + ReturnValue_t unlockQueue(); +protected: + /** + * @brief Implementation to be called from any send Call within + * MessageQueue and MessageQueueSenderIF. + * @details + * This method takes the message provided, adds the sentFrom information and + * passes it on to the destination provided with an operating system call. + * The OS's return value is returned. + * @param sendTo + * This parameter specifies the message queue id to send the message to. + * @param message + * This is a pointer to a previously created message, which is sent. + * @param sentFrom + * The sentFrom information can be set to inject the sender's queue id into + * the message. This variable is set to zero by default. + * @param ignoreFault + * If set to true, the internal software fault counter is not incremented + * if queue is full. + * @param context Specify whether call is made from task or from an ISR. + */ + static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE, + bool ignoreFault=false); + + //static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault); + +private: + std::queue messageQueue; + /** + * @brief The class stores the queue id it got assigned. + * If initialization fails, the queue id is set to zero. + */ + MessageQueueId_t mqId = 0; + size_t messageSize = 0; + size_t messageDepth = 0; + + MutexIF* queueLock; + + bool defaultDestinationSet = false; + MessageQueueId_t defaultDestination = 0; + MessageQueueId_t lastPartner = 0; +}; + +#endif /* FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ */ diff --git a/osal/host/Mutex.cpp b/osal/host/Mutex.cpp new file mode 100644 index 00000000..03948c4c --- /dev/null +++ b/osal/host/Mutex.cpp @@ -0,0 +1,40 @@ +#include +#include + +const uint32_t MutexIF::POLLING = 0; +const uint32_t MutexIF::BLOCKING = 0xffffffff; + +ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { + if(timeoutMs == MutexIF::BLOCKING) { + mutex.lock(); + locked = true; + return HasReturnvaluesIF::RETURN_OK; + } + else if(timeoutMs == MutexIF::POLLING) { + if(mutex.try_lock()) { + locked = true; + return HasReturnvaluesIF::RETURN_OK; + } + } + else if(timeoutMs > MutexIF::POLLING){ + auto chronoMs = std::chrono::milliseconds(timeoutMs); + if(mutex.try_lock_for(chronoMs)) { + locked = true; + return HasReturnvaluesIF::RETURN_OK; + } + } + return MutexIF::MUTEX_TIMEOUT; +} + +ReturnValue_t Mutex::unlockMutex() { + if(not locked) { + return MutexIF::CURR_THREAD_DOES_NOT_OWN_MUTEX; + } + mutex.unlock(); + locked = false; + return HasReturnvaluesIF::RETURN_OK; +} + +std::timed_mutex* Mutex::getMutexHandle() { + return &mutex; +} diff --git a/osal/host/Mutex.h b/osal/host/Mutex.h new file mode 100644 index 00000000..d882c457 --- /dev/null +++ b/osal/host/Mutex.h @@ -0,0 +1,28 @@ +#ifndef FRAMEWORK_OSAL_FREERTOS_MUTEX_H_ +#define FRAMEWORK_OSAL_FREERTOS_MUTEX_H_ + +#include + +#include + +/** + * @brief OS component to implement MUTual EXclusion + * + * @details + * Mutexes are binary semaphores which include a priority inheritance mechanism. + * Documentation: https://www.freertos.org/Real-time-embedded-RTOS-mutexes.html + * @ingroup osal + */ +class Mutex : public MutexIF { +public: + Mutex() = default; + ReturnValue_t lockMutex(uint32_t timeoutMs = MutexIF::BLOCKING) override; + ReturnValue_t unlockMutex() override; + + std::timed_mutex* getMutexHandle(); +private: + bool locked = false; + std::timed_mutex mutex; +}; + +#endif /* FRAMEWORK_FREERTOS_MUTEX_H_ */ diff --git a/osal/host/MutexFactory.cpp b/osal/host/MutexFactory.cpp new file mode 100644 index 00000000..25d9fa46 --- /dev/null +++ b/osal/host/MutexFactory.cpp @@ -0,0 +1,28 @@ +#include +#include + +//TODO: Different variant than the lazy loading in QueueFactory. +//What's better and why? -> one is on heap the other on bss/data +//MutexFactory* MutexFactory::factoryInstance = new MutexFactory(); +MutexFactory* MutexFactory::factoryInstance = nullptr; + +MutexFactory::MutexFactory() { +} + +MutexFactory::~MutexFactory() { +} + +MutexFactory* MutexFactory::instance() { + if (factoryInstance == nullptr){ + factoryInstance = new MutexFactory(); + } + return MutexFactory::factoryInstance; +} + +MutexIF* MutexFactory::createMutex() { + return new Mutex(); +} + +void MutexFactory::deleteMutex(MutexIF* mutex) { + delete mutex; +} diff --git a/osal/host/PeriodicTask.cpp b/osal/host/PeriodicTask.cpp new file mode 100644 index 00000000..1a5024ab --- /dev/null +++ b/osal/host/PeriodicTask.cpp @@ -0,0 +1,176 @@ +#include +#include +#include + +#include +#include + +#include +#include + +#if defined(WIN32) +#include +#elif defined(LINUX) +#include +#endif + +PeriodicTask::PeriodicTask(const char *name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod setPeriod, + void (*setDeadlineMissedFunc)()) : + started(false), taskName(name), period(setPeriod), + deadlineMissedFunc(setDeadlineMissedFunc) { + // It is propably possible to set task priorities by using the native + // task handles for Windows / Linux + mainThread = std::thread(&PeriodicTask::taskEntryPoint, this, this); +#if defined(WIN32) + /* List of possible priority classes: + * https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ + * nf-processthreadsapi-setpriorityclass + * And respective thread priority numbers: + * https://docs.microsoft.com/en-us/windows/ + * win32/procthread/scheduling-priorities */ + int result = SetPriorityClass( + reinterpret_cast(mainThread.native_handle()), + ABOVE_NORMAL_PRIORITY_CLASS); + if(result != 0) { + sif::error << "PeriodicTask: Windows SetPriorityClass failed with code " + << GetLastError() << std::endl; + } + result = SetThreadPriority( + reinterpret_cast(mainThread.native_handle()), + THREAD_PRIORITY_NORMAL); + if(result != 0) { + sif::error << "PeriodicTask: Windows SetPriorityClass failed with code " + << GetLastError() << std::endl; + } +#elif defined(LINUX) + // we can just copy and paste the code from linux here. +#endif +} + +PeriodicTask::~PeriodicTask(void) { + //Do not delete objects, we were responsible for ptrs only. + terminateThread = true; + if(mainThread.joinable()) { + mainThread.join(); + } + delete this; +} + +void PeriodicTask::taskEntryPoint(void* argument) { + PeriodicTask *originalTask(reinterpret_cast(argument)); + + + if (not originalTask->started) { + // we have to suspend/block here until the task is started. + // if semaphores are implemented, use them here. + std::unique_lock lock(initMutex); + initCondition.wait(lock); + } + + this->taskFunctionality(); + sif::debug << "PeriodicTask::taskEntryPoint: " + "Returned from taskFunctionality." << std::endl; +} + +ReturnValue_t PeriodicTask::startTask() { + started = true; + + // Notify task to start. + std::lock_guard lock(initMutex); + initCondition.notify_one(); + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) { + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); + return HasReturnvaluesIF::RETURN_OK; +} + +void PeriodicTask::taskFunctionality() { + std::chrono::milliseconds periodChrono(static_cast(period*1000)); + auto currentStartTime { + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + }; + auto nextStartTime{ currentStartTime }; + + /* Enter the loop that defines the task behavior. */ + for (;;) { + if(terminateThread.load()) { + break; + } + for (ObjectList::iterator it = objectList.begin(); + it != objectList.end(); ++it) { + (*it)->performOperation(); + } + if(not delayForInterval(¤tStartTime, periodChrono)) { + sif::warning << "PeriodicTask: " << taskName << + " missed deadline!\n" << std::flush; + if(deadlineMissedFunc != nullptr) { + this->deadlineMissedFunc(); + } + } + } +} + +ReturnValue_t PeriodicTask::addComponent(object_id_t object) { + ExecutableObjectIF* newObject = objectManager->get( + object); + if (newObject == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + objectList.push_back(newObject); + return HasReturnvaluesIF::RETURN_OK; +} + +uint32_t PeriodicTask::getPeriodMs() const { + return period * 1000; +} + +bool PeriodicTask::delayForInterval(chron_ms* previousWakeTimeMs, + const chron_ms interval) { + bool shouldDelay = false; + //Get current wakeup time + auto currentStartTime = + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()); + /* Generate the tick time at which the task wants to wake. */ + auto nextTimeToWake_ms = (*previousWakeTimeMs) + interval; + + if (currentStartTime < *previousWakeTimeMs) { + /* The tick count has overflowed since this function was + lasted called. In this case the only time we should ever + actually delay is if the wake time has also overflowed, + and the wake time is greater than the tick time. When this + is the case it is as if neither time had overflowed. */ + if ((nextTimeToWake_ms < *previousWakeTimeMs) + && (nextTimeToWake_ms > currentStartTime)) { + shouldDelay = true; + } + } else { + /* The tick time has not overflowed. In this case we will + delay if either the wake time has overflowed, and/or the + tick time is less than the wake time. */ + if ((nextTimeToWake_ms < *previousWakeTimeMs) + || (nextTimeToWake_ms > currentStartTime)) { + shouldDelay = true; + } + } + + /* Update the wake time ready for the next call. */ + + (*previousWakeTimeMs) = nextTimeToWake_ms; + + if (shouldDelay) { + auto sleepTime = std::chrono::duration_cast( + nextTimeToWake_ms - currentStartTime); + std::this_thread::sleep_for(sleepTime); + return true; + } + //We are shifting the time in case the deadline was missed like rtems + (*previousWakeTimeMs) = currentStartTime; + return false; + +} diff --git a/osal/host/PeriodicTask.h b/osal/host/PeriodicTask.h new file mode 100644 index 00000000..d97bf089 --- /dev/null +++ b/osal/host/PeriodicTask.h @@ -0,0 +1,123 @@ +#ifndef FRAMEWORK_OSAL_HOST_PERIODICTASK_H_ +#define FRAMEWORK_OSAL_HOST_PERIODICTASK_H_ + +#include +#include +#include + +#include +#include +#include +#include + +class ExecutableObjectIF; + +/** + * @brief This class represents a specialized task for + * periodic activities of multiple objects. + * @details + * + * @ingroup task_handling + */ +class PeriodicTask: public PeriodicTaskIF { +public: + /** + * @brief Standard constructor of the class. + * @details + * The class is initialized without allocated objects. These need to be + * added with #addComponent. + * @param priority + * @param stack_size + * @param setPeriod + * @param setDeadlineMissedFunc + * The function pointer to the deadline missed function that shall be + * assigned. + */ + PeriodicTask(const char *name, TaskPriority setPriority, TaskStackSize setStack, + TaskPeriod setPeriod,void (*setDeadlineMissedFunc)()); + /** + * @brief Currently, the executed object's lifetime is not coupled with + * the task object's lifetime, so the destructor is empty. + */ + virtual ~PeriodicTask(void); + + /** + * @brief The method to start the task. + * @details The method starts the task with the respective system call. + * Entry point is the taskEntryPoint method described below. + * The address of the task object is passed as an argument + * to the system call. + */ + ReturnValue_t startTask(void); + /** + * Adds an object to the list of objects to be executed. + * The objects are executed in the order added. + * @param object Id of the object to add. + * @return + * -@c RETURN_OK on success + * -@c RETURN_FAILED if the object could not be added. + */ + ReturnValue_t addComponent(object_id_t object); + + uint32_t getPeriodMs() const; + + ReturnValue_t sleepFor(uint32_t ms); + +protected: + using chron_ms = std::chrono::milliseconds; + bool started; + //!< Typedef for the List of objects. + typedef std::vector ObjectList; + std::thread mainThread; + std::atomic terminateThread = false; + + /** + * @brief This attribute holds a list of objects to be executed. + */ + ObjectList objectList; + + std::condition_variable initCondition; + std::mutex initMutex; + std::string taskName; + /** + * @brief The period of the task. + * @details + * The period determines the frequency of the task's execution. + * It is expressed in clock ticks. + */ + TaskPeriod period; + /** + * @brief The pointer to the deadline-missed function. + * @details + * This pointer stores the function that is executed if the task's deadline + * is missed. So, each may react individually on a timing failure. + * The pointer may be NULL, then nothing happens on missing the deadline. + * The deadline is equal to the next execution of the periodic task. + */ + void (*deadlineMissedFunc)(void); + /** + * @brief This is the function executed in the new task's context. + * @details + * It converts the argument back to the thread object type and copies the + * class instance to the task context. + * The taskFunctionality method is called afterwards. + * @param A pointer to the task object itself is passed as argument. + */ + + void taskEntryPoint(void* argument); + /** + * @brief The function containing the actual functionality of the task. + * @details + * The method sets and starts the task's period, then enters a loop that is + * repeated as long as the isRunning attribute is true. Within the loop, + * all performOperation methods of the added objects are called. Afterwards + * the checkAndRestartPeriod system call blocks the task until the next + * period. On missing the deadline, the deadlineMissedFunction is executed. + */ + void taskFunctionality(void); + + bool delayForInterval(chron_ms * previousWakeTimeMs, + const chron_ms interval); +}; + +#endif /* PERIODICTASK_H_ */ diff --git a/osal/host/QueueFactory.cpp b/osal/host/QueueFactory.cpp new file mode 100644 index 00000000..225bb8c7 --- /dev/null +++ b/osal/host/QueueFactory.cpp @@ -0,0 +1,41 @@ +#include +#include +#include +#include + +QueueFactory* QueueFactory::factoryInstance = nullptr; + + +ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + return MessageQueue::sendMessageFromMessageQueue(sendTo,message, + sentFrom,ignoreFault); + return HasReturnvaluesIF::RETURN_OK; +} + +QueueFactory* QueueFactory::instance() { + if (factoryInstance == nullptr) { + factoryInstance = new QueueFactory; + } + return factoryInstance; +} + +QueueFactory::QueueFactory() { +} + +QueueFactory::~QueueFactory() { +} + +MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, + size_t maxMessageSize) { + // A thread-safe queue can be implemented by using a combination + // of std::queue and std::mutex. This uses dynamic memory allocation + // which could be alleviated by using a custom allocator, external library + // (etl::queue) or simply using std::queue, we're on a host machine anyway. + return new MessageQueue(messageDepth, maxMessageSize); +} + +void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { + delete queue; +} diff --git a/osal/host/QueueMapManager.cpp b/osal/host/QueueMapManager.cpp new file mode 100644 index 00000000..89b9a948 --- /dev/null +++ b/osal/host/QueueMapManager.cpp @@ -0,0 +1,51 @@ +#include +#include +#include + +QueueMapManager* QueueMapManager::mqManagerInstance = nullptr; + +QueueMapManager::QueueMapManager() { + mapLock = MutexFactory::instance()->createMutex(); +} + +QueueMapManager* QueueMapManager::instance() { + if (mqManagerInstance == nullptr){ + mqManagerInstance = new QueueMapManager(); + } + return QueueMapManager::mqManagerInstance; +} + +ReturnValue_t QueueMapManager::addMessageQueue( + MessageQueueIF* queueToInsert, MessageQueueId_t* id) { + // Not thread-safe, but it is assumed all message queues are created + // at software initialization now. If this is to be made thread-safe in + // the future, it propably would be sufficient to lock the increment + // operation here + uint32_t currentId = queueCounter++; + auto returnPair = queueMap.emplace(currentId, queueToInsert); + if(not returnPair.second) { + // this should never happen for the atomic variable. + sif::error << "QueueMapManager: This ID is already inside the map!" + << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if (id != nullptr) { + *id = currentId; + } + return HasReturnvaluesIF::RETURN_OK; +} + +MessageQueueIF* QueueMapManager::getMessageQueue( + MessageQueueId_t messageQueueId) const { + MutexHelper(mapLock, 50); + auto queueIter = queueMap.find(messageQueueId); + if(queueIter != queueMap.end()) { + return queueIter->second; + } + else { + sif::warning << "QueueMapManager::getQueueHandle: The ID" << + messageQueueId << " does not exists in the map" << std::endl; + return nullptr; + } +} + diff --git a/osal/host/QueueMapManager.h b/osal/host/QueueMapManager.h new file mode 100644 index 00000000..a2a1b658 --- /dev/null +++ b/osal/host/QueueMapManager.h @@ -0,0 +1,47 @@ +#ifndef FRAMEWORK_OSAL_HOST_QUEUEMAP_H_ +#define FRAMEWORK_OSAL_HOST_QUEUEMAP_H_ + +#include +#include +#include +#include + +using QueueMap = std::unordered_map; + + +/** + * An internal map to map message queue IDs to message queues. + * This propably should be a singleton.. + */ +class QueueMapManager { +public: + //! Returns the single instance of SemaphoreFactory. + static QueueMapManager* instance(); + + /** + * Insert a message queue into the map and returns a message queue ID + * @param queue The message queue to insert. + * @param id The passed value will be set unless a nullptr is passed + * @return + */ + ReturnValue_t addMessageQueue(MessageQueueIF* queue, MessageQueueId_t* + id = nullptr); + /** + * Get the message queue handle by providing a message queue ID. + * @param messageQueueId + * @return + */ + MessageQueueIF* getMessageQueue(MessageQueueId_t messageQueueId) const; + +private: + //! External instantiation is forbidden. + QueueMapManager(); + uint32_t queueCounter = 1; + MutexIF* mapLock; + QueueMap queueMap; + static QueueMapManager* mqManagerInstance; +}; + + + +#endif /* FRAMEWORK_OSAL_HOST_QUEUEMAP_H_ */ diff --git a/osal/host/SemaphoreFactory.cpp b/osal/host/SemaphoreFactory.cpp new file mode 100644 index 00000000..0c077f68 --- /dev/null +++ b/osal/host/SemaphoreFactory.cpp @@ -0,0 +1,42 @@ +#include +#include +#include +#include + +const uint32_t SemaphoreIF::POLLING = 0; +const uint32_t SemaphoreIF::BLOCKING = 0xFFFFFFFF; + +SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; + +SemaphoreFactory::SemaphoreFactory() { +} + +SemaphoreFactory::~SemaphoreFactory() { + delete factoryInstance; +} + +SemaphoreFactory* SemaphoreFactory::instance() { + if (factoryInstance == nullptr){ + factoryInstance = new SemaphoreFactory(); + } + return SemaphoreFactory::factoryInstance; +} + +SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t arguments) { + // Just gonna wait for full C++20 for now. + sif::error << "SemaphoreFactory: Binary Semaphore not implemented yet." + " Returning nullptr!\n" << std::flush; + return nullptr; +} + +SemaphoreIF* SemaphoreFactory::createCountingSemaphore(const uint8_t maxCount, + uint8_t initCount, uint32_t arguments) { + // Just gonna wait for full C++20 for now. + sif::error << "SemaphoreFactory: Counting Semaphore not implemented yet." + " Returning nullptr!\n" << std::flush; + return nullptr; +} + +void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { + delete semaphore; +} diff --git a/osal/host/TaskFactory.cpp b/osal/host/TaskFactory.cpp new file mode 100644 index 00000000..9db8ac4d --- /dev/null +++ b/osal/host/TaskFactory.cpp @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include + +#include + +TaskFactory* TaskFactory::factoryInstance = new TaskFactory(); + +// Will propably not be used for hosted implementation +const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = 0; + +TaskFactory::TaskFactory() { +} + +TaskFactory::~TaskFactory() { +} + +TaskFactory* TaskFactory::instance() { + return TaskFactory::factoryInstance; +} + +PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, + TaskPriority taskPriority_,TaskStackSize stackSize_, + TaskPeriod periodInSeconds_, + TaskDeadlineMissedFunction deadLineMissedFunction_) { + // This is going to be interesting. Time now learn the C++ threading library + // :-) + return new PeriodicTask(name_, taskPriority_, stackSize_, periodInSeconds_, + deadLineMissedFunction_); +} + +FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_, + TaskPriority taskPriority_,TaskStackSize stackSize_, + TaskPeriod periodInSeconds_, + TaskDeadlineMissedFunction deadLineMissedFunction_) { + // This is going to be interesting. Time now learn the C++ threading library + // :-) + return new FixedTimeslotTask(name_, taskPriority_, stackSize_, + periodInSeconds_, deadLineMissedFunction_); +} + +ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) { + // This might block for some time! + delete task; + return HasReturnvaluesIF::RETURN_FAILED; +} + +ReturnValue_t TaskFactory::delayTask(uint32_t delayMs){ + std::this_thread::sleep_for(std::chrono::milliseconds(delayMs)); + return HasReturnvaluesIF::RETURN_OK; +} + + From 549ad97bd3b2ee6b05af2383e7a30ef1ac846f5c Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 18 Aug 2020 11:25:57 +0200 Subject: [PATCH 227/653] shared ring buffer pull request --- container/SharedRingBuffer.cpp | 30 +++++++++++++++ container/SharedRingBuffer.h | 68 ++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 container/SharedRingBuffer.cpp create mode 100644 container/SharedRingBuffer.h diff --git a/container/SharedRingBuffer.cpp b/container/SharedRingBuffer.cpp new file mode 100644 index 00000000..001a21ed --- /dev/null +++ b/container/SharedRingBuffer.cpp @@ -0,0 +1,30 @@ +#include +#include +#include + +SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size, + bool overwriteOld, size_t maxExcessBytes): + SystemObject(objectId), SimpleRingBuffer(size, overwriteOld, + maxExcessBytes) { + mutex = MutexFactory::instance()->createMutex(); +} + +SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer, + const size_t size, bool overwriteOld, size_t maxExcessBytes): + SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld, + maxExcessBytes) { + mutex = MutexFactory::instance()->createMutex(); +} + +ReturnValue_t SharedRingBuffer::lockRingBufferMutex( + MutexIF::TimeoutType timeoutType, dur_millis_t timeout) { + return mutex->lockMutex(timeoutType, timeout); +} + +ReturnValue_t SharedRingBuffer::unlockRingBufferMutex() { + return mutex->unlockMutex(); +} + +MutexIF* SharedRingBuffer::getMutexHandle() const { + return mutex; +} diff --git a/container/SharedRingBuffer.h b/container/SharedRingBuffer.h new file mode 100644 index 00000000..0b5be052 --- /dev/null +++ b/container/SharedRingBuffer.h @@ -0,0 +1,68 @@ +#ifndef FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ +#define FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ + +#include +#include +#include +#include + +/** + * @brief Ring buffer which can be shared among multiple objects + * @details + * This class offers a mutex to perform thread-safe operation on the ring + * buffer. It is still up to the developer to actually perform the lock + * and unlock operations. + */ +class SharedRingBuffer: public SystemObject, + public SimpleRingBuffer { +public: + /** + * This constructor allocates a new internal buffer with the supplied size. + * @param size + * @param overwriteOld + * If the ring buffer is overflowing at a write operartion, the oldest data + * will be overwritten. + */ + SharedRingBuffer(object_id_t objectId, const size_t size, + bool overwriteOld, size_t maxExcessBytes); + + /** + * This constructor takes an external buffer with the specified size. + * @param buffer + * @param size + * @param overwriteOld + * If the ring buffer is overflowing at a write operartion, the oldest data + * will be overwritten. + */ + SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size, + bool overwriteOld, size_t maxExcessBytes); + + /** + * Unless a read-only constant value is read, all operations on the + * shared ring buffer should be protected by calling this function. + * @param timeoutType + * @param timeout + * @return + */ + virtual ReturnValue_t lockRingBufferMutex(MutexIF::TimeoutType timeoutType, + dur_millis_t timeout); + /** + * Any locked mutex also has to be unlocked, otherwise, access to the + * shared ring buffer will be blocked. + * @return + */ + virtual ReturnValue_t unlockRingBufferMutex(); + + /** + * The mutex handle can be accessed directly, for example to perform + * the lock with the #MutexHelper for a RAII compliant lock operation. + * @return + */ + MutexIF* getMutexHandle() const; +private: + MutexIF* mutex = nullptr; +}; + + + +#endif /* FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ */ From c63665c257984be89bd2cd19f83bc81b1adbd588 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 19 Aug 2020 13:13:57 +0200 Subject: [PATCH 228/653] renamed framework.mk to fsfw.mk --- fsfw.mk | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 fsfw.mk diff --git a/fsfw.mk b/fsfw.mk new file mode 100644 index 00000000..c025ba23 --- /dev/null +++ b/fsfw.mk @@ -0,0 +1,59 @@ +# This submake file needs to be included by the primary Makefile. +# This file needs FRAMEWORK_PATH and OS_FSFW set correctly by another Makefile. +# Valid API settings: rtems, linux, freeRTOS, host + +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/action/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/container/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/contrib/sgp4/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/controller/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/coordinates/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datalinklayer/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapool/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/devicehandlers/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/eventmatching/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/fdir/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/globalfunctions/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/globalfunctions/matching/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/globalfunctions/math/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/health/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/internalError/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/ipc/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/memory/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/modes/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/monitoring/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/objectmanager/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/*.cpp) + +# select the OS +ifeq ($(OS_FSFW),rtems) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/rtems/*.cpp) +else ifeq ($(OS_FSFW),linux) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/linux/*.cpp) +else ifeq ($(OS_FSFW),freeRTOS) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/FreeRTOS/*.cpp) +else ifeq ($(OS_FSFW),host) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/host/*.cpp) +else +$(error invalid OS specified, valid OS are rtems, linux, freeRTOS, host) +endif + +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/parameters/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/power/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/returnvalues/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/rmap/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/serialize/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/serviceinterface/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/storagemanager/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/subsystem/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/subsystem/modes/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tasks/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tcdistribution/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/thermal/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/timemanager/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmstorage/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/packetmatcher/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/pus/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcservices/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/pus/*.cpp) From e59022dd432cdda2fc57ba8ee9ba350af33a1317 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 19 Aug 2020 13:15:14 +0200 Subject: [PATCH 229/653] old .mk file removed --- framework.mk | 58 ---------------------------------------------------- 1 file changed, 58 deletions(-) delete mode 100644 framework.mk diff --git a/framework.mk b/framework.mk deleted file mode 100644 index 136eff3a..00000000 --- a/framework.mk +++ /dev/null @@ -1,58 +0,0 @@ -# This file needs FRAMEWORK_PATH and OS_FSFW set correctly by another Makefile. -# Valid API settings: rtems, linux, freeRTOS, host - -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/action/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/container/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/contrib/sgp4/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/controller/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/coordinates/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datalinklayer/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapool/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/devicehandlers/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/eventmatching/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/fdir/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/globalfunctions/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/globalfunctions/matching/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/globalfunctions/math/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/health/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/internalError/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/ipc/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/memory/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/modes/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/monitoring/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/objectmanager/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/*.cpp) - -# select the OS -ifeq ($(OS_FSFW),rtems) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/rtems/*.cpp) -else ifeq ($(OS_FSFW),linux) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/linux/*.cpp) -else ifeq ($(OS_FSFW),freeRTOS) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/FreeRTOS/*.cpp) -else ifeq ($(OS_FSFW),host) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/host/*.cpp) -else -$(error invalid OS_FSFW specified, valid OS_FSFW are rtems, linux, freeRTOS, host) -endif - -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/parameters/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/power/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/returnvalues/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/rmap/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/serialize/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/serviceinterface/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/storagemanager/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/subsystem/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/subsystem/modes/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tasks/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tcdistribution/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/thermal/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/timemanager/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmstorage/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/packetmatcher/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/pus/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcservices/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/pus/*.cpp) From 31f398cec948bd232e40f29fc128e2596a20e6b7 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 19 Aug 2020 13:16:08 +0200 Subject: [PATCH 230/653] small fix --- fsfw.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsfw.mk b/fsfw.mk index c025ba23..c2c6e747 100644 --- a/fsfw.mk +++ b/fsfw.mk @@ -35,7 +35,7 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/FreeRTOS/*.cpp) else ifeq ($(OS_FSFW),host) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/host/*.cpp) else -$(error invalid OS specified, valid OS are rtems, linux, freeRTOS, host) +$(error invalid OS_FSFW specified, valid OS_FSFW are rtems, linux, freeRTOS, host) endif CXXSRC += $(wildcard $(FRAMEWORK_PATH)/parameters/*.cpp) From 1b4c4de3fa06f5a22e6ae828ad75f5ca015de7e0 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 24 Aug 2020 14:38:59 +0200 Subject: [PATCH 231/653] getter/setter functions for serial buffer adapter --- serialize/SerialBufferAdapter.cpp | 222 +++++++++++++++++------------- serialize/SerialBufferAdapter.h | 113 ++++++++++----- 2 files changed, 206 insertions(+), 129 deletions(-) diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index 5dd01f54..b1e0856a 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -1,94 +1,128 @@ -#include "SerialBufferAdapter.h" -#include - - - -template -SerialBufferAdapter::SerialBufferAdapter(const uint8_t* buffer, - T bufferLength, bool serializeLenght) : - serializeLength(serializeLenght), constBuffer(buffer), buffer(NULL), bufferLength( - bufferLength) { -} - -template -SerialBufferAdapter::SerialBufferAdapter(uint8_t* buffer, T bufferLength, - bool serializeLenght) : - serializeLength(serializeLenght), constBuffer(NULL), buffer(buffer), bufferLength( - bufferLength) { -} - -template -SerialBufferAdapter::~SerialBufferAdapter() { -} - -template -ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, size_t* size, - size_t maxSize, Endianness streamEndianness) const { - uint32_t serializedLength = bufferLength; - if (serializeLength) { - serializedLength += SerializeAdapter::getSerializedSize( - &bufferLength); - } - if (*size + serializedLength > maxSize) { - return BUFFER_TOO_SHORT; - } else { - if (serializeLength) { - SerializeAdapter::serialize(&bufferLength, buffer, size, - maxSize, streamEndianness); - } - if (this->constBuffer != NULL) { - memcpy(*buffer, this->constBuffer, bufferLength); - } else if (this->buffer != NULL) { - memcpy(*buffer, this->buffer, bufferLength); - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } - *size += bufferLength; - (*buffer) += bufferLength; - return HasReturnvaluesIF::RETURN_OK; - } -} - -template -size_t SerialBufferAdapter::getSerializedSize() const { - if (serializeLength) { - return bufferLength + SerializeAdapter::getSerializedSize(&bufferLength); - } else { - return bufferLength; - } -} -template -ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, - size_t* size, Endianness streamEndianness) { - //TODO Ignores Endian flag! - if (buffer != NULL) { - if(serializeLength){ - T serializedSize = SerializeAdapter::getSerializedSize( - &bufferLength); - if((*size - bufferLength - serializedSize) >= 0){ - *buffer += serializedSize; - *size -= serializedSize; - }else{ - return STREAM_TOO_SHORT; - } - } - //No Else If, go on with buffer - if (*size - bufferLength >= 0) { - *size -= bufferLength; - memcpy(this->buffer, *buffer, bufferLength); - (*buffer) += bufferLength; - return HasReturnvaluesIF::RETURN_OK; - } else { - return STREAM_TOO_SHORT; - } - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } -} - - -//forward Template declaration for linker -template class SerialBufferAdapter; -template class SerialBufferAdapter; -template class SerialBufferAdapter; - +#include "../serialize/SerialBufferAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include + +template +SerialBufferAdapter::SerialBufferAdapter(const uint8_t* buffer, + count_t bufferLength, bool serializeLength) : + serializeLength(serializeLength), + constBuffer(buffer), buffer(nullptr), + bufferLength(bufferLength) {} + +template +SerialBufferAdapter::SerialBufferAdapter(uint8_t* buffer, + count_t bufferLength, bool serializeLength) : + serializeLength(serializeLength), constBuffer(buffer), buffer(buffer), + bufferLength(bufferLength) {} + + +template +SerialBufferAdapter::~SerialBufferAdapter() { +} + +template +ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { + uint32_t serializedLength = bufferLength; + if (serializeLength) { + serializedLength += SerializeAdapter::getSerializedSize( + &bufferLength); + } + if (*size + serializedLength > maxSize) { + return BUFFER_TOO_SHORT; + } else { + if (serializeLength) { + SerializeAdapter::serialize(&bufferLength, buffer, size, + maxSize, streamEndianness); + } + if (constBuffer != nullptr) { + memcpy(*buffer, this->constBuffer, bufferLength); + } + else if (buffer != nullptr) { + // This will propably be never reached, constBuffer should always be + // set if non-const buffer is set. + memcpy(*buffer, this->buffer, bufferLength); + } + else { + return HasReturnvaluesIF::RETURN_FAILED; + } + *size += bufferLength; + (*buffer) += bufferLength; + return HasReturnvaluesIF::RETURN_OK; + } +} + +template +size_t SerialBufferAdapter::getSerializedSize() const { + if (serializeLength) { + return bufferLength + SerializeAdapter::getSerializedSize(&bufferLength); + } else { + return bufferLength; + } +} + +template +ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, + size_t* size, Endianness streamEndianness) { + //TODO Ignores Endian flag! + if (buffer != NULL) { + if(serializeLength){ + T serializedSize = SerializeAdapter::getSerializedSize( + &bufferLength); + if(bufferLength + serializedSize <= *size) { + *buffer += serializedSize; + *size -= serializedSize; + } + else { + return STREAM_TOO_SHORT; + } + } + //No Else If, go on with buffer + if (bufferLength <= *size) { + *size -= bufferLength; + memcpy(this->buffer, *buffer, bufferLength); + (*buffer) += bufferLength; + return HasReturnvaluesIF::RETURN_OK; + } + else { + return STREAM_TOO_SHORT; + } + } + else { + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +template +uint8_t * SerialBufferAdapter::getBuffer() { + if(buffer == nullptr) { + sif::error << "Wrong access function for stored type !" + " Use getConstBuffer()." << std::endl; + return nullptr; + } + return buffer; +} + +template +const uint8_t * SerialBufferAdapter::getConstBuffer() { + if(constBuffer == nullptr) { + sif::error << "SerialBufferAdapter: Buffers are unitialized!" << std::endl; + return nullptr; + } + return constBuffer; +} + +template +void SerialBufferAdapter::setBuffer(uint8_t* buffer, + count_t bufferLength) { + this->buffer = buffer; + this->constBuffer = buffer; + this->bufferLength = bufferLength; +} + + +//forward Template declaration for linker +template class SerialBufferAdapter; +template class SerialBufferAdapter; +template class SerialBufferAdapter; + diff --git a/serialize/SerialBufferAdapter.h b/serialize/SerialBufferAdapter.h index c27a5424..c3dfcd8f 100644 --- a/serialize/SerialBufferAdapter.h +++ b/serialize/SerialBufferAdapter.h @@ -1,35 +1,78 @@ -#ifndef SERIALBUFFERADAPTER_H_ -#define SERIALBUFFERADAPTER_H_ - -#include "SerializeIF.h" -#include "SerializeAdapter.h" - -/** - * \ingroup serialize - */ -template -class SerialBufferAdapter: public SerializeIF { -public: - SerialBufferAdapter(const uint8_t * buffer, T bufferLength, bool serializeLenght = false); - SerialBufferAdapter(uint8_t* buffer, T bufferLength, - bool serializeLenght = false); - - virtual ~SerialBufferAdapter(); - - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, - size_t maxSize, Endianness streamEndianness) const override; - - virtual size_t getSerializedSize() const override; - - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) override; -private: - bool serializeLength; - const uint8_t *constBuffer; - uint8_t *buffer; - T bufferLength; -}; - - - -#endif /* SERIALBUFFERADAPTER_H_ */ +#ifndef SERIALBUFFERADAPTER_H_ +#define SERIALBUFFERADAPTER_H_ + +#include "../serialize/SerializeIF.h" +#include "../serialize/SerializeAdapter.h" + +/** + * 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>. + * Right now, the SerialBufferAdapter must always + * be initialized with the buffer and size ! + * + * \ingroup serialize + */ +template +class SerialBufferAdapter: public SerializeIF { +public: + + /** + * Constructor for constant uint8_t buffer. Length field can be serialized optionally. + * Type of length can be supplied as template type. + * @param buffer + * @param bufferLength + * @param serializeLength + */ + SerialBufferAdapter(const uint8_t* buffer, count_t bufferLength, + bool serializeLength = false); + + /** + * Constructor for non-constant uint8_t buffer. + * Length field can be serialized optionally. + * Type of length can be supplied as template type. + * @param buffer + * @param bufferLength + * @param serializeLength Length field will be serialized with size count_t + */ + SerialBufferAdapter(uint8_t* buffer, count_t bufferLength, + bool serializeLength = false); + + virtual ~SerialBufferAdapter(); + + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const override; + + virtual size_t getSerializedSize() const override; + + /** + * @brief This function deserializes a buffer into the member buffer. + * @details + * If a length field is present, it is ignored, as the size should have + * been set in the constructor. If the size is not known beforehand, + * consider using SerialFixedArrayListAdapter instead. + * @param buffer [out] Resulting buffer + * @param size remaining size to deserialize, should be larger than buffer + * + size field size + * @param bigEndian + * @return + */ + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; + + uint8_t * getBuffer(); + const uint8_t * getConstBuffer(); + void setBuffer(uint8_t* buffer, count_t bufferLength); +private: + bool serializeLength = false; + const uint8_t *constBuffer = nullptr; + uint8_t *buffer = nullptr; + count_t bufferLength = 0; +}; + +#endif /* SERIALBUFFERADAPTER_H_ */ From 26b63d63b90340823777245e194cce253509dd29 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 24 Aug 2020 14:47:53 +0200 Subject: [PATCH 232/653] small fix --- serialize/SerialBufferAdapter.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index b1e0856a..5528331d 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -30,15 +30,16 @@ ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, size_t* size, } if (*size + serializedLength > maxSize) { return BUFFER_TOO_SHORT; - } else { + } + else { if (serializeLength) { SerializeAdapter::serialize(&bufferLength, buffer, size, maxSize, streamEndianness); } - if (constBuffer != nullptr) { + if (this->constBuffer != nullptr) { memcpy(*buffer, this->constBuffer, bufferLength); } - else if (buffer != nullptr) { + else if (this->buffer != nullptr) { // This will propably be never reached, constBuffer should always be // set if non-const buffer is set. memcpy(*buffer, this->buffer, bufferLength); From b7612bee37fdcfefa879ae80b71fdd8ebeaf198e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 24 Aug 2020 14:55:32 +0200 Subject: [PATCH 233/653] getFreeELement function added --- container/SimpleRingBuffer.cpp | 203 ++++++++++++++++++++++----------- container/SimpleRingBuffer.h | 149 ++++++++++++++++++++---- 2 files changed, 263 insertions(+), 89 deletions(-) diff --git a/container/SimpleRingBuffer.cpp b/container/SimpleRingBuffer.cpp index ee087643..7ed019b2 100644 --- a/container/SimpleRingBuffer.cpp +++ b/container/SimpleRingBuffer.cpp @@ -1,68 +1,135 @@ -#include "SimpleRingBuffer.h" -#include - -SimpleRingBuffer::SimpleRingBuffer(uint32_t size, bool overwriteOld) : - RingBufferBase<>(0, size, overwriteOld), buffer(NULL) { - buffer = new uint8_t[size]; -} - -SimpleRingBuffer::~SimpleRingBuffer() { - delete[] buffer; -} - -ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, - uint32_t amount) { - if (availableWriteSpace() >= amount || overwriteOld) { - uint32_t amountTillWrap = writeTillWrap(); - if (amountTillWrap >= amount) { - memcpy(&buffer[write], data, amount); - } else { - memcpy(&buffer[write], data, amountTillWrap); - memcpy(buffer, data + amountTillWrap, amount - amountTillWrap); - } - incrementWrite(amount); - return HasReturnvaluesIF::RETURN_OK; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, uint32_t amount, - bool readRemaining, uint32_t* trueAmount) { - uint32_t availableData = availableReadData(READ_PTR); - uint32_t amountTillWrap = readTillWrap(READ_PTR); - if (availableData < amount) { - if (readRemaining) { - amount = availableData; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } - } - if (trueAmount != NULL) { - *trueAmount = amount; - } - if (amountTillWrap >= amount) { - memcpy(data, &buffer[read[READ_PTR]], amount); - } else { - memcpy(data, &buffer[read[READ_PTR]], amountTillWrap); - memcpy(data + amountTillWrap, buffer, amount - amountTillWrap); - } - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t SimpleRingBuffer::deleteData(uint32_t amount, - bool deleteRemaining, uint32_t* trueAmount) { - uint32_t availableData = availableReadData(READ_PTR); - if (availableData < amount) { - if (deleteRemaining) { - amount = availableData; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } - } - if (trueAmount != NULL) { - *trueAmount = amount; - } - incrementRead(amount, READ_PTR); - return HasReturnvaluesIF::RETURN_OK; -} +#include "../container/SimpleRingBuffer.h" +#include + +SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld, + size_t maxExcessBytes) : + RingBufferBase<>(0, size, overwriteOld), + maxExcessBytes(maxExcessBytes) { + if(maxExcessBytes > size) { + this->maxExcessBytes = size; + } + else { + this->maxExcessBytes = maxExcessBytes; + } + buffer = new uint8_t[size + maxExcessBytes]; +} + +SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size, + bool overwriteOld, size_t maxExcessBytes): + RingBufferBase<>(0, size, overwriteOld), buffer(buffer) { + if(maxExcessBytes > size) { + this->maxExcessBytes = size; + } + else { + this->maxExcessBytes = maxExcessBytes; + } +} + + +SimpleRingBuffer::~SimpleRingBuffer() { + delete[] buffer; +} + + +ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer, + size_t amount) { + if (availableWriteSpace() >= amount or overwriteOld) { + size_t amountTillWrap = writeTillWrap(); + if (amountTillWrap < amount) { + if((amount - amountTillWrap + excessBytes) > maxExcessBytes) { + return HasReturnvaluesIF::RETURN_FAILED; + } + excessBytes = amount - amountTillWrap; + } + *writePointer = &buffer[write]; + return HasReturnvaluesIF::RETURN_OK; + } + else { + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +void SimpleRingBuffer::confirmBytesWritten(size_t amount) { + if(getExcessBytes() > 0) { + moveExcessBytesToStart(); + } + incrementWrite(amount); + +} + +ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, + size_t amount) { + if (availableWriteSpace() >= amount or overwriteOld) { + size_t amountTillWrap = writeTillWrap(); + if (amountTillWrap >= amount) { + // remaining size in buffer is sufficient to fit full 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, size_t amount, + bool incrementReadPtr, bool readRemaining, size_t* trueAmount) { + size_t availableData = getAvailableReadData(READ_PTR); + size_t amountTillWrap = readTillWrap(READ_PTR); + if (availableData < amount) { + if (readRemaining) { + // more data available than amount specified. + amount = availableData; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + if (trueAmount != nullptr) { + *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); + } + + if(incrementReadPtr) { + deleteData(amount, readRemaining); + } + return HasReturnvaluesIF::RETURN_OK; +} + +size_t SimpleRingBuffer::getExcessBytes() const { + return excessBytes; +} + +void SimpleRingBuffer::moveExcessBytesToStart() { + if(excessBytes > 0) { + std::memcpy(buffer, &buffer[size], excessBytes); + excessBytes = 0; + } +} + +ReturnValue_t SimpleRingBuffer::deleteData(size_t amount, + bool deleteRemaining, size_t* trueAmount) { + size_t availableData = getAvailableReadData(READ_PTR); + if (availableData < amount) { + if (deleteRemaining) { + amount = availableData; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + if (trueAmount != nullptr) { + *trueAmount = amount; + } + incrementRead(amount, READ_PTR); + return HasReturnvaluesIF::RETURN_OK; +} + + diff --git a/container/SimpleRingBuffer.h b/container/SimpleRingBuffer.h index 5d4fecab..b13e9f2a 100644 --- a/container/SimpleRingBuffer.h +++ b/container/SimpleRingBuffer.h @@ -1,21 +1,128 @@ -#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ -#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ - -#include "RingBufferBase.h" -#include - -class SimpleRingBuffer: public RingBufferBase<> { -public: - SimpleRingBuffer(uint32_t size, bool overwriteOld); - virtual ~SimpleRingBuffer(); - ReturnValue_t writeData(const uint8_t* data, uint32_t amount); - ReturnValue_t readData(uint8_t* data, uint32_t amount, bool readRemaining = false, uint32_t* trueAmount = NULL); - ReturnValue_t deleteData(uint32_t amount, bool deleteRemaining = false, uint32_t* trueAmount = NULL); -private: -// static const uint8_t TEMP_READ_PTR = 1; - static const uint8_t READ_PTR = 0; - uint8_t* buffer; -}; - -#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */ - +#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ +#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ + +#include "../container/RingBufferBase.h" +#include + +/** + * @brief Circular buffer implementation, useful for buffering + * into data streams. + * @details + * Note that the deleteData() has to be called to increment the read pointer. + * This class allocated dynamically, so + * @ingroup containers + */ +class SimpleRingBuffer: public RingBufferBase<> { +public: + /** + * This constructor allocates a new internal buffer with the supplied size. + * + * @param size + * @param overwriteOld If the ring buffer is overflowing at a write + * operation, the oldest data will be overwritten. + * @param maxExcessBytes These additional bytes will be allocated in addtion + * to the specified size to accomodate contiguous write operations + * with getFreeElement. + * + */ + SimpleRingBuffer(const size_t size, bool overwriteOld, + size_t maxExcessBytes = 0); + /** + * This constructor takes an external buffer with the specified size. + * @param buffer + * @param size + * @param overwriteOld + * If the ring buffer is overflowing at a write operartion, the oldest data + * will be overwritten. + * @param maxExcessBytes + * If the buffer can accomodate additional bytes for contigous write + * operations with getFreeElement, this is the maximum allowed additional + * size + */ + SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld, + size_t maxExcessBytes = 0); + + virtual ~SimpleRingBuffer(); + + /** + * Write to circular buffer and increment write pointer by amount. + * @param data + * @param amount + * @return -@c RETURN_OK if write operation was successfull + * -@c RETURN_FAILED if + */ + ReturnValue_t writeData(const uint8_t* data, size_t amount); + + /** + * Returns a pointer to a free element. If the remaining buffer is + * not large enough, the data will be written past the actual size + * and the amount of excess bytes will be cached. This function + * does not increment the write pointer! + * @param writePointer Pointer to a pointer which can be used to write + * contiguous blocks into the ring buffer + * @param amount + * @return + */ + ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount); + + /** + * This increments the write pointer and also copies the excess bytes + * to the beginning. It should be called if the write operation + * conducted after calling getFreeElement() was performed. + * @return + */ + void confirmBytesWritten(size_t amount); + + virtual size_t getExcessBytes() const; + /** + * Helper functions which moves any excess bytes to the start + * of the ring buffer. + * @return + */ + virtual void moveExcessBytesToStart(); + + /** + * Read from circular buffer at read pointer. + * @param data + * @param amount + * @param incrementReadPtr + * If this is set to true, the read pointer will be incremented. + * If readRemaining is set to true, the read pointer will be incremented + * accordingly. + * @param readRemaining + * If this is set to true, the data will be read even if the amount + * specified exceeds the read data available. + * @param trueAmount [out] + * If readRemaining was set to true, the true amount read will be assigned + * to the passed value. + * @return + * - @c RETURN_OK if data was read successfully + * - @c RETURN_FAILED if not enough data was available and readRemaining + * was set to false. + */ + ReturnValue_t readData(uint8_t* data, size_t amount, + bool incrementReadPtr = false, bool readRemaining = false, + size_t* trueAmount = nullptr); + + /** + * Delete data by incrementing read pointer. + * @param amount + * @param deleteRemaining + * If the amount specified is larger than the remaing size to read and this + * is set to true, the remaining amount will be deleted as well + * @param trueAmount [out] + * If deleteRemaining was set to true, the amount deleted will be assigned + * to the passed value. + * @return + */ + ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false, + size_t* trueAmount = nullptr); +private: + static const uint8_t READ_PTR = 0; + uint8_t* buffer = nullptr; + size_t maxExcessBytes; + size_t excessBytes = 0; +}; + +#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */ + From 84d99a6f04b5ccd6d544c6e633247e0d10bb1fd7 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 24 Aug 2020 14:56:50 +0200 Subject: [PATCH 234/653] added brackets for boolean expressions --- container/SimpleRingBuffer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/container/SimpleRingBuffer.cpp b/container/SimpleRingBuffer.cpp index 7ed019b2..2a19d619 100644 --- a/container/SimpleRingBuffer.cpp +++ b/container/SimpleRingBuffer.cpp @@ -33,7 +33,7 @@ SimpleRingBuffer::~SimpleRingBuffer() { ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer, size_t amount) { - if (availableWriteSpace() >= amount or overwriteOld) { + if ((availableWriteSpace() >= amount) or overwriteOld) { size_t amountTillWrap = writeTillWrap(); if (amountTillWrap < amount) { if((amount - amountTillWrap + excessBytes) > maxExcessBytes) { @@ -59,7 +59,7 @@ void SimpleRingBuffer::confirmBytesWritten(size_t amount) { ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, size_t amount) { - if (availableWriteSpace() >= amount or overwriteOld) { + if ((availableWriteSpace() >= amount) or overwriteOld) { size_t amountTillWrap = writeTillWrap(); if (amountTillWrap >= amount) { // remaining size in buffer is sufficient to fit full amount. From a4626aeac0682b07b5fee7ee2c4fa94d5322d1b8 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 12:04:59 +0200 Subject: [PATCH 235/653] made rtems adaption --- osal/rtems/Mutex.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osal/rtems/Mutex.cpp b/osal/rtems/Mutex.cpp index 68514534..f1c88826 100644 --- a/osal/rtems/Mutex.cpp +++ b/osal/rtems/Mutex.cpp @@ -25,12 +25,13 @@ Mutex::~Mutex() { } } -ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { - if(timeoutMs == MutexIF::BLOCKING) { +ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType = + TimeoutType::BLOCKING, uint32_t timeoutMs) { + if(timeoutMs == MutexIF::TimeoutType::BLOCKING) { rtems_status_code status = rtems_semaphore_obtain(mutexId, RTEMS_WAIT, timeoutMs); } - else if(timeoutMs == MutexIF::POLLING) { + else if(timeoutMs == MutexIF::TimeoutType::POLLING) { timeoutMs = RTEMS_NO_TIMEOUT; rtems_status_code status = rtems_semaphore_obtain(mutexId, RTEMS_NO_WAIT, timeoutMs); From 49a36d6fdc9d635946e6eb307ac771aa1ce01266 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 12:06:39 +0200 Subject: [PATCH 236/653] removed definitions --- osal/rtems/Mutex.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/osal/rtems/Mutex.cpp b/osal/rtems/Mutex.cpp index f1c88826..31acdb3c 100644 --- a/osal/rtems/Mutex.cpp +++ b/osal/rtems/Mutex.cpp @@ -1,8 +1,6 @@ #include "Mutex.h" #include "../../serviceinterface/ServiceInterfaceStream.h" -const uint32_t MutexIF::BLOCKING = RTEMS_WAIT; -const uint32_t MutexIF::POLLING = RTEMS_NO_WAIT; uint8_t Mutex::count = 0; Mutex::Mutex() : From ab4c65c87ae719143697de99d5a5b26c302d4e68 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 12:08:12 +0200 Subject: [PATCH 237/653] added header file changes --- osal/rtems/Mutex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osal/rtems/Mutex.h b/osal/rtems/Mutex.h index 624b556f..72368210 100644 --- a/osal/rtems/Mutex.h +++ b/osal/rtems/Mutex.h @@ -8,7 +8,7 @@ class Mutex : public MutexIF { public: Mutex(); ~Mutex(); - ReturnValue_t lockMutex(uint32_t timeoutMs = MutexIF::BLOCKING); + ReturnValue_t lockMutex(TimeoutType timeoutType, uint32_t timeoutMs = 0); ReturnValue_t unlockMutex(); private: rtems_id mutexId; From 74dea921e027f1ab6798a58b1b5e7e7cec6c7b01 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 12:10:28 +0200 Subject: [PATCH 238/653] made fixes --- osal/rtems/Mutex.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osal/rtems/Mutex.cpp b/osal/rtems/Mutex.cpp index 31acdb3c..9553ac79 100644 --- a/osal/rtems/Mutex.cpp +++ b/osal/rtems/Mutex.cpp @@ -27,16 +27,16 @@ ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType = TimeoutType::BLOCKING, uint32_t timeoutMs) { if(timeoutMs == MutexIF::TimeoutType::BLOCKING) { rtems_status_code status = rtems_semaphore_obtain(mutexId, - RTEMS_WAIT, timeoutMs); + RTEMS_WAIT, RTEMS_NO_TIMEOUT); } else if(timeoutMs == MutexIF::TimeoutType::POLLING) { timeoutMs = RTEMS_NO_TIMEOUT; rtems_status_code status = rtems_semaphore_obtain(mutexId, - RTEMS_NO_WAIT, timeoutMs); + RTEMS_NO_WAIT, 0); } else { rtems_status_code status = rtems_semaphore_obtain(mutexId, - RTEMS_NO_WAIT, timeoutMs); + RTEMS_WAIT, timeoutMs); } switch(status){ From 1235e38556b4015b3b1edfc2079d55b172db9904 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 12:20:56 +0200 Subject: [PATCH 239/653] rtems adaption --- osal/rtems/MultiObjectTask.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osal/rtems/MultiObjectTask.cpp b/osal/rtems/MultiObjectTask.cpp index 3c4886a5..2342c24c 100644 --- a/osal/rtems/MultiObjectTask.cpp +++ b/osal/rtems/MultiObjectTask.cpp @@ -78,6 +78,8 @@ ReturnValue_t MultiObjectTask::addComponent(object_id_t object) { return HasReturnvaluesIF::RETURN_FAILED; } objectList.push_back(newObject); + newObject->setTaskIF(this); + return HasReturnvaluesIF::RETURN_OK; } From d0419467a7d9bdf111bd60cd5c642803bb38e69a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 12:23:46 +0200 Subject: [PATCH 240/653] include guard fix --- osal/rtems/MultiObjectTask.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osal/rtems/MultiObjectTask.h b/osal/rtems/MultiObjectTask.h index 28d05fb1..d7c71422 100644 --- a/osal/rtems/MultiObjectTask.h +++ b/osal/rtems/MultiObjectTask.h @@ -4,8 +4,8 @@ * @date 30.01.2014 * @author baetz */ -#ifndef MULTIOBJECTTASK_H_ -#define MULTIOBJECTTASK_H_ +#ifndef FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_ +#define FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_ #include "../../objectmanager/ObjectManagerIF.h" #include "../../tasks/PeriodicTaskIF.h" @@ -63,11 +63,11 @@ public: * @param object Id of the object to add. * @return RETURN_OK on success, RETURN_FAILED if the object could not be added. */ - ReturnValue_t addComponent(object_id_t object); + ReturnValue_t addComponent(object_id_t object) override; - uint32_t getPeriodMs() const; + uint32_t getPeriodMs() const override; - ReturnValue_t sleepFor(uint32_t ms); + ReturnValue_t sleepFor(uint32_t ms) override; protected: typedef std::vector ObjectList; //!< Typedef for the List of objects. /** @@ -110,4 +110,4 @@ protected: void taskFunctionality(void); }; -#endif /* MULTIOBJECTTASK_H_ */ +#endif /* FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_ */ From 7e0cf49723fd4443751afd63f62d2c6f40b81b9a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 12:24:37 +0200 Subject: [PATCH 241/653] author tag --- osal/rtems/MultiObjectTask.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osal/rtems/MultiObjectTask.h b/osal/rtems/MultiObjectTask.h index d7c71422..736e79dd 100644 --- a/osal/rtems/MultiObjectTask.h +++ b/osal/rtems/MultiObjectTask.h @@ -1,9 +1,3 @@ -/** - * @file MultiObjectTask.h - * @brief This file defines the MultiObjectTask class. - * @date 30.01.2014 - * @author baetz - */ #ifndef FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_ #define FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_ @@ -21,7 +15,7 @@ class ExecutableObjectIF; * @details MultiObjectTask is an extension to ObjectTask in the way that it is able to execute * multiple objects that implement the ExecutableObjectIF interface. The objects must be * added prior to starting the task. - * + * @author baetz * @ingroup task_handling */ class MultiObjectTask: public TaskBase, public PeriodicTaskIF { From c0332a80a7218e45d7ba8dfc47028124530e6c98 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 12:40:06 +0200 Subject: [PATCH 242/653] task management update --- osal/FreeRTOS/TaskManagement.cpp | 12 ++++++------ osal/FreeRTOS/TaskManagement.h | 20 ++++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/osal/FreeRTOS/TaskManagement.cpp b/osal/FreeRTOS/TaskManagement.cpp index ff552adb..16682d36 100644 --- a/osal/FreeRTOS/TaskManagement.cpp +++ b/osal/FreeRTOS/TaskManagement.cpp @@ -1,11 +1,11 @@ -#include - +#include "../../osal/FreeRTOS/TaskManagement.h" + void TaskManagement::vRequestContextSwitchFromTask() { vTaskDelay(0); } - + void TaskManagement::requestContextSwitch( - CallContext callContext = CallContext::TASK) { + CallContext callContext = CallContext::TASK) { if(callContext == CallContext::ISR) { // This function depends on the partmacro.h definition for the specific device vRequestContextSwitchFromISR(); @@ -13,7 +13,7 @@ void TaskManagement::requestContextSwitch( vRequestContextSwitchFromTask(); } } - + TaskHandle_t TaskManagement::getCurrentTaskHandle() { return xTaskGetCurrentTaskHandle(); } @@ -21,4 +21,4 @@ TaskHandle_t TaskManagement::getCurrentTaskHandle() { size_t TaskManagement::getTaskStackHighWatermark( TaskHandle_t task) { return uxTaskGetStackHighWaterMark(task) * sizeof(StackType_t); -} +} diff --git a/osal/FreeRTOS/TaskManagement.h b/osal/FreeRTOS/TaskManagement.h index 62c68331..43003d76 100644 --- a/osal/FreeRTOS/TaskManagement.h +++ b/osal/FreeRTOS/TaskManagement.h @@ -1,14 +1,14 @@ #ifndef FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ #define FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ -#include +#include "../../returnvalues/HasReturnvaluesIF.h" extern "C" { #include #include } #include - + /** * Architecture dependant portmacro.h function call. * Should be implemented in bsp. @@ -17,9 +17,9 @@ extern void vRequestContextSwitchFromISR(); /*! * Used by functions to tell if they are being called from - * within an ISR or from a regular task. This is required because FreeRTOS + * within an ISR or from a regular task. This is required because FreeRTOS * has different functions for handling semaphores and messages from within - * an ISR and task. + * an ISR and task. */ enum class CallContext { TASK = 0x00,//!< task_context @@ -29,19 +29,19 @@ enum class CallContext { class TaskManagement { public: - /** + /** * @brief In this function, a function dependant on the portmacro.h header * function calls to request a context switch can be specified. * This can be used if sending to the queue from an ISR caused a task - * to unblock and a context switch is required. + * to unblock and a context switch is required. */ static void requestContextSwitch(CallContext callContext); /** * If task preemption in FreeRTOS is disabled, a context switch * can be requested manually by calling this function. - */ - static void vRequestContextSwitchFromTask(void); + */ + static void vRequestContextSwitchFromTask(void); /** * @return The current task handle @@ -56,9 +56,9 @@ public: * E.g. on a 32 bit machine, a value of 200 means 800 bytes. * @return Smallest value of stack remaining since the task was started in * words. - */ + */ static size_t getTaskStackHighWatermark( - TaskHandle_t task = nullptr); + TaskHandle_t task = nullptr); }; #endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */ From 825bf62d791a077c0c9b1af642e98f074459cb30 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 13:14:13 +0200 Subject: [PATCH 243/653] fixed deSerialize --- serialize/SerialBufferAdapter.cpp | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index 5528331d..dc721f0d 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -20,9 +20,9 @@ template SerialBufferAdapter::~SerialBufferAdapter() { } -template -ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, size_t* size, - size_t maxSize, Endianness streamEndianness) const { +template +ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, + size_t* size, size_t maxSize, Endianness streamEndianness) const { uint32_t serializedLength = bufferLength; if (serializeLength) { serializedLength += SerializeAdapter::getSerializedSize( @@ -53,8 +53,8 @@ ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, size_t* size, } } -template -size_t SerialBufferAdapter::getSerializedSize() const { +template +size_t SerialBufferAdapter::getSerializedSize() const { if (serializeLength) { return bufferLength + SerializeAdapter::getSerializedSize(&bufferLength); } else { @@ -62,20 +62,16 @@ size_t SerialBufferAdapter::getSerializedSize() const { } } -template -ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, +template +ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) { //TODO Ignores Endian flag! - if (buffer != NULL) { + if (buffer != nullptr) { if(serializeLength){ - T serializedSize = SerializeAdapter::getSerializedSize( - &bufferLength); - if(bufferLength + serializedSize <= *size) { - *buffer += serializedSize; - *size -= serializedSize; - } - else { - return STREAM_TOO_SHORT; + ReturnValue_t result = SerializeAdapter::deSerialize(&bufferLength, + buffer, size, streamEndianness); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; } } //No Else If, go on with buffer From 857d61ea130ebe556cb65635e219b1eb2655b90f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 13:16:17 +0200 Subject: [PATCH 244/653] member pointer now checked --- serialize/SerialBufferAdapter.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index dc721f0d..53d0b8d4 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -66,7 +66,7 @@ template ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) { //TODO Ignores Endian flag! - if (buffer != nullptr) { + if (this->buffer != nullptr) { if(serializeLength){ ReturnValue_t result = SerializeAdapter::deSerialize(&bufferLength, buffer, size, streamEndianness); @@ -77,7 +77,7 @@ ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, //No Else If, go on with buffer if (bufferLength <= *size) { *size -= bufferLength; - memcpy(this->buffer, *buffer, bufferLength); + std::memcpy(this->buffer, *buffer, bufferLength); (*buffer) += bufferLength; return HasReturnvaluesIF::RETURN_OK; } @@ -103,7 +103,8 @@ uint8_t * SerialBufferAdapter::getBuffer() { template const uint8_t * SerialBufferAdapter::getConstBuffer() { if(constBuffer == nullptr) { - sif::error << "SerialBufferAdapter: Buffers are unitialized!" << std::endl; + sif::error << "SerialBufferAdapter::getConstBuffer:" + " Buffers are unitialized!" << std::endl; return nullptr; } return constBuffer; From c8595c3442b4e48c5d50330a64e2dae7fed1fc87 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 13:29:36 +0200 Subject: [PATCH 245/653] deSerialize fixed/improved --- serialize/SerialBufferAdapter.cpp | 39 +++++++++++++++++-------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index 53d0b8d4..8a5bef4a 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -65,28 +65,31 @@ size_t SerialBufferAdapter::getSerializedSize() const { template ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) { - //TODO Ignores Endian flag! - if (this->buffer != nullptr) { - if(serializeLength){ - ReturnValue_t result = SerializeAdapter::deSerialize(&bufferLength, - buffer, size, streamEndianness); - if(result != HasReturnvaluesIF::RETURN_OK) { - return result; - } + if (this->buffer == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + + if(serializeLength){ + count_t lengthField = 0; + ReturnValue_t result = SerializeAdapter::deSerialize(&lengthField, + buffer, size, streamEndianness); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; } - //No Else If, go on with buffer - if (bufferLength <= *size) { - *size -= bufferLength; - std::memcpy(this->buffer, *buffer, bufferLength); - (*buffer) += bufferLength; - return HasReturnvaluesIF::RETURN_OK; - } - else { - return STREAM_TOO_SHORT; + if(lengthField > bufferLength) { + return TOO_MANY_ELEMENTS; } + bufferLength = lengthField; + } + + if (bufferLength <= *size) { + *size -= bufferLength; + std::memcpy(this->buffer, *buffer, bufferLength); + (*buffer) += bufferLength; + return HasReturnvaluesIF::RETURN_OK; } else { - return HasReturnvaluesIF::RETURN_FAILED; + return STREAM_TOO_SHORT; } } From 7d2c48fb3375ca1ab8f1b90a3baa0256ca2f9f58 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 13:32:17 +0200 Subject: [PATCH 246/653] serializhe improved --- serialize/SerialBufferAdapter.cpp | 41 +++++++++++++++++-------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index 8a5bef4a..85a55343 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -28,29 +28,34 @@ ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, serializedLength += SerializeAdapter::getSerializedSize( &bufferLength); } + if (*size + serializedLength > maxSize) { return BUFFER_TOO_SHORT; } - else { - if (serializeLength) { - SerializeAdapter::serialize(&bufferLength, buffer, size, - maxSize, streamEndianness); + + if (serializeLength) { + ReturnValue_t result = SerializeAdapter::serialize(&bufferLength, + buffer, size, maxSize, streamEndianness); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; } - if (this->constBuffer != nullptr) { - memcpy(*buffer, this->constBuffer, bufferLength); - } - else if (this->buffer != nullptr) { - // This will propably be never reached, constBuffer should always be - // set if non-const buffer is set. - memcpy(*buffer, this->buffer, bufferLength); - } - else { - return HasReturnvaluesIF::RETURN_FAILED; - } - *size += bufferLength; - (*buffer) += bufferLength; - return HasReturnvaluesIF::RETURN_OK; } + + if (this->constBuffer != nullptr) { + std::memcpy(*buffer, this->constBuffer, bufferLength); + } + else if (this->buffer != nullptr) { + // This will propably be never reached, constBuffer should always be + // set if non-const buffer is set. + std::memcpy(*buffer, this->buffer, bufferLength); + } + else { + return HasReturnvaluesIF::RETURN_FAILED; + } + *size += bufferLength; + (*buffer) += bufferLength; + return HasReturnvaluesIF::RETURN_OK; + } template From ba4eac65ccc50898ee936b257f245a75bdd7f3e7 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 13:33:31 +0200 Subject: [PATCH 247/653] count t replacements --- serialize/SerialBufferAdapter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index 85a55343..478957e9 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -23,7 +23,7 @@ SerialBufferAdapter::~SerialBufferAdapter() { template ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, size_t* size, size_t maxSize, Endianness streamEndianness) const { - uint32_t serializedLength = bufferLength; + count_t serializedLength = bufferLength; if (serializeLength) { serializedLength += SerializeAdapter::getSerializedSize( &bufferLength); From fb0a3d22dbbd5d33e2ad9fde4586d7a9ef8731b7 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 13:34:52 +0200 Subject: [PATCH 248/653] linker forward decl added --- serialize/SerialBufferAdapter.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index 478957e9..c300eb36 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -131,4 +131,6 @@ void SerialBufferAdapter::setBuffer(uint8_t* buffer, template class SerialBufferAdapter; template class SerialBufferAdapter; template class SerialBufferAdapter; +template class SerialBufferAdapter; +template class SerialBufferAdapter; From de98dd0871a8c091b8413bd9172416a3afe54f71 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 13:37:42 +0200 Subject: [PATCH 249/653] optimization --- serialize/SerialBufferAdapter.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index c300eb36..ab52262f 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -23,16 +23,6 @@ SerialBufferAdapter::~SerialBufferAdapter() { template ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, size_t* size, size_t maxSize, Endianness streamEndianness) const { - count_t serializedLength = bufferLength; - if (serializeLength) { - serializedLength += SerializeAdapter::getSerializedSize( - &bufferLength); - } - - if (*size + serializedLength > maxSize) { - return BUFFER_TOO_SHORT; - } - if (serializeLength) { ReturnValue_t result = SerializeAdapter::serialize(&bufferLength, buffer, size, maxSize, streamEndianness); @@ -41,6 +31,10 @@ ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, } } + if (*size + bufferLength > maxSize) { + return BUFFER_TOO_SHORT; + } + if (this->constBuffer != nullptr) { std::memcpy(*buffer, this->constBuffer, bufferLength); } From 9c2925333788750422f65364445d8f428c00aeb1 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 13:42:36 +0200 Subject: [PATCH 250/653] removed forward decl --- serialize/SerialBufferAdapter.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index ab52262f..812cd34b 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -126,5 +126,4 @@ template class SerialBufferAdapter; template class SerialBufferAdapter; template class SerialBufferAdapter; template class SerialBufferAdapter; -template class SerialBufferAdapter; From 3001911d69522c3fb44a2483c25d129e6cfef98e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 14:00:27 +0200 Subject: [PATCH 251/653] taken over interface changes --- storagemanager/ConstStorageAccessor.cpp | 174 ++++++------ storagemanager/ConstStorageAccessor.h | 232 ++++++++-------- storagemanager/StorageAccessor.cpp | 134 +++++----- storagemanager/StorageAccessor.h | 89 +++---- storagemanager/StorageManagerIF.h | 335 ++++++++++++------------ 5 files changed, 482 insertions(+), 482 deletions(-) diff --git a/storagemanager/ConstStorageAccessor.cpp b/storagemanager/ConstStorageAccessor.cpp index 0bfde58c..ea9f2e44 100644 --- a/storagemanager/ConstStorageAccessor.cpp +++ b/storagemanager/ConstStorageAccessor.cpp @@ -1,87 +1,87 @@ -#include -#include -#include -#include - -ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): - storeId(storeId) {} - -ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId, - StorageManagerIF* store): - storeId(storeId), store(store) { - internalState = AccessState::ASSIGNED; -} - -ConstStorageAccessor::~ConstStorageAccessor() { - if(deleteData and store != nullptr) { - sif::debug << "deleting store data" << std::endl; - store->deleteData(storeId); - } -} - -ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other): - constDataPointer(other.constDataPointer), storeId(other.storeId), - size_(other.size_), store(other.store), deleteData(other.deleteData), - internalState(other.internalState) { - // This prevent premature deletion - other.store = nullptr; -} - -ConstStorageAccessor& ConstStorageAccessor::operator=( - ConstStorageAccessor&& other) { - constDataPointer = other.constDataPointer; - storeId = other.storeId; - store = other.store; - size_ = other.size_; - deleteData = other.deleteData; - this->store = other.store; - // This prevents premature deletion - other.store = nullptr; - return *this; -} - -const uint8_t* ConstStorageAccessor::data() const { - return constDataPointer; -} - -size_t ConstStorageAccessor::size() const { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - } - return size_; -} - -ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t *pointer, - size_t maxSize) { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - if(size_ > maxSize) { - sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - std::copy(constDataPointer, constDataPointer + size_, pointer); - return HasReturnvaluesIF::RETURN_OK; -} - -void ConstStorageAccessor::release() { - deleteData = false; -} - -store_address_t ConstStorageAccessor::getId() const { - return storeId; -} - -void ConstStorageAccessor::print() const { - if(internalState == AccessState::UNINIT or constDataPointer == nullptr) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return; - } - arrayprinter::print(constDataPointer, size_); -} - -void ConstStorageAccessor::assignStore(StorageManagerIF* store) { - internalState = AccessState::ASSIGNED; - this->store = store; -} +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../storagemanager/ConstStorageAccessor.h" +#include "../storagemanager/StorageManagerIF.h" +#include "../globalfunctions/arrayprinter.h" + +ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): + storeId(storeId) {} + +ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId, + StorageManagerIF* store): + storeId(storeId), store(store) { + internalState = AccessState::ASSIGNED; +} + +ConstStorageAccessor::~ConstStorageAccessor() { + if(deleteData and store != nullptr) { + sif::debug << "deleting store data" << std::endl; + store->deleteData(storeId); + } +} + +ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other): + constDataPointer(other.constDataPointer), storeId(other.storeId), + size_(other.size_), store(other.store), deleteData(other.deleteData), + internalState(other.internalState) { + // This prevent premature deletion + other.store = nullptr; +} + +ConstStorageAccessor& ConstStorageAccessor::operator=( + ConstStorageAccessor&& other) { + constDataPointer = other.constDataPointer; + storeId = other.storeId; + store = other.store; + size_ = other.size_; + deleteData = other.deleteData; + this->store = other.store; + // This prevents premature deletion + other.store = nullptr; + return *this; +} + +const uint8_t* ConstStorageAccessor::data() const { + return constDataPointer; +} + +size_t ConstStorageAccessor::size() const { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + } + return size_; +} + +ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t *pointer, + size_t maxSize) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(size_ > maxSize) { + sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(constDataPointer, constDataPointer + size_, pointer); + return HasReturnvaluesIF::RETURN_OK; +} + +void ConstStorageAccessor::release() { + deleteData = false; +} + +store_address_t ConstStorageAccessor::getId() const { + return storeId; +} + +void ConstStorageAccessor::print() const { + if(internalState == AccessState::UNINIT or constDataPointer == nullptr) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return; + } + arrayprinter::print(constDataPointer, size_); +} + +void ConstStorageAccessor::assignStore(StorageManagerIF* store) { + internalState = AccessState::ASSIGNED; + this->store = store; +} diff --git a/storagemanager/ConstStorageAccessor.h b/storagemanager/ConstStorageAccessor.h index bb003f55..ec2da8ce 100644 --- a/storagemanager/ConstStorageAccessor.h +++ b/storagemanager/ConstStorageAccessor.h @@ -1,116 +1,116 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ -#define FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ - -#include "storeAddress.h" -#include "../returnvalues/HasReturnvaluesIF.h" -#include - -class StorageManagerIF; - -/** - * @brief Helper classes to facilitate safe access to storages which is also - * conforming to RAII principles - * @details - * Accessor class which can be returned by pool manager or passed and set by - * pool managers to have safe access to the pool resources. - * - * These helper can be used together with the StorageManager classes to manage - * access to a storage. It can take care of thread-safety while also providing - * mechanisms to automatically clear storage data. - */ -class ConstStorageAccessor { - //! StorageManager classes have exclusive access to private variables. - template - friend class PoolManager; - template - friend class LocalPool; -public: - /** - * @brief Simple constructor which takes the store ID of the storage - * entry to access. - * @param storeId - */ - ConstStorageAccessor(store_address_t storeId); - ConstStorageAccessor(store_address_t storeId, StorageManagerIF* store); - - /** - * @brief The destructor in default configuration takes care of - * deleting the accessed pool entry and unlocking the mutex - */ - virtual ~ConstStorageAccessor(); - - /** - * @brief Returns a pointer to the read-only data - * @return - */ - const uint8_t* data() const; - - /** - * @brief Copies the read-only data to the supplied pointer - * @param pointer - */ - virtual ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize); - - /** - * @brief Calling this will prevent the Accessor from deleting the data - * when the destructor is called. - */ - void release(); - - /** - * Get the size of the data - * @return - */ - size_t size() const; - - /** - * Get the storage ID. - * @return - */ - store_address_t getId() const; - - void print() const; - - /** - * @brief Move ctor and move assignment allow returning accessors as - * a returnvalue. They prevent resource being free prematurely. - * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ - * move-constructors-and-move-assignment-operators-cpp.md - * @param - * @return - */ - ConstStorageAccessor& operator= (ConstStorageAccessor&&); - ConstStorageAccessor (ConstStorageAccessor&&); - - //! The copy ctor and copy assignemnt should be deleted implicitely - //! according to https://foonathan.net/2019/02/special-member-functions/ - //! but I still deleted them to make it more explicit. (remember rule of 5). - ConstStorageAccessor& operator= (ConstStorageAccessor&) = delete; - ConstStorageAccessor (ConstStorageAccessor&) = delete; -protected: - const uint8_t* constDataPointer = nullptr; - store_address_t storeId; - size_t size_ = 0; - //! Managing pool, has to assign itself. - StorageManagerIF* store = nullptr; - bool deleteData = true; - - enum class AccessState { - UNINIT, - ASSIGNED - }; - //! Internal state for safety reasons. - AccessState internalState = AccessState::UNINIT; - /** - * Used by the pool manager instances to assign themselves to the - * accessor. This is necessary to delete the data when the acessor - * exits the scope ! The internal state will be considered read - * when this function is called, so take care all data is set properly as - * well. - * @param - */ - void assignStore(StorageManagerIF*); -}; - - -#endif /* FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ */ +#ifndef FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ +#define FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ + +#include "../storagemanager/storeAddress.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include + +class StorageManagerIF; + +/** + * @brief Helper classes to facilitate safe access to storages which is also + * conforming to RAII principles + * @details + * Accessor class which can be returned by pool manager or passed and set by + * pool managers to have safe access to the pool resources. + * + * These helper can be used together with the StorageManager classes to manage + * access to a storage. It can take care of thread-safety while also providing + * mechanisms to automatically clear storage data. + */ +class ConstStorageAccessor { + //! StorageManager classes have exclusive access to private variables. + template + friend class PoolManager; + template + friend class LocalPool; +public: + /** + * @brief Simple constructor which takes the store ID of the storage + * entry to access. + * @param storeId + */ + ConstStorageAccessor(store_address_t storeId); + ConstStorageAccessor(store_address_t storeId, StorageManagerIF* store); + + /** + * @brief The destructor in default configuration takes care of + * deleting the accessed pool entry and unlocking the mutex + */ + virtual ~ConstStorageAccessor(); + + /** + * @brief Returns a pointer to the read-only data + * @return + */ + const uint8_t* data() const; + + /** + * @brief Copies the read-only data to the supplied pointer + * @param pointer + */ + virtual ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize); + + /** + * @brief Calling this will prevent the Accessor from deleting the data + * when the destructor is called. + */ + void release(); + + /** + * Get the size of the data + * @return + */ + size_t size() const; + + /** + * Get the storage ID. + * @return + */ + store_address_t getId() const; + + void print() const; + + /** + * @brief Move ctor and move assignment allow returning accessors as + * a returnvalue. They prevent resource being free prematurely. + * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ + * move-constructors-and-move-assignment-operators-cpp.md + * @param + * @return + */ + ConstStorageAccessor& operator= (ConstStorageAccessor&&); + ConstStorageAccessor(ConstStorageAccessor&&); + + //! The copy ctor and copy assignemnt should be deleted implicitely + //! according to https://foonathan.net/2019/02/special-member-functions/ + //! but I still deleted them to make it more explicit. (remember rule of 5). + ConstStorageAccessor& operator=(const ConstStorageAccessor&) = delete; + ConstStorageAccessor(const ConstStorageAccessor&) = delete; +protected: + const uint8_t* constDataPointer = nullptr; + store_address_t storeId; + size_t size_ = 0; + //! Managing pool, has to assign itself. + StorageManagerIF* store = nullptr; + bool deleteData = true; + + enum class AccessState { + UNINIT, + ASSIGNED + }; + //! Internal state for safety reasons. + AccessState internalState = AccessState::UNINIT; + /** + * Used by the pool manager instances to assign themselves to the + * accessor. This is necessary to delete the data when the acessor + * exits the scope ! The internal state will be considered read + * when this function is called, so take care all data is set properly as + * well. + * @param + */ + void assignStore(StorageManagerIF*); +}; + + +#endif /* FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ */ diff --git a/storagemanager/StorageAccessor.cpp b/storagemanager/StorageAccessor.cpp index 9c2f936a..d4d2a54d 100644 --- a/storagemanager/StorageAccessor.cpp +++ b/storagemanager/StorageAccessor.cpp @@ -1,67 +1,67 @@ -#include "StorageAccessor.h" -#include "StorageManagerIF.h" -#include "../serviceinterface/ServiceInterfaceStream.h" - -StorageAccessor::StorageAccessor(store_address_t storeId): - ConstStorageAccessor(storeId) { -} - -StorageAccessor::StorageAccessor(store_address_t storeId, - StorageManagerIF* store): - ConstStorageAccessor(storeId, store) { -} - -StorageAccessor& StorageAccessor::operator =( - StorageAccessor&& other) { - // Call the parent move assignment and also assign own member. - dataPointer = other.dataPointer; - StorageAccessor::operator=(std::move(other)); - return * this; -} - -// Call the parent move ctor and also transfer own member. -StorageAccessor::StorageAccessor(StorageAccessor&& other): - ConstStorageAccessor(std::move(other)), dataPointer(other.dataPointer) { -} - -ReturnValue_t StorageAccessor::getDataCopy(uint8_t *pointer, size_t maxSize) { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - if(size_ > maxSize) { - sif::error << "StorageAccessor: Supplied buffer not large " - "enough" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - std::copy(dataPointer, dataPointer + size_, pointer); - return HasReturnvaluesIF::RETURN_OK; -} - -uint8_t* StorageAccessor::data() { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - } - return dataPointer; -} - -ReturnValue_t StorageAccessor::write(uint8_t *data, size_t size, - uint16_t offset) { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - if(offset + size > size_) { - sif::error << "StorageAccessor: Data too large for pool " - "entry!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - std::copy(data, data + size, dataPointer + offset); - return HasReturnvaluesIF::RETURN_OK; -} - -void StorageAccessor::assignConstPointer() { - constDataPointer = dataPointer; -} - - +#include "../storagemanager/StorageAccessor.h" +#include "../storagemanager/StorageManagerIF.h" +#include "../serviceinterface/ServiceInterfaceStream.h" + +StorageAccessor::StorageAccessor(store_address_t storeId): + ConstStorageAccessor(storeId) { +} + +StorageAccessor::StorageAccessor(store_address_t storeId, + StorageManagerIF* store): + ConstStorageAccessor(storeId, store) { +} + +StorageAccessor& StorageAccessor::operator =( + StorageAccessor&& other) { + // Call the parent move assignment and also assign own member. + dataPointer = other.dataPointer; + StorageAccessor::operator=(std::move(other)); + return * this; +} + +// Call the parent move ctor and also transfer own member. +StorageAccessor::StorageAccessor(StorageAccessor&& other): + ConstStorageAccessor(std::move(other)), dataPointer(other.dataPointer) { +} + +ReturnValue_t StorageAccessor::getDataCopy(uint8_t *pointer, size_t maxSize) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(size_ > maxSize) { + sif::error << "StorageAccessor: Supplied buffer not large " + "enough" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(dataPointer, dataPointer + size_, pointer); + return HasReturnvaluesIF::RETURN_OK; +} + +uint8_t* StorageAccessor::data() { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + } + return dataPointer; +} + +ReturnValue_t StorageAccessor::write(uint8_t *data, size_t size, + uint16_t offset) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(offset + size > size_) { + sif::error << "StorageAccessor: Data too large for pool " + "entry!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(data, data + size, dataPointer + offset); + return HasReturnvaluesIF::RETURN_OK; +} + +void StorageAccessor::assignConstPointer() { + constDataPointer = dataPointer; +} + + diff --git a/storagemanager/StorageAccessor.h b/storagemanager/StorageAccessor.h index 5cdd82a7..1ca5f7dd 100644 --- a/storagemanager/StorageAccessor.h +++ b/storagemanager/StorageAccessor.h @@ -1,44 +1,45 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ -#define FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ - -#include "ConstStorageAccessor.h" - -class StorageManagerIF; - -/** - * @brief Child class for modifyable data. Also has a normal pointer member. - */ -class StorageAccessor: public ConstStorageAccessor { - //! StorageManager classes have exclusive access to private variables. - template - friend class PoolManager; - template - friend class LocalPool; -public: - StorageAccessor(store_address_t storeId); - StorageAccessor(store_address_t storeId, StorageManagerIF* store); - /** - * @brief Move ctor and move assignment allow returning accessors as - * a returnvalue. They prevent resource being free prematurely. - * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ - * move-constructors-and-move-assignment-operators-cpp.md - * @param - * @return - */ - StorageAccessor& operator= (StorageAccessor&&); - StorageAccessor (StorageAccessor&&); - - ReturnValue_t write(uint8_t *data, size_t size, - uint16_t offset = 0); - uint8_t* data(); - ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize) override; - -private: - //! Non-const pointer for modifyable data. - uint8_t* dataPointer = nullptr; - //! For modifyable data, the const pointer is assigned to the normal - //! pointer by the pool manager so both access functions can be used safely - void assignConstPointer(); -}; - -#endif /* TEST_PROTOTYPES_STORAGEACCESSOR_H_ */ +#ifndef FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ +#define FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ + +#include "../storagemanager/ConstStorageAccessor.h" + +class StorageManagerIF; + +/** + * @brief Child class for modifyable data. Also has a normal pointer member. + */ +class StorageAccessor: public ConstStorageAccessor { + //! StorageManager classes have exclusive access to private variables. + template + friend class PoolManager; + template + friend class LocalPool; +public: + StorageAccessor(store_address_t storeId); + StorageAccessor(store_address_t storeId, StorageManagerIF* store); + + /** + * @brief Move ctor and move assignment allow returning accessors as + * a returnvalue. They prevent resource being freed prematurely. + * See: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ + * move-constructors-and-move-assignment-operators-cpp.md + * @param + * @return + */ + StorageAccessor& operator=(StorageAccessor&&); + StorageAccessor(StorageAccessor&&); + + ReturnValue_t write(uint8_t *data, size_t size, + uint16_t offset = 0); + uint8_t* data(); + ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize) override; + +private: + //! Non-const pointer for modifyable data. + uint8_t* dataPointer = nullptr; + //! For modifyable data, the const pointer is assigned to the normal + //! pointer by the pool manager so both access functions can be used safely + void assignConstPointer(); +}; + +#endif /* TEST_PROTOTYPES_STORAGEACCESSOR_H_ */ diff --git a/storagemanager/StorageManagerIF.h b/storagemanager/StorageManagerIF.h index a36a714a..85341f2e 100644 --- a/storagemanager/StorageManagerIF.h +++ b/storagemanager/StorageManagerIF.h @@ -1,168 +1,167 @@ -#ifndef STORAGEMANAGERIF_H_H -#define STORAGEMANAGERIF_H_H - - -#include "../events/Event.h" -#include "../returnvalues/HasReturnvaluesIF.h" -#include "../storagemanager/StorageAccessor.h" -#include "../storagemanager/storeAddress.h" -#include -#include - -using AccessorPair = std::pair; -using ConstAccessorPair = std::pair; - -/** - * @brief This class provides an interface for intermediate data storage. - * @details The Storage manager classes shall be used to store larger chunks of - * data in RAM for exchange between tasks. This interface expects the - * data to be stored in one consecutive block of memory, so tasks can - * write directly to the destination pointer. - * For interprocess communication, the stores must be locked during - * insertion and deletion. If the receiving storage identifier is - * passed token-like between tasks, a lock during read and write - * operations is not necessary. - * @author Bastian Baetz - * @date 18.09.2012 - */ -class StorageManagerIF : public HasReturnvaluesIF { -public: - static const uint8_t INTERFACE_ID = CLASS_ID::STORAGE_MANAGER_IF; //!< The unique ID for return codes for this interface. - static const ReturnValue_t DATA_TOO_LARGE = MAKE_RETURN_CODE(1); //!< This return code indicates that the data to be stored is too large for the store. - static const ReturnValue_t DATA_STORAGE_FULL = MAKE_RETURN_CODE(2); //!< This return code indicates that a data storage is full. - static const ReturnValue_t ILLEGAL_STORAGE_ID = MAKE_RETURN_CODE(3); //!< This return code indicates that data was requested with an illegal storage ID. - static const ReturnValue_t DATA_DOES_NOT_EXIST = MAKE_RETURN_CODE(4); //!< This return code indicates that the requested ID was valid, but no data is stored there. - static const ReturnValue_t ILLEGAL_ADDRESS = MAKE_RETURN_CODE(5); - static const ReturnValue_t POOL_TOO_LARGE = MAKE_RETURN_CODE(6); //!< Pool size too large on initialization. - - static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::OBSW; - static const Event GET_DATA_FAILED = MAKE_EVENT(0, SEVERITY::LOW); - static const Event STORE_DATA_FAILED = MAKE_EVENT(1, SEVERITY::LOW); - - static const uint32_t INVALID_ADDRESS = 0xFFFFFFFF; //!< Indicates an invalid (i.e unused) storage address. - /** - * @brief This is the empty virtual destructor as required for C++ interfaces. - */ - virtual ~StorageManagerIF() { - } - ; - /** - * @brief With addData, a free storage position is allocated and data - * stored there. - * @details During the allocation, the StorageManager is blocked. - * @param storageId A pointer to the storageId to retrieve. - * @param data The data to be stored in the StorageManager. - * @param size The amount of data to be stored. - * @return Returns @li RETURN_OK if data was added. - * @li RETURN_FAILED if data could not be added. - * storageId is unchanged then. - */ - virtual ReturnValue_t addData(store_address_t* storageId, - const uint8_t * data, size_t size, bool ignoreFault = false) = 0; - /** - * @brief With deleteData, the storageManager frees the memory region - * identified by packet_id. - * @param packet_id The identifier of the memory region to be freed. - * @return @li RETURN_OK on success. - * @li RETURN_FAILED if deletion did not work - * (e.g. an illegal packet_id was passed). - */ - virtual ReturnValue_t deleteData(store_address_t packet_id) = 0; - /** - * @brief Another deleteData which uses the pointer and size of the - * stored data to delete the content. - * @param buffer Pointer to the data. - * @param size Size of data to be stored. - * @param storeId Store id of the deleted element (optional) - * @return @li RETURN_OK on success. - * @li failure code if deletion did not work - */ - virtual ReturnValue_t deleteData(uint8_t* buffer, size_t size, - store_address_t* storeId = nullptr) = 0; - - - /** - * @brief Access the data by supplying a store ID. - * @details - * A pair consisting of the retrieval result and an instance of a - * ConstStorageAccessor class is returned - * @param storeId - * @return Pair of return value and a ConstStorageAccessor instance - */ - virtual ConstAccessorPair getData(store_address_t storeId) = 0; - - /** - * @brief Access the data by supplying a store ID and a helper - * instance - * @param storeId - * @param constAccessor Wrapper function to access store data. - * @return - */ - virtual ReturnValue_t getData(store_address_t storeId, - ConstStorageAccessor& constAccessor) = 0; - - - /** - * @brief getData returns an address to data and the size of the data - * for a given packet_id. - * @param packet_id The id of the data to be returned - * @param packet_ptr The passed pointer address is set to the the memory - * position - * @param size The exact size of the stored data is returned here. - * @return @li RETURN_OK on success. - * @li RETURN_FAILED if fetching data did not work - * (e.g. an illegal packet_id was passed). - */ - virtual ReturnValue_t getData(store_address_t packet_id, - const uint8_t** packet_ptr, size_t* size) = 0; - - - /** - * Modify data by supplying a store ID - * @param storeId - * @return Pair of return value and StorageAccessor helper - */ - virtual AccessorPair modifyData(store_address_t storeId) = 0; - - /** - * Modify data by supplying a store ID and a StorageAccessor helper instance. - * @param storeId - * @param accessor Helper class to access the modifiable data. - * @return - */ - virtual ReturnValue_t modifyData(store_address_t storeId, - StorageAccessor& accessor) = 0; - - /** - * Get pointer and size of modifiable data by supplying the storeId - * @param packet_id - * @param packet_ptr [out] Pointer to pointer of data to set - * @param size [out] Pointer to size to set - * @return - */ - virtual ReturnValue_t modifyData(store_address_t packet_id, - uint8_t** packet_ptr, size_t* size) = 0; - /** - * This method reserves an element of \c size. - * - * It returns the packet id of this element as well as a direct pointer to the - * data of the element. It must be assured that exactly \c size data is - * written to p_data! - * @param storageId A pointer to the storageId to retrieve. - * @param size The size of the space to be reserved. - * @param p_data A pointer to the element data is returned here. - * @return Returns @li RETURN_OK if data was added. - * @li RETURN_FAILED if data could not be added. - * storageId is unchanged then. - */ - virtual ReturnValue_t getFreeElement(store_address_t* storageId, - const size_t size, uint8_t** p_data, bool ignoreFault = false ) = 0; - - /** - * Clears the whole store. - * Use with care! - */ - virtual void clearStore() = 0; -}; - -#endif /* STORAGEMANAGERIF_H_ */ +#ifndef STORAGEMANAGERIF_H_H +#define STORAGEMANAGERIF_H_H + +#include "../events/Event.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../storagemanager/StorageAccessor.h" +#include "../storagemanager/storeAddress.h" +#include +#include + +using AccessorPair = std::pair; +using ConstAccessorPair = std::pair; + +/** + * @brief This class provides an interface for intermediate data storage. + * @details The Storage manager classes shall be used to store larger chunks of + * data in RAM for exchange between tasks. This interface expects the + * data to be stored in one consecutive block of memory, so tasks can + * write directly to the destination pointer. + * For interprocess communication, the stores must be locked during + * insertion and deletion. If the receiving storage identifier is + * passed token-like between tasks, a lock during read and write + * operations is not necessary. + * @author Bastian Baetz + * @date 18.09.2012 + */ +class StorageManagerIF : public HasReturnvaluesIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::STORAGE_MANAGER_IF; //!< The unique ID for return codes for this interface. + static const ReturnValue_t DATA_TOO_LARGE = MAKE_RETURN_CODE(1); //!< This return code indicates that the data to be stored is too large for the store. + static const ReturnValue_t DATA_STORAGE_FULL = MAKE_RETURN_CODE(2); //!< This return code indicates that a data storage is full. + static const ReturnValue_t ILLEGAL_STORAGE_ID = MAKE_RETURN_CODE(3); //!< This return code indicates that data was requested with an illegal storage ID. + static const ReturnValue_t DATA_DOES_NOT_EXIST = MAKE_RETURN_CODE(4); //!< This return code indicates that the requested ID was valid, but no data is stored there. + static const ReturnValue_t ILLEGAL_ADDRESS = MAKE_RETURN_CODE(5); + static const ReturnValue_t POOL_TOO_LARGE = MAKE_RETURN_CODE(6); //!< Pool size too large on initialization. + + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::OBSW; + static const Event GET_DATA_FAILED = MAKE_EVENT(0, SEVERITY::LOW); + static const Event STORE_DATA_FAILED = MAKE_EVENT(1, SEVERITY::LOW); + + static const uint32_t INVALID_ADDRESS = 0xFFFFFFFF; //!< Indicates an invalid (i.e unused) storage address. + /** + * @brief This is the empty virtual destructor as required for C++ interfaces. + */ + virtual ~StorageManagerIF() { + } + ; + /** + * @brief With addData, a free storage position is allocated and data + * stored there. + * @details During the allocation, the StorageManager is blocked. + * @param storageId A pointer to the storageId to retrieve. + * @param data The data to be stored in the StorageManager. + * @param size The amount of data to be stored. + * @return Returns @li RETURN_OK if data was added. + * @li RETURN_FAILED if data could not be added. + * storageId is unchanged then. + */ + virtual ReturnValue_t addData(store_address_t* storageId, + const uint8_t * data, size_t size, bool ignoreFault = false) = 0; + /** + * @brief With deleteData, the storageManager frees the memory region + * identified by packet_id. + * @param packet_id The identifier of the memory region to be freed. + * @return @li RETURN_OK on success. + * @li RETURN_FAILED if deletion did not work + * (e.g. an illegal packet_id was passed). + */ + virtual ReturnValue_t deleteData(store_address_t packet_id) = 0; + /** + * @brief Another deleteData which uses the pointer and size of the + * stored data to delete the content. + * @param buffer Pointer to the data. + * @param size Size of data to be stored. + * @param storeId Store id of the deleted element (optional) + * @return @li RETURN_OK on success. + * @li failure code if deletion did not work + */ + virtual ReturnValue_t deleteData(uint8_t* buffer, size_t size, + store_address_t* storeId = nullptr) = 0; + + + /** + * @brief Access the data by supplying a store ID. + * @details + * A pair consisting of the retrieval result and an instance of a + * ConstStorageAccessor class is returned + * @param storeId + * @return Pair of return value and a ConstStorageAccessor instance + */ + virtual ConstAccessorPair getData(store_address_t storeId) = 0; + + /** + * @brief Access the data by supplying a store ID and a helper + * instance + * @param storeId + * @param constAccessor Wrapper function to access store data. + * @return + */ + virtual ReturnValue_t getData(store_address_t storeId, + ConstStorageAccessor& constAccessor) = 0; + + + /** + * @brief getData returns an address to data and the size of the data + * for a given packet_id. + * @param packet_id The id of the data to be returned + * @param packet_ptr The passed pointer address is set to the the memory + * position + * @param size The exact size of the stored data is returned here. + * @return @li RETURN_OK on success. + * @li RETURN_FAILED if fetching data did not work + * (e.g. an illegal packet_id was passed). + */ + virtual ReturnValue_t getData(store_address_t packet_id, + const uint8_t** packet_ptr, size_t* size) = 0; + + + /** + * Modify data by supplying a store ID + * @param storeId + * @return Pair of return value and StorageAccessor helper + */ + virtual AccessorPair modifyData(store_address_t storeId) = 0; + + /** + * Modify data by supplying a store ID and a StorageAccessor helper instance. + * @param storeId + * @param accessor Helper class to access the modifiable data. + * @return + */ + virtual ReturnValue_t modifyData(store_address_t storeId, + StorageAccessor& accessor) = 0; + + /** + * Get pointer and size of modifiable data by supplying the storeId + * @param packet_id + * @param packet_ptr [out] Pointer to pointer of data to set + * @param size [out] Pointer to size to set + * @return + */ + virtual ReturnValue_t modifyData(store_address_t packet_id, + uint8_t** packet_ptr, size_t* size) = 0; + /** + * This method reserves an element of \c size. + * + * It returns the packet id of this element as well as a direct pointer to the + * data of the element. It must be assured that exactly \c size data is + * written to p_data! + * @param storageId A pointer to the storageId to retrieve. + * @param size The size of the space to be reserved. + * @param p_data A pointer to the element data is returned here. + * @return Returns @li RETURN_OK if data was added. + * @li RETURN_FAILED if data could not be added. + * storageId is unchanged then. + */ + virtual ReturnValue_t getFreeElement(store_address_t* storageId, + const size_t size, uint8_t** p_data, bool ignoreFault = false ) = 0; + + /** + * Clears the whole store. + * Use with care! + */ + virtual void clearStore() = 0; +}; + +#endif /* STORAGEMANAGERIF_H_ */ From af52d1ffdaa3a8fa09a34a4c0e39785d9ade9ff9 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 25 Aug 2020 14:14:58 +0200 Subject: [PATCH 252/653] Added some documentation in SerializeIF --- serialize/SerializeIF.h | 55 ++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/serialize/SerializeIF.h b/serialize/SerializeIF.h index 9ed52d29..1f31d91e 100644 --- a/serialize/SerializeIF.h +++ b/serialize/SerializeIF.h @@ -1,16 +1,16 @@ -#ifndef SERIALIZEIF_H_ -#define SERIALIZEIF_H_ +#ifndef FSFW_SERIALIZE_SERIALIZEIF_H_ +#define FSFW_SERIALIZE_SERIALIZEIF_H_ #include "../returnvalues/HasReturnvaluesIF.h" #include /** * \defgroup serialize Serialization - * Contains serialisation services. + * Contains serialization services. */ /** - * Translation of objects into data streams. + * Translation of objects into data streams and from data streams. * \ingroup serialize */ class SerializeIF { @@ -20,21 +20,58 @@ public: }; static const uint8_t INTERFACE_ID = CLASS_ID::SERIALIZE_IF; - static const ReturnValue_t BUFFER_TOO_SHORT = MAKE_RETURN_CODE(1); - static const ReturnValue_t STREAM_TOO_SHORT = MAKE_RETURN_CODE(2); - static const ReturnValue_t TOO_MANY_ELEMENTS = MAKE_RETURN_CODE(3); + static const ReturnValue_t BUFFER_TOO_SHORT = MAKE_RETURN_CODE(1); // !< The given buffer in serialize is too short + static const ReturnValue_t STREAM_TOO_SHORT = MAKE_RETURN_CODE(2); // !< The input stream in deSerialize is too short + static const ReturnValue_t TOO_MANY_ELEMENTS = MAKE_RETURN_CODE(3);// !< There are too many elements to be deSerialized virtual ~SerializeIF() { } - + /** + * Function to serialize the object into a buffer with maxSize at the current size. + * + * Implementations of this function must increase the size variable and move the buffer pointer. + * + * + * Custom implementations might use additional return values. + * + * @param buffer Buffer to serialize into, will be set to the current write location + * @param size Size that has been used in the buffer already, will be increase by the function + * @param maxSize Max size of the buffer. + * @param streamEndianness Endianness of the serialized data according to SerializeIF::Endianness + * @return + * - @¢ BUFFER_TOO_SHORT The given buffer in is too short + * - @c RETURN_FAILED Generic error + * - @c RETURN_OK Successful serialization + */ virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, Endianness streamEndianness) const = 0; + /** + * Gets the size of a object if it would be serialized in a buffer + * @return Size of serialized object + */ virtual size_t getSerializedSize() const = 0; + /** + * DeSerializes a object from a given buffer of given size. + * + * Buffer must be moved to the current read location by the implementation + * of this function. Size must be decreased by the implementation. + * + * Custom implementations might use additional return values. + * + * @param buffer Buffer to deSerialize from. Will be moved by the function. + * @param size Remaining Size of the buffer to read from. Will be decreased by function. + * @param streamEndianness Endianness as in according to SerializeIF::Endianness + * @return + * - @c STREAM_TOO_SHORT The input stream is too short to deSerialize the object + * - @c TOO_MANY_ELEMENTS The buffer has more inputs than expected + * - @c RETURN_FAILED Generic Error + * - @c RETURN_OK Successful deserialization + */ virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, Endianness streamEndianness) = 0; }; -#endif /* SERIALIZEIF_H_ */ +#endif /* FSFW_SERIALIZE_SERIALIZEIF_H_ */ From 6903a761ff3a185c1d79ada853cee975b77fdf57 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 25 Aug 2020 14:23:59 +0200 Subject: [PATCH 253/653] Some corrections --- serialize/SerializeIF.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/serialize/SerializeIF.h b/serialize/SerializeIF.h index 1f31d91e..3fb8b264 100644 --- a/serialize/SerializeIF.h +++ b/serialize/SerializeIF.h @@ -21,8 +21,8 @@ public: static const uint8_t INTERFACE_ID = CLASS_ID::SERIALIZE_IF; static const ReturnValue_t BUFFER_TOO_SHORT = MAKE_RETURN_CODE(1); // !< The given buffer in serialize is too short - static const ReturnValue_t STREAM_TOO_SHORT = MAKE_RETURN_CODE(2); // !< The input stream in deSerialize is too short - static const ReturnValue_t TOO_MANY_ELEMENTS = MAKE_RETURN_CODE(3);// !< There are too many elements to be deSerialized + static const ReturnValue_t STREAM_TOO_SHORT = MAKE_RETURN_CODE(2); // !< The input stream in deserialize is too short + static const ReturnValue_t TOO_MANY_ELEMENTS = MAKE_RETURN_CODE(3);// !< There are too many elements to be deserialized virtual ~SerializeIF() { } @@ -53,7 +53,7 @@ public: virtual size_t getSerializedSize() const = 0; /** - * DeSerializes a object from a given buffer of given size. + * Deserializes a object from a given buffer of given size. * * Buffer must be moved to the current read location by the implementation * of this function. Size must be decreased by the implementation. @@ -61,7 +61,7 @@ public: * Custom implementations might use additional return values. * * @param buffer Buffer to deSerialize from. Will be moved by the function. - * @param size Remaining Size of the buffer to read from. Will be decreased by function. + * @param size Remaining size of the buffer to read from. Will be decreased by function. * @param streamEndianness Endianness as in according to SerializeIF::Endianness * @return * - @c STREAM_TOO_SHORT The input stream is too short to deSerialize the object From 1ae79ab99d53f324eccf7a715bb3aaa9ba665e66 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 25 Aug 2020 15:06:53 +0200 Subject: [PATCH 254/653] Improvements of comments --- serialize/SerializeIF.h | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/serialize/SerializeIF.h b/serialize/SerializeIF.h index 3fb8b264..2bb17154 100644 --- a/serialize/SerializeIF.h +++ b/serialize/SerializeIF.h @@ -27,17 +27,21 @@ public: virtual ~SerializeIF() { } /** - * Function to serialize the object into a buffer with maxSize at the current size. + * @brief + * Function to serialize the object into a buffer with maxSize. Size represents the written amount. + * If a part of the buffer has been used already, size must be set to the used amount of bytes. * + * @details * Implementations of this function must increase the size variable and move the buffer pointer. - * + * MaxSize must be checked by implementations of this function + * and BUFFER_TOO_SHORT has to be returned if size would be larger than maxSize. * * Custom implementations might use additional return values. * - * @param buffer Buffer to serialize into, will be set to the current write location - * @param size Size that has been used in the buffer already, will be increase by the function - * @param maxSize Max size of the buffer. - * @param streamEndianness Endianness of the serialized data according to SerializeIF::Endianness + * @param[in/out] buffer Buffer to serialize into, will be set to the current write location + * @param[in/out] size Size that has been used in the buffer already, will be increased by the function + * @param[in] maxSize The size of the buffer that is allowed to be used for serialize. + * @param[in] streamEndianness Endianness of the serialized data according to SerializeIF::Endianness * @return * - @¢ BUFFER_TOO_SHORT The given buffer in is too short * - @c RETURN_FAILED Generic error @@ -47,22 +51,25 @@ public: size_t maxSize, Endianness streamEndianness) const = 0; /** - * Gets the size of a object if it would be serialized in a buffer + * Gets the size of a object if it would be serialized in a buffer.s * @return Size of serialized object */ virtual size_t getSerializedSize() const = 0; /** + * @brief * Deserializes a object from a given buffer of given size. * + * @details * Buffer must be moved to the current read location by the implementation * of this function. Size must be decreased by the implementation. + * Implementations are not allowed to alter the buffer as indicated by const pointer. * * Custom implementations might use additional return values. * - * @param buffer Buffer to deSerialize from. Will be moved by the function. - * @param size Remaining size of the buffer to read from. Will be decreased by function. - * @param streamEndianness Endianness as in according to SerializeIF::Endianness + * @param[in/out] buffer Buffer to deSerialize from. Will be moved by the function. + * @param[in/out] size Remaining size of the buffer to read from. Will be decreased by function. + * @param[in] streamEndianness Endianness as in according to SerializeIF::Endianness * @return * - @c STREAM_TOO_SHORT The input stream is too short to deSerialize the object * - @c TOO_MANY_ELEMENTS The buffer has more inputs than expected From d9ee6d0d909028dd1190985189e4b2f01c58e5c3 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 18:15:02 +0200 Subject: [PATCH 255/653] include fix --- osal/FreeRTOS/Mutex.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osal/FreeRTOS/Mutex.cpp b/osal/FreeRTOS/Mutex.cpp index e5896c41..9d9638b5 100644 --- a/osal/FreeRTOS/Mutex.cpp +++ b/osal/FreeRTOS/Mutex.cpp @@ -1,4 +1,4 @@ -#include +#include "Mutex.h" #include "../../serviceinterface/ServiceInterfaceStream.h" From 3f9d9b8770561a1487302d3f61e3e07aa012899d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 18:24:46 +0200 Subject: [PATCH 256/653] ipc update --- devicehandlers/HealthDevice.cpp | 2 +- ipc/CommandMessage.cpp | 242 +++++++++++++--------------- ipc/CommandMessage.h | 263 +++++++++++++++---------------- ipc/CommandMessageCleaner.cpp | 45 ++++++ ipc/CommandMessageCleaner.h | 16 ++ ipc/CommandMessageIF.h | 73 +++++++++ ipc/MessageQueueMessage.cpp | 149 ++++++++++-------- ipc/MessageQueueMessage.h | 268 ++++++++++++++++++-------------- ipc/MessageQueueMessageIF.h | 91 +++++++++++ 9 files changed, 700 insertions(+), 449 deletions(-) create mode 100644 ipc/CommandMessageCleaner.cpp create mode 100644 ipc/CommandMessageCleaner.h create mode 100644 ipc/CommandMessageIF.h create mode 100644 ipc/MessageQueueMessageIF.h diff --git a/devicehandlers/HealthDevice.cpp b/devicehandlers/HealthDevice.cpp index 411731dc..b15e5d2b 100644 --- a/devicehandlers/HealthDevice.cpp +++ b/devicehandlers/HealthDevice.cpp @@ -5,7 +5,7 @@ HealthDevice::HealthDevice(object_id_t setObjectId, MessageQueueId_t parentQueue) : SystemObject(setObjectId), lastHealth(HEALTHY), parentQueue( parentQueue), commandQueue(), healthHelper(this, setObjectId) { - commandQueue = QueueFactory::instance()->createMessageQueue(3, CommandMessage::COMMAND_MESSAGE_SIZE); + commandQueue = QueueFactory::instance()->createMessageQueue(3); } HealthDevice::~HealthDevice() { diff --git a/ipc/CommandMessage.cpp b/ipc/CommandMessage.cpp index dbea8533..16293608 100644 --- a/ipc/CommandMessage.cpp +++ b/ipc/CommandMessage.cpp @@ -1,131 +1,111 @@ -/** - * @file CommandMessage.cpp - * @brief This file defines the CommandMessage class. - * @date 20.06.2013 - * @author baetz - */ - -#include "../devicehandlers/DeviceHandlerMessage.h" -#include "../health/HealthMessage.h" -#include "CommandMessage.h" -#include "../memory/MemoryMessage.h" -#include "../modes/ModeMessage.h" -#include "../monitoring/MonitoringMessage.h" -#include "../subsystem/modes/ModeSequenceMessage.h" -#include "../tmstorage/TmStoreMessage.h" -#include "../parameters/ParameterMessage.h" - -namespace messagetypes { -void clearMissionMessage(CommandMessage* message); -} - - -CommandMessage::CommandMessage() { - this->messageSize = COMMAND_MESSAGE_SIZE; - setCommand(CMD_NONE); -} - -CommandMessage::CommandMessage(Command_t command, uint32_t parameter1, - uint32_t parameter2) { - this->messageSize = COMMAND_MESSAGE_SIZE; - setCommand(command); - setParameter(parameter1); - setParameter2(parameter2); -} - -Command_t CommandMessage::getCommand() const { - Command_t command; - memcpy(&command, getData(), sizeof(Command_t)); - return command; -} - -void CommandMessage::setCommand(Command_t command) { - memcpy(getData(), &command, sizeof(command)); -} - -uint32_t CommandMessage::getParameter() const { - uint32_t parameter1; - memcpy(¶meter1, getData() + sizeof(Command_t), sizeof(parameter1)); - return parameter1; -} - -void CommandMessage::setParameter(uint32_t parameter1) { - memcpy(getData() + sizeof(Command_t), ¶meter1, sizeof(parameter1)); -} - -uint32_t CommandMessage::getParameter2() const { - uint32_t parameter2; - memcpy(¶meter2, getData() + sizeof(Command_t) + sizeof(uint32_t), - sizeof(parameter2)); - return parameter2; -} - -void CommandMessage::setParameter2(uint32_t parameter2) { - memcpy(getData() + sizeof(Command_t) + sizeof(uint32_t), ¶meter2, - sizeof(parameter2)); -} - -void CommandMessage::clearCommandMessage() { - switch((getCommand()>>8) & 0xff){ - case messagetypes::MODE_COMMAND: - ModeMessage::clear(this); - break; - case messagetypes::HEALTH_COMMAND: - HealthMessage::clear(this); - break; - case messagetypes::MODE_SEQUENCE: - ModeSequenceMessage::clear(this); - break; - case messagetypes::ACTION: - ActionMessage::clear(this); - break; - case messagetypes::DEVICE_HANDLER_COMMAND: - DeviceHandlerMessage::clear(this); - break; - case messagetypes::MEMORY: - MemoryMessage::clear(this); - break; - case messagetypes::MONITORING: - MonitoringMessage::clear(this); - break; - case messagetypes::TM_STORE: - TmStoreMessage::clear(this); - break; - case messagetypes::PARAMETER: - ParameterMessage::clear(this); - break; - default: - messagetypes::clearMissionMessage(this); - break; - } -} - -bool CommandMessage::isClearedCommandMessage() { - return getCommand() == CMD_NONE; -} - -size_t CommandMessage::getMinimumMessageSize() const { - return COMMAND_MESSAGE_SIZE; -} - -void CommandMessage::setToUnknownCommand() { - Command_t initialCommand = getCommand(); - clearCommandMessage(); - setReplyRejected(UNKNOWN_COMMAND, initialCommand); -} - -void CommandMessage::setReplyRejected(ReturnValue_t reason, - Command_t initialCommand) { - setCommand(REPLY_REJECTED); - setParameter(reason); - setParameter2(initialCommand); -} - -ReturnValue_t CommandMessage::getReplyRejectedReason( - Command_t *initialCommand) const { - ReturnValue_t reason = getParameter(); - if(initialCommand != nullptr) { - *initialCommand = getParameter2(); - } - return reason; -} +#include "CommandMessage.h" +#include "CommandMessageCleaner.h" +#include + +CommandMessage::CommandMessage() { + MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE); + setCommand(CMD_NONE); +} + +CommandMessage::CommandMessage(Command_t command, uint32_t parameter1, + uint32_t parameter2) { + MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE); + setCommand(command); + setParameter(parameter1); + setParameter2(parameter2); +} + +Command_t CommandMessage::getCommand() const { + Command_t command; + std::memcpy(&command, MessageQueueMessage::getData(), sizeof(Command_t)); + return command; +} + +void CommandMessage::setCommand(Command_t command) { + std::memcpy(MessageQueueMessage::getData(), &command, sizeof(Command_t)); +} + +uint8_t CommandMessage::getMessageType() const { + // first byte of command ID. + return getCommand() >> 8 & 0xff; +} + +uint32_t CommandMessage::getParameter() const { + uint32_t parameter1; + std::memcpy(¶meter1, this->getData(), sizeof(parameter1)); + return parameter1; +} + +void CommandMessage::setParameter(uint32_t parameter1) { + std::memcpy(this->getData(), ¶meter1, sizeof(parameter1)); +} + +uint32_t CommandMessage::getParameter2() const { + uint32_t parameter2; + std::memcpy(¶meter2, this->getData() + sizeof(uint32_t), + sizeof(parameter2)); + return parameter2; +} + +void CommandMessage::setParameter2(uint32_t parameter2) { + std::memcpy(this->getData() + sizeof(uint32_t), ¶meter2, + sizeof(parameter2)); +} + +uint32_t CommandMessage::getParameter3() const { + uint32_t parameter3; + std::memcpy(¶meter3, this->getData() + 2 * sizeof(uint32_t), + sizeof(parameter3)); + return parameter3; +} + +void CommandMessage::setParameter3(uint32_t parameter3) { + std::memcpy(this->getData() + 2 * sizeof(uint32_t), ¶meter3, + sizeof(parameter3)); +} + +size_t CommandMessage::getMinimumMessageSize() const { + return MINIMUM_COMMAND_MESSAGE_SIZE; +} + +void CommandMessage::clearCommandMessage() { + clear(); +} + +void CommandMessage::clear() { + CommandMessageCleaner::clearCommandMessage(this); +} + +bool CommandMessage::isClearedCommandMessage() { + return getCommand() == CMD_NONE; +} + +void CommandMessage::setToUnknownCommand() { + Command_t initialCommand = getCommand(); + this->clear(); + setReplyRejected(UNKNOWN_COMMAND, initialCommand); +} + +void CommandMessage::setReplyRejected(ReturnValue_t reason, + Command_t initialCommand) { + setCommand(REPLY_REJECTED); + setParameter(reason); + setParameter2(initialCommand); +} + +ReturnValue_t CommandMessage::getReplyRejectedReason( + Command_t *initialCommand) const { + ReturnValue_t reason = getParameter(); + if(initialCommand != nullptr) { + *initialCommand = getParameter2(); + } + return reason; +} + +uint8_t* CommandMessage::getData() { + return MessageQueueMessage::getData() + sizeof(Command_t); +} + +const uint8_t* CommandMessage::getData() const { + return MessageQueueMessage::getData() + sizeof(Command_t); +} diff --git a/ipc/CommandMessage.h b/ipc/CommandMessage.h index e984ad3d..3be9a120 100644 --- a/ipc/CommandMessage.h +++ b/ipc/CommandMessage.h @@ -1,134 +1,129 @@ -/** - * @file CommandMessage.h - * @brief This file defines the CommandMessage class. - * @date 20.06.2013 - * @author baetz - */ - -#ifndef COMMANDMESSAGE_H_ -#define COMMANDMESSAGE_H_ - - -#include "FwMessageTypes.h" -#include - -#include "MessageQueueMessage.h" - -#define MAKE_COMMAND_ID( number ) ((MESSAGE_ID << 8) + (number)) -typedef ReturnValue_t Command_t; - -class CommandMessage : public MessageQueueMessage { -public: - static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE; - static const ReturnValue_t UNKNOWN_COMMAND = MAKE_RETURN_CODE(0x01); - - - static const uint8_t MESSAGE_ID = messagetypes::COMMAND; - static const Command_t CMD_NONE = MAKE_COMMAND_ID( 0 );//!< Used internally, will be ignored - static const Command_t REPLY_COMMAND_OK = MAKE_COMMAND_ID( 3 ); - static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID( 0xD1 );//!< Reply indicating that the current command was rejected, par1 should contain the error code - - /** - * This is the size of a message as it is seen by the MessageQueue - */ - static const size_t COMMAND_MESSAGE_SIZE = HEADER_SIZE - + sizeof(Command_t) + 2 * sizeof(uint32_t); - - /** - * Default Constructor, does not initialize anything. - * - * This constructor should be used when receiving a Message, as the content is filled by the MessageQueue. - */ - CommandMessage(); - /** - * This constructor creates a new message with all message content initialized - * - * @param command The DeviceHandlerCommand_t that will be sent - * @param parameter1 The first parameter - * @param parameter2 The second parameter - */ - CommandMessage(Command_t command, - uint32_t parameter1, uint32_t parameter2); - - /** - * Default Destructor - */ - virtual ~CommandMessage() { - } - - /** - * Read the DeviceHandlerCommand_t that is stored in the message, usually used after receiving - * - * @return the Command stored in the Message - */ - Command_t getCommand() const; - - /** - * Set the DeviceHandlerCOmmand_t of the message - * - * @param the Command to be sent - */ - void setCommand(Command_t command); - - /** - * Get the first parameter of the message - * - * @return the first Parameter of the message - */ - uint32_t getParameter() const; - - /** - * Set the first parameter of the message - * - * @param the first parameter of the message - */ - void setParameter(uint32_t parameter1); - - /** - * Get the second parameter of the message - * - * @return the second Parameter of the message - */ - uint32_t getParameter2() const; - - /** - * Set the second parameter of the message - * - * @param the second parameter of the message - */ - void setParameter2(uint32_t parameter2); - - /** - * Set the command to CMD_NONE and try to find - * the correct class to handle a more detailed - * clear. - * Also, calls a mission-specific clearMissionMessage - * function to separate between framework and mission - * messages. Not optimal, may be replaced by totally - * different auto-delete solution (e.g. smart pointers). - * - */ - void clearCommandMessage(); - - /** - * check if a message was cleared - * - * @return if the command is CMD_NONE - */ - bool isClearedCommandMessage(); - - - /** - * Sets the command to REPLY_REJECTED with parameter UNKNOWN_COMMAND. - * Is needed quite often, so we better code it once only. - */ - void setToUnknownCommand(); - void setReplyRejected(ReturnValue_t reason, Command_t initialCommand = CMD_NONE); - ReturnValue_t getReplyRejectedReason( - Command_t *initialCommand = nullptr) const; - - size_t getMinimumMessageSize() const; -}; - - -#endif /* COMMANDMESSAGE_H_ */ +#ifndef FSFW_IPC_COMMANDMESSAGE_H_ +#define FSFW_IPC_COMMANDMESSAGE_H_ + +#include "CommandMessageIF.h" +#include "MessageQueueMessage.h" +#include "FwMessageTypes.h" + +/** + * @brief Default command message used to pass command messages between tasks. + * Primary message type for IPC. Contains sender, 2-byte command ID + * field, and 2 4-byte parameters. + * @details + * It operates on an external memory which is contained inside a + * class implementing MessageQueueMessageIF by taking its address. + * This allows for a more flexible designs of message implementations. + * The pointer can be passed to different message implementations without + * the need of unnecessary copying. + * + * The command message is based of the generic MessageQueueMessage which + * currently has an internal message size of 28 bytes. + * @author Bastian Baetz + */ +class CommandMessage: public MessageQueueMessage, public CommandMessageIF { +public: + /** + * Default size can accomodate 2 4-byte parameters. + */ + static constexpr size_t DEFAULT_COMMAND_MESSAGE_SIZE = + CommandMessageIF::MINIMUM_COMMAND_MESSAGE_SIZE + sizeof(uint32_t); + + /** + * @brief Default Constructor, does not initialize anything. + * @details + * This constructor should be used when receiving a Message, as the + * content is filled by the MessageQueue. + */ + CommandMessage(); + /** + * This constructor creates a new message with all message content + * initialized + * + * @param command The DeviceHandlerCommand_t that will be sent + * @param parameter1 The first parameter + * @param parameter2 The second parameter + */ + CommandMessage(Command_t command, uint32_t parameter1, uint32_t parameter2); + + /** + * @brief Default Destructor + */ + virtual ~CommandMessage() {} + + /** + * Read the DeviceHandlerCommand_t that is stored in the message, + * usually used after receiving. + * + * @return the Command stored in the Message + */ + virtual Command_t getCommand() const override; + /** + * Set the command type of the message. Default implementation also + * sets the message type, which will be the first byte of the command ID. + * @param the Command to be sent + */ + virtual void setCommand(Command_t command); + + virtual uint8_t* getData() override; + virtual const uint8_t* getData() const override; + + /** + * Get the first parameter of the message + * @return the first Parameter of the message + */ + uint32_t getParameter() const; + /** + * Set the first parameter of the message + * @param the first parameter of the message + */ + void setParameter(uint32_t parameter1); + uint32_t getParameter2() const; + void setParameter2(uint32_t parameter2); + uint32_t getParameter3() const; + void setParameter3(uint32_t parameter3); + + /** + * check if a message was cleared + * + * @return if the command is CMD_NONE + */ + bool isClearedCommandMessage(); + + /** + * Sets the command to REPLY_REJECTED with parameter UNKNOWN_COMMAND. + * Is needed quite often, so we better code it once only. + */ + void setToUnknownCommand() override; + + /** + * A command message can be rejected and needs to offer a function + * to set a rejected reply + * @param reason + * @param initialCommand + */ + void setReplyRejected(ReturnValue_t reason, + Command_t initialCommand) override; + /** + * Corrensonding getter function. + * @param initialCommand + * @return + */ + ReturnValue_t getReplyRejectedReason( + Command_t* initialCommand = nullptr) const override; + + + virtual void clear() override; + void clearCommandMessage(); + + /** + * Extract message ID, which is the first byte of the command ID for the + * default implementation. + * @return + */ + virtual uint8_t getMessageType() const override; + + /** MessageQueueMessageIF functions used for minimum size check. */ + size_t getMinimumMessageSize() const override; +}; + +#endif /* FSFW_IPC_COMMANDMESSAGE_H_ */ diff --git a/ipc/CommandMessageCleaner.cpp b/ipc/CommandMessageCleaner.cpp new file mode 100644 index 00000000..a4dec78d --- /dev/null +++ b/ipc/CommandMessageCleaner.cpp @@ -0,0 +1,45 @@ +#include "../ipc/CommandMessageCleaner.h" + +#include "../devicehandlers/DeviceHandlerMessage.h" +#include "../health/HealthMessage.h" +#include "../memory/MemoryMessage.h" +#include "../modes/ModeMessage.h" +#include "../monitoring/MonitoringMessage.h" +#include "../subsystem/modes/ModeSequenceMessage.h" +#include "../tmstorage/TmStoreMessage.h" +#include "../parameters/ParameterMessage.h" + +void CommandMessageCleaner::clearCommandMessage(CommandMessage* message) { + switch(message->getMessageType()){ + case messagetypes::MODE_COMMAND: + ModeMessage::clear(message); + break; + case messagetypes::HEALTH_COMMAND: + HealthMessage::clear(message); + break; + case messagetypes::MODE_SEQUENCE: + ModeSequenceMessage::clear(message); + break; + case messagetypes::ACTION: + ActionMessage::clear(message); + break; + case messagetypes::DEVICE_HANDLER_COMMAND: + DeviceHandlerMessage::clear(message); + break; + case messagetypes::MEMORY: + MemoryMessage::clear(message); + break; + case messagetypes::MONITORING: + MonitoringMessage::clear(message); + break; + case messagetypes::TM_STORE: + TmStoreMessage::clear(message); + break; + case messagetypes::PARAMETER: + ParameterMessage::clear(message); + break; + default: + messagetypes::clearMissionMessage(message); + break; + } +} diff --git a/ipc/CommandMessageCleaner.h b/ipc/CommandMessageCleaner.h new file mode 100644 index 00000000..f17bf282 --- /dev/null +++ b/ipc/CommandMessageCleaner.h @@ -0,0 +1,16 @@ +#ifndef FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ +#define FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ +#include "../ipc/CommandMessage.h" + +namespace messagetypes { +// Implemented in config. +void clearMissionMessage(CommandMessage* message); +} + +class CommandMessageCleaner { +public: + static void clearCommandMessage(CommandMessage* message); +}; + + +#endif /* FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ */ diff --git a/ipc/CommandMessageIF.h b/ipc/CommandMessageIF.h new file mode 100644 index 00000000..68a8d956 --- /dev/null +++ b/ipc/CommandMessageIF.h @@ -0,0 +1,73 @@ +#ifndef FSFW_IPC_COMMANDMESSAGEIF_H_ +#define FSFW_IPC_COMMANDMESSAGEIF_H_ + +#include "MessageQueueMessageIF.h" +#include "FwMessageTypes.h" +#include "../returnvalues/HasReturnvaluesIF.h" + +#define MAKE_COMMAND_ID( number ) ((MESSAGE_ID << 8) + (number)) +typedef uint16_t Command_t; + +class CommandMessageIF { +public: + /** + * Header consists of sender ID and command ID. + */ + static constexpr size_t HEADER_SIZE = MessageQueueMessageIF::HEADER_SIZE + + sizeof(Command_t); + /** + * This minimum size is derived from the interface requirement to be able + * to set a rejected reply, which contains a returnvalue and the initial + * command. + */ + static constexpr size_t MINIMUM_COMMAND_MESSAGE_SIZE = + CommandMessageIF::HEADER_SIZE + sizeof(ReturnValue_t) + + sizeof(Command_t); + + static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE; + static const ReturnValue_t UNKNOWN_COMMAND = MAKE_RETURN_CODE(0x01); + + static const uint8_t MESSAGE_ID = messagetypes::COMMAND; + //! Used internally, shall be ignored + static const Command_t CMD_NONE = MAKE_COMMAND_ID( 0 ); + static const Command_t REPLY_COMMAND_OK = MAKE_COMMAND_ID( 1 ); + //! Reply indicating that the current command was rejected, + //! par1 should contain the error code + static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID( 2 ); + + virtual ~CommandMessageIF() {}; + + /** + * A command message shall have a uint16_t command ID field. + * @return + */ + virtual Command_t getCommand() const = 0; + /** + * A command message shall have a uint8_t message type ID field. + * @return + */ + virtual uint8_t getMessageType() const = 0; + + /** + * A command message can be rejected and needs to offer a function + * to set a rejected reply + * @param reason + * @param initialCommand + */ + virtual void setReplyRejected(ReturnValue_t reason, + Command_t initialCommand) = 0; + /** + * Corrensonding getter function. + * @param initialCommand + * @return + */ + virtual ReturnValue_t getReplyRejectedReason( + Command_t* initialCommand = nullptr) const = 0; + + virtual void setToUnknownCommand() = 0; + + virtual void clear() = 0; + +}; + +#endif /* FSFW_IPC_COMMANDMESSAGEIF_H_ */ diff --git a/ipc/MessageQueueMessage.cpp b/ipc/MessageQueueMessage.cpp index 05dde1f5..2f79cb3b 100644 --- a/ipc/MessageQueueMessage.cpp +++ b/ipc/MessageQueueMessage.cpp @@ -1,65 +1,84 @@ -#include "MessageQueueMessage.h" -#include "../serviceinterface/ServiceInterfaceStream.h" - -#include - -MessageQueueMessage::MessageQueueMessage() : - messageSize(this->HEADER_SIZE) { - memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); -} - -MessageQueueMessage::~MessageQueueMessage() { -} - -const uint8_t* MessageQueueMessage::getBuffer() const { - return this->internalBuffer; -} - -uint8_t* MessageQueueMessage::getBuffer() { - return this->internalBuffer; -} - -const uint8_t* MessageQueueMessage::getData() const { - return this->internalBuffer + this->HEADER_SIZE; -} - -uint8_t* MessageQueueMessage::getData() { - return this->internalBuffer + this->HEADER_SIZE; -} - -MessageQueueId_t MessageQueueMessage::getSender() const { - MessageQueueId_t temp_id; - memcpy(&temp_id, this->internalBuffer, sizeof(MessageQueueId_t)); - return temp_id; -} - -void MessageQueueMessage::setSender(MessageQueueId_t setId) { - memcpy(this->internalBuffer, &setId, sizeof(MessageQueueId_t)); -} - -MessageQueueMessage::MessageQueueMessage(uint8_t* data, uint32_t size) : - messageSize(this->HEADER_SIZE + size) { - if (size <= this->MAX_DATA_SIZE) { - memcpy(this->getData(), data, size); - } else { - memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); - this->messageSize = this->HEADER_SIZE; - } -} - -size_t MessageQueueMessage::getMinimumMessageSize() { - return this->HEADER_SIZE; -} - -void MessageQueueMessage::print() { - sif::debug << "MessageQueueMessage has size: " << this->messageSize << std::hex - << std::endl; - for (uint8_t count = 0; count < this->messageSize; count++) { - sif::debug << (uint32_t) this->internalBuffer[count] << ":"; - } - sif::debug << std::dec << std::endl; -} - -void MessageQueueMessage::clear() { - memset(this->getBuffer(), 0, this->MAX_MESSAGE_SIZE); -} +#include "MessageQueueMessage.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../globalfunctions/arrayprinter.h" +#include + +MessageQueueMessage::MessageQueueMessage() : + messageSize(getMinimumMessageSize()) { + memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); +} + +MessageQueueMessage::MessageQueueMessage(uint8_t* data, size_t size) : + messageSize(this->HEADER_SIZE + size) { + if (size <= this->MAX_DATA_SIZE) { + memcpy(this->getData(), data, size); + this->messageSize = this->HEADER_SIZE + size; + } + else { + sif::warning << "MessageQueueMessage: Passed size larger than maximum" + "allowed size! Setting content to 0" << std::endl; + memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); + this->messageSize = this->HEADER_SIZE; + } +} + +MessageQueueMessage::~MessageQueueMessage() { +} + +const uint8_t* MessageQueueMessage::getBuffer() const { + return this->internalBuffer; +} + +uint8_t* MessageQueueMessage::getBuffer() { + return this->internalBuffer; +} + +const uint8_t* MessageQueueMessage::getData() const { + return this->internalBuffer + this->HEADER_SIZE; +} + +uint8_t* MessageQueueMessage::getData() { + return this->internalBuffer + this->HEADER_SIZE; +} + +MessageQueueId_t MessageQueueMessage::getSender() const { + MessageQueueId_t temp_id; + memcpy(&temp_id, this->internalBuffer, sizeof(MessageQueueId_t)); + return temp_id; +} + +void MessageQueueMessage::setSender(MessageQueueId_t setId) { + memcpy(this->internalBuffer, &setId, sizeof(MessageQueueId_t)); +} + +void MessageQueueMessage::print(bool printWholeMessage) { + sif::debug << "MessageQueueMessage content: " << std::endl; + if(printWholeMessage) { + arrayprinter::print(getData(), getMaximumMessageSize()); + } + else { + arrayprinter::print(getData(), getMessageSize()); + } + +} + +void MessageQueueMessage::clear() { + memset(this->getBuffer(), 0, this->MAX_MESSAGE_SIZE); +} + +size_t MessageQueueMessage::getMessageSize() const { + return this->messageSize; +} + +void MessageQueueMessage::setMessageSize(size_t messageSize) { + this->messageSize = messageSize; +} + +size_t MessageQueueMessage::getMinimumMessageSize() const { + return this->MIN_MESSAGE_SIZE; +} + +size_t MessageQueueMessage::getMaximumMessageSize() const { + return this->MAX_MESSAGE_SIZE; +} + diff --git a/ipc/MessageQueueMessage.h b/ipc/MessageQueueMessage.h index aa3559d6..da5c78cb 100644 --- a/ipc/MessageQueueMessage.h +++ b/ipc/MessageQueueMessage.h @@ -1,118 +1,150 @@ -#ifndef MESSAGEQUEUEMESSAGE_H_ -#define MESSAGEQUEUEMESSAGE_H_ - -#include "MessageQueueSenderIF.h" -#include - -/** - * \brief This class is the representation and data organizer for interprocess messages. - * - * \details To facilitate and standardize interprocess communication, this class was created - * to handle a lightweight "interprocess message protocol". It adds a header with the - * sender's queue id to every sent message and defines the maximum total message size. - * Specialized messages, such as device commanding messages, can be created by inheriting - * from this class and filling the buffer provided by getData with additional content. - * If larger amounts of data must be sent between processes, the data shall be stored in - * the IPC Store object and only the storage id is passed in a queue message. - * The class is used both to generate and send messages and to receive messages from - * other tasks. - * \ingroup message_queue - */ -class MessageQueueMessage { -public: - /** - * \brief This constant defines the maximum size of the data content, excluding the header. - * \details It may be changed if necessary, but in general should be kept as small as possible. - */ - static const size_t MAX_DATA_SIZE = 24; - /** - * \brief This constants defines the size of the header, which is added to every message. - */ - static const size_t HEADER_SIZE = sizeof(MessageQueueId_t); - /** - * \brief This constant defines the maximum total size in bytes of a sent message. - * \details It is the sum of the maximum data and the header size. Be aware that this constant - * is used to define the buffer sizes for every message queue in the system. So, a change - * here may have significant impact on the required resources. - */ - static const size_t MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE; -private: - /** - * \brief This is the internal buffer that contains the actual message data. - */ - uint8_t internalBuffer[MAX_MESSAGE_SIZE]; -public: - /** - * \brief The size information of each message is stored in this attribute. - * \details It is public to simplify usage and to allow for passing the variable's address as a - * pointer. Care must be taken when inheriting from this class, as every child class is - * responsible for managing the size information by itself. When using the class to - * receive a message, the size information is updated automatically. - */ - size_t messageSize; - /** - * \brief The class is initialized empty with this constructor. - * \details The messageSize attribute is set to the header's size and the whole content is set to - * zero. - */ - MessageQueueMessage(); - /** - * \brief With this constructor the class is initialized with the given content. - * \details If the passed message size fits into the buffer, the passed data is copied to the - * internal buffer and the messageSize information is set. Otherwise, messageSize - * is set to the header's size and the whole content is set to zero. - * \param data The data to be put in the message. - * \param size Size of the data to be copied. Must be smaller than MAX_MESSAGE_SIZE. - */ - MessageQueueMessage(uint8_t* data, uint32_t size); - /** - * \brief As no memory is allocated in this class, the destructor is empty. - */ - virtual ~MessageQueueMessage(); - /** - * \brief This method is used to get the complete data of the message. - */ - const uint8_t* getBuffer() const; - /** - * \brief This method is used to get the complete data of the message. - */ - uint8_t* getBuffer(); - /** - * \brief This method is used to fetch the data content of the message. - * \details It shall be used by child classes to add data at the right position. - */ - const uint8_t* getData() const; - /** - * \brief This method is used to fetch the data content of the message. - * \details It shall be used by child classes to add data at the right position. - */ - uint8_t* getData(); - /** - * \brief This method is used to extract the sender's message queue id information from a - * received message. - */ - MessageQueueId_t getSender() const; - /** - * \brief With this method, the whole content and the message size is set to zero. - */ - void clear(); - /** - * \brief This is a debug method that prints the content (till messageSize) to the debug output. - */ - void print(); - /** - * \brief This method is used to set the sender's message queue id information prior to - * sending the message. - * \param setId The message queue id that identifies the sending message queue. - */ - void setSender(MessageQueueId_t setId); - /** - * \brief This helper function is used by the MessageQueue class to check the size of an - * incoming message. - * \details The method must be overwritten by child classes if size checks shall be more strict. - * @return The default implementation returns HEADER_SIZE. - */ - virtual size_t getMinimumMessageSize(); -}; - -#endif /* MESSAGEQUEUEMESSAGE_H_ */ +#ifndef FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ +#define FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ + +#include "../ipc/MessageQueueMessageIF.h" +#include "../ipc/MessageQueueSenderIF.h" +#include + +/** + * @brief This class is the representation and data organizer + * for interprocess messages. + * @details + * To facilitate and standardize interprocess communication, this class was + * created to handle a lightweight "interprocess message protocol". + * + * It adds a header with the sender's queue id to every sent message and + * defines the maximum total message size. Specialized messages, such as + * device commanding messages, can be created by inheriting from this class + * and filling the buffer provided by getData with additional content. + * + * If larger amounts of data must be sent between processes, the data shall + * be stored in the IPC Store object and only the storage id is passed in a + * queue message.The class is used both to generate and send messages and to + * receive messages from other tasks. + * @ingroup message_queue + */ +class MessageQueueMessage: public MessageQueueMessageIF { +public: + /** + * @brief The class is initialized empty with this constructor. + * @details + * The messageSize attribute is set to the header's size and the whole + * content is set to zero. + */ + MessageQueueMessage(); + /** + * @brief With this constructor the class is initialized with + * the given content. + * @details + * If the passed message size fits into the buffer, the passed data is + * copied to the internal buffer and the messageSize information is set. + * Otherwise, messageSize is set to the header's size and the whole + * content is set to zero. + * @param data The data to be put in the message. + * @param size Size of the data to be copied. Must be smaller than + * MAX_MESSAGE_SIZE and larger than MIN_MESSAGE_SIZE. + */ + MessageQueueMessage(uint8_t* data, size_t size); + + /** + * @brief As no memory is allocated in this class, + * the destructor is empty. + */ + virtual ~MessageQueueMessage(); + + /** + * @brief The size information of each message is stored in + * this attribute. + * @details + * It is public to simplify usage and to allow for passing the size + * address as a pointer. Care must be taken when inheriting from this class, + * as every child class is responsible for managing the size information by + * itself. When using the class to receive a message, the size information + * is updated automatically. + * + * Please note that the minimum size is limited by the size of the header + * while the maximum size is limited by the maximum allowed message size. + */ + size_t messageSize; + /** + * @brief This constant defines the maximum size of the data content, + * excluding the header. + * @details + * It may be changed if necessary, but in general should be kept + * as small as possible. + */ + static const size_t MAX_DATA_SIZE = 24; + + /** + * @brief This constant defines the maximum total size in bytes + * of a sent message. + * @details + * It is the sum of the maximum data and the header size. Be aware that + * this constant is used to define the buffer sizes for every message + * queue in the system. So, a change here may have significant impact on + * the required resources. + */ + static constexpr size_t MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE; + /** + * @brief Defines the minimum size of a message where only the + * header is included + */ + static constexpr size_t MIN_MESSAGE_SIZE = HEADER_SIZE; +private: + /** + * @brief This is the internal buffer that contains the + * actual message data. + */ + uint8_t internalBuffer[MAX_MESSAGE_SIZE]; +public: + /** + * @brief This method is used to get the complete data of the message. + */ + const uint8_t* getBuffer() const override; + /** + * @brief This method is used to get the complete data of the message. + */ + uint8_t* getBuffer() override; + /** + * @brief This method is used to fetch the data content of the message. + * @details + * It shall be used by child classes to add data at the right position. + */ + const uint8_t* getData() const override; + /** + * @brief This method is used to fetch the data content of the message. + * @details + * It shall be used by child classes to add data at the right position. + */ + uint8_t* getData() override; + /** + * @brief This method is used to extract the sender's message + * queue id information from a received message. + */ + MessageQueueId_t getSender() const override; + /** + * @brief With this method, the whole content + * and the message size is set to zero. + */ + void clear() override; + + /** + * @brief This method is used to set the sender's message queue id + * information prior to ing the message. + * @param setId + * The message queue id that identifies the sending message queue. + */ + void setSender(MessageQueueId_t setId) override; + + virtual size_t getMessageSize() const override; + virtual void setMessageSize(size_t messageSize) override; + virtual size_t getMinimumMessageSize() const override; + virtual size_t getMaximumMessageSize() const override; + + /** + * @brief This is a debug method that prints the content. + */ + void print(bool printWholeMessage); +}; + +#endif /* FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ */ diff --git a/ipc/MessageQueueMessageIF.h b/ipc/MessageQueueMessageIF.h new file mode 100644 index 00000000..91753ced --- /dev/null +++ b/ipc/MessageQueueMessageIF.h @@ -0,0 +1,91 @@ +#ifndef FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_ +#define FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_ +#include +#include + +/* + * TODO: Actually, the definition of this ID to be a uint32_t is not ideal and + * breaks layering. However, it is difficult to keep layering, as the ID is + * stored in many places and sent around in MessageQueueMessage. + * Ideally, one would use the (current) object_id_t only, however, doing a + * lookup of queueIDs for every call does not sound ideal. + * In a first step, I'll circumvent the issue by not touching it, + * maybe in a second step. This also influences Interface design + * (getCommandQueue) and some other issues.. + */ + +typedef uint32_t MessageQueueId_t; + +class MessageQueueMessageIF { +public: + static const MessageQueueId_t NO_QUEUE = -1; + /** + * @brief This constants defines the size of the header, + * which is added to every message. + */ + static const size_t HEADER_SIZE = sizeof(MessageQueueId_t); + + virtual ~MessageQueueMessageIF() {}; + + /** + * @brief With this method, the whole content and the message + * size is set to zero. + * @details + * Implementations should also take care to clear data which is stored + * indirectly (e.g. storage data). + */ + virtual void clear() = 0; + + /** + * @brief Get read-only pointer to the complete data of the message. + * @return + */ + virtual const uint8_t* getBuffer() const = 0; + + /** + * @brief This method is used to get the complete data of the message. + */ + virtual uint8_t* getBuffer() = 0; + + /** + * @brief This method is used to set the sender's message queue id + * information prior to sending the message. + * @param setId + * The message queue id that identifies the sending message queue. + */ + virtual void setSender(MessageQueueId_t setId) = 0; + + /** + * @brief This method is used to extract the sender's message queue id + * information from a received message. + */ + virtual MessageQueueId_t getSender() const = 0; + + /** + * @brief This method is used to fetch the data content of the message. + * @details + * It shall be used by child classes to add data at the right position. + */ + virtual const uint8_t* getData() const = 0; + /** + * @brief This method is used to fetch the data content of the message. + * @details + * It shall be used by child classes to add data at the right position. + */ + virtual uint8_t* getData() = 0; + + /** + * Get constant message size of current message implementation. + * @return + */ + virtual size_t getMessageSize() const = 0; + + virtual void setMessageSize(size_t messageSize) = 0; + virtual size_t getMinimumMessageSize() const = 0; + virtual size_t getMaximumMessageSize() const = 0; + +}; + + + +#endif /* FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_ */ From f13e7b4255005a1857abe9734cd8e1df325a4b0a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 18:30:11 +0200 Subject: [PATCH 257/653] include replacements --- osal/host/Clock.cpp | 454 +++++++++++++++---------------- osal/host/FixedTimeslotTask.cpp | 382 +++++++++++++------------- osal/host/FixedTimeslotTask.h | 260 +++++++++--------- osal/host/MessageQueue.cpp | 310 ++++++++++----------- osal/host/MessageQueue.h | 460 ++++++++++++++++---------------- osal/host/Mutex.cpp | 80 +++--- osal/host/Mutex.h | 56 ++-- osal/host/MutexFactory.cpp | 56 ++-- osal/host/PeriodicTask.cpp | 352 ++++++++++++------------ osal/host/PeriodicTask.h | 246 ++++++++--------- osal/host/QueueFactory.cpp | 82 +++--- osal/host/QueueMapManager.cpp | 102 +++---- osal/host/QueueMapManager.h | 94 +++---- osal/host/SemaphoreFactory.cpp | 84 +++--- osal/host/TaskFactory.cpp | 110 ++++---- 15 files changed, 1564 insertions(+), 1564 deletions(-) diff --git a/osal/host/Clock.cpp b/osal/host/Clock.cpp index 57f2572b..52d0d5f0 100644 --- a/osal/host/Clock.cpp +++ b/osal/host/Clock.cpp @@ -1,227 +1,227 @@ -#include -#include - -#include -#if defined(WIN32) -#include -#elif defined(LINUX) -#include -#endif - -uint16_t Clock::leapSeconds = 0; -MutexIF* Clock::timeMutex = NULL; - -using SystemClock = std::chrono::system_clock; - -uint32_t Clock::getTicksPerSecond(void){ - sif::warning << "Clock::getTicksPerSecond: not implemented yet" << std::endl; - return 0; - //return CLOCKS_PER_SEC; - //uint32_t ticks = sysconf(_SC_CLK_TCK); - //return ticks; -} - -ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { - // do some magic with chrono - sif::warning << "Clock::setClock: not implemented yet" << std::endl; - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t Clock::setClock(const timeval* time) { - // do some magic with chrono -#if defined(WIN32) - return HasReturnvaluesIF::RETURN_OK; -#elif defined(LINUX) - return HasReturnvaluesIF::RETURN_OK; -#else - -#endif - sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; -} - -ReturnValue_t Clock::getClock_timeval(timeval* time) { -#if defined(WIN32) - auto now = std::chrono::system_clock::now(); - auto secondsChrono = std::chrono::time_point_cast(now); - auto epoch = now.time_since_epoch(); - time->tv_sec = std::chrono::duration_cast(epoch).count(); - auto fraction = now - secondsChrono; - time->tv_usec = std::chrono::duration_cast( - fraction).count(); - return HasReturnvaluesIF::RETURN_OK; -#elif defined(LINUX) - timespec timeUnix; - int status = clock_gettime(CLOCK_REALTIME,&timeUnix); - if(status!=0){ - return HasReturnvaluesIF::RETURN_FAILED; - } - time->tv_sec = timeUnix.tv_sec; - time->tv_usec = timeUnix.tv_nsec / 1000.0; - return HasReturnvaluesIF::RETURN_OK; -#else - sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; -#endif - -} - -ReturnValue_t Clock::getClock_usecs(uint64_t* time) { - // do some magic with chrono - sif::warning << "Clock::gerClock_usecs: not implemented yet" << std::endl; - return HasReturnvaluesIF::RETURN_OK; -} - -timeval Clock::getUptime() { - timeval timeval; -#if defined(WIN32) - auto uptime = std::chrono::milliseconds(GetTickCount64()); - auto secondsChrono = std::chrono::duration_cast(uptime); - timeval.tv_sec = secondsChrono.count(); - auto fraction = uptime - secondsChrono; - timeval.tv_usec = std::chrono::duration_cast( - fraction).count(); -#elif defined(LINUX) - double uptimeSeconds; - if (std::ifstream("/proc/uptime", std::ios::in) >> uptimeSeconds) - { - // value is rounded down automatically - timeval.tv_sec = uptimeSeconds; - timeval.tv_usec = uptimeSeconds *(double) 1e6 - (timeval.tv_sec *1e6); - } -#else - sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; -#endif - return timeval; -} - -ReturnValue_t Clock::getUptime(timeval* uptime) { - *uptime = getUptime(); - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) { - timeval uptime = getUptime(); - *uptimeMs = uptime.tv_sec * 1000 + uptime.tv_usec / 1000; - return HasReturnvaluesIF::RETURN_OK; -} - - -ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { - // do some magic with chrono (C++20!) - // Right now, the library doesn't have the new features yet. - // so we work around that for now. - auto now = SystemClock::now(); - auto seconds = std::chrono::time_point_cast(now); - auto fraction = now - seconds; - time_t tt = SystemClock::to_time_t(now); - struct tm* timeInfo; - timeInfo = gmtime(&tt); - time->year = timeInfo->tm_year + 1900; - time->month = timeInfo->tm_mon+1; - time->day = timeInfo->tm_mday; - time->hour = timeInfo->tm_hour; - time->minute = timeInfo->tm_min; - time->second = timeInfo->tm_sec; - auto usecond = std::chrono::duration_cast(fraction); - time->usecond = usecond.count(); - - //sif::warning << "Clock::getDateAndTime: not implemented yet" << std::endl; - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, - timeval* to) { - struct tm time_tm; - - time_tm.tm_year = from->year - 1900; - time_tm.tm_mon = from->month - 1; - time_tm.tm_mday = from->day; - - time_tm.tm_hour = from->hour; - time_tm.tm_min = from->minute; - time_tm.tm_sec = from->second; - - time_t seconds = mktime(&time_tm); - - to->tv_sec = seconds; - to->tv_usec = from->usecond; - //Fails in 2038.. - return HasReturnvaluesIF::RETURN_OK; - sif::warning << "Clock::convertTimeBla: not implemented yet" << std::endl; - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) { - *JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. - / 3600.; - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) { - //SHOULDDO: works not for dates in the past (might have less leap seconds) - if (timeMutex == NULL) { - return HasReturnvaluesIF::RETURN_FAILED; - } - - uint16_t leapSeconds; - ReturnValue_t result = getLeapSeconds(&leapSeconds); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - timeval leapSeconds_timeval = { 0, 0 }; - leapSeconds_timeval.tv_sec = leapSeconds; - - //initial offset between UTC and TAI - timeval UTCtoTAI1972 = { 10, 0 }; - - timeval TAItoTT = { 32, 184000 }; - - *tt = utc + leapSeconds_timeval + UTCtoTAI1972 + TAItoTT; - - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) { - if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){ - return HasReturnvaluesIF::RETURN_FAILED; - } - ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - - leapSeconds = leapSeconds_; - - result = timeMutex->unlockMutex(); - return result; -} - -ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) { - if(timeMutex == nullptr){ - return HasReturnvaluesIF::RETURN_FAILED; - } - ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - - *leapSeconds_ = leapSeconds; - - result = timeMutex->unlockMutex(); - return result; -} - -ReturnValue_t Clock::checkOrCreateClockMutex(){ - if(timeMutex == nullptr){ - MutexFactory* mutexFactory = MutexFactory::instance(); - if (mutexFactory == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - timeMutex = mutexFactory->createMutex(); - if (timeMutex == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - } - return HasReturnvaluesIF::RETURN_OK; -} +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../timemanager/Clock.h" + +#include +#if defined(WIN32) +#include +#elif defined(LINUX) +#include +#endif + +uint16_t Clock::leapSeconds = 0; +MutexIF* Clock::timeMutex = NULL; + +using SystemClock = std::chrono::system_clock; + +uint32_t Clock::getTicksPerSecond(void){ + sif::warning << "Clock::getTicksPerSecond: not implemented yet" << std::endl; + return 0; + //return CLOCKS_PER_SEC; + //uint32_t ticks = sysconf(_SC_CLK_TCK); + //return ticks; +} + +ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { + // do some magic with chrono + sif::warning << "Clock::setClock: not implemented yet" << std::endl; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::setClock(const timeval* time) { + // do some magic with chrono +#if defined(WIN32) + return HasReturnvaluesIF::RETURN_OK; +#elif defined(LINUX) + return HasReturnvaluesIF::RETURN_OK; +#else + +#endif + sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; +} + +ReturnValue_t Clock::getClock_timeval(timeval* time) { +#if defined(WIN32) + auto now = std::chrono::system_clock::now(); + auto secondsChrono = std::chrono::time_point_cast(now); + auto epoch = now.time_since_epoch(); + time->tv_sec = std::chrono::duration_cast(epoch).count(); + auto fraction = now - secondsChrono; + time->tv_usec = std::chrono::duration_cast( + fraction).count(); + return HasReturnvaluesIF::RETURN_OK; +#elif defined(LINUX) + timespec timeUnix; + int status = clock_gettime(CLOCK_REALTIME,&timeUnix); + if(status!=0){ + return HasReturnvaluesIF::RETURN_FAILED; + } + time->tv_sec = timeUnix.tv_sec; + time->tv_usec = timeUnix.tv_nsec / 1000.0; + return HasReturnvaluesIF::RETURN_OK; +#else + sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; +#endif + +} + +ReturnValue_t Clock::getClock_usecs(uint64_t* time) { + // do some magic with chrono + sif::warning << "Clock::gerClock_usecs: not implemented yet" << std::endl; + return HasReturnvaluesIF::RETURN_OK; +} + +timeval Clock::getUptime() { + timeval timeval; +#if defined(WIN32) + auto uptime = std::chrono::milliseconds(GetTickCount64()); + auto secondsChrono = std::chrono::duration_cast(uptime); + timeval.tv_sec = secondsChrono.count(); + auto fraction = uptime - secondsChrono; + timeval.tv_usec = std::chrono::duration_cast( + fraction).count(); +#elif defined(LINUX) + double uptimeSeconds; + if (std::ifstream("/proc/uptime", std::ios::in) >> uptimeSeconds) + { + // value is rounded down automatically + timeval.tv_sec = uptimeSeconds; + timeval.tv_usec = uptimeSeconds *(double) 1e6 - (timeval.tv_sec *1e6); + } +#else + sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; +#endif + return timeval; +} + +ReturnValue_t Clock::getUptime(timeval* uptime) { + *uptime = getUptime(); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) { + timeval uptime = getUptime(); + *uptimeMs = uptime.tv_sec * 1000 + uptime.tv_usec / 1000; + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { + // do some magic with chrono (C++20!) + // Right now, the library doesn't have the new features yet. + // so we work around that for now. + auto now = SystemClock::now(); + auto seconds = std::chrono::time_point_cast(now); + auto fraction = now - seconds; + time_t tt = SystemClock::to_time_t(now); + struct tm* timeInfo; + timeInfo = gmtime(&tt); + time->year = timeInfo->tm_year + 1900; + time->month = timeInfo->tm_mon+1; + time->day = timeInfo->tm_mday; + time->hour = timeInfo->tm_hour; + time->minute = timeInfo->tm_min; + time->second = timeInfo->tm_sec; + auto usecond = std::chrono::duration_cast(fraction); + time->usecond = usecond.count(); + + //sif::warning << "Clock::getDateAndTime: not implemented yet" << std::endl; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, + timeval* to) { + struct tm time_tm; + + time_tm.tm_year = from->year - 1900; + time_tm.tm_mon = from->month - 1; + time_tm.tm_mday = from->day; + + time_tm.tm_hour = from->hour; + time_tm.tm_min = from->minute; + time_tm.tm_sec = from->second; + + time_t seconds = mktime(&time_tm); + + to->tv_sec = seconds; + to->tv_usec = from->usecond; + //Fails in 2038.. + return HasReturnvaluesIF::RETURN_OK; + sif::warning << "Clock::convertTimeBla: not implemented yet" << std::endl; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) { + *JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. + / 3600.; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) { + //SHOULDDO: works not for dates in the past (might have less leap seconds) + if (timeMutex == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } + + uint16_t leapSeconds; + ReturnValue_t result = getLeapSeconds(&leapSeconds); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + timeval leapSeconds_timeval = { 0, 0 }; + leapSeconds_timeval.tv_sec = leapSeconds; + + //initial offset between UTC and TAI + timeval UTCtoTAI1972 = { 10, 0 }; + + timeval TAItoTT = { 32, 184000 }; + + *tt = utc + leapSeconds_timeval + UTCtoTAI1972 + TAItoTT; + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) { + if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){ + return HasReturnvaluesIF::RETURN_FAILED; + } + ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + leapSeconds = leapSeconds_; + + result = timeMutex->unlockMutex(); + return result; +} + +ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) { + if(timeMutex == nullptr){ + return HasReturnvaluesIF::RETURN_FAILED; + } + ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + *leapSeconds_ = leapSeconds; + + result = timeMutex->unlockMutex(); + return result; +} + +ReturnValue_t Clock::checkOrCreateClockMutex(){ + if(timeMutex == nullptr){ + MutexFactory* mutexFactory = MutexFactory::instance(); + if (mutexFactory == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + timeMutex = mutexFactory->createMutex(); + if (timeMutex == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/osal/host/FixedTimeslotTask.cpp b/osal/host/FixedTimeslotTask.cpp index dac399f6..1999c9e6 100644 --- a/osal/host/FixedTimeslotTask.cpp +++ b/osal/host/FixedTimeslotTask.cpp @@ -1,191 +1,191 @@ -#include - -#include -#include -#include - -#include -#include - -#include -#include - -#if defined(WIN32) -#include -#elif defined(LINUX) -#include -#endif - -FixedTimeslotTask::FixedTimeslotTask(const char *name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod setPeriod, - void (*setDeadlineMissedFunc)()) : - started(false), pollingSeqTable(setPeriod*1000), taskName(name), - period(setPeriod), deadlineMissedFunc(setDeadlineMissedFunc) { - // It is propably possible to set task priorities by using the native - // task handles for Windows / Linux - mainThread = std::thread(&FixedTimeslotTask::taskEntryPoint, this, this); -#if defined(WIN32) - /* List of possible priority classes: - * https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ - * nf-processthreadsapi-setpriorityclass - * And respective thread priority numbers: - * https://docs.microsoft.com/en-us/windows/ - * win32/procthread/scheduling-priorities */ - int result = SetPriorityClass( - reinterpret_cast(mainThread.native_handle()), - ABOVE_NORMAL_PRIORITY_CLASS); - if(result != 0) { - sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with code " - << GetLastError() << std::endl; - } - result = SetThreadPriority( - reinterpret_cast(mainThread.native_handle()), - THREAD_PRIORITY_NORMAL); - if(result != 0) { - sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with code " - << GetLastError() << std::endl; - } -#elif defined(LINUX) - // we can just copy and paste the code from linux here. -#endif -} - -FixedTimeslotTask::~FixedTimeslotTask(void) { - //Do not delete objects, we were responsible for ptrs only. - terminateThread = true; - if(mainThread.joinable()) { - mainThread.join(); - } - delete this; -} - -void FixedTimeslotTask::taskEntryPoint(void* argument) { - FixedTimeslotTask *originalTask(reinterpret_cast(argument)); - - if (not originalTask->started) { - // we have to suspend/block here until the task is started. - // if semaphores are implemented, use them here. - std::unique_lock lock(initMutex); - initCondition.wait(lock); - } - - this->taskFunctionality(); - sif::debug << "FixedTimeslotTask::taskEntryPoint: " - "Returned from taskFunctionality." << std::endl; -} - -ReturnValue_t FixedTimeslotTask::startTask() { - started = true; - - // Notify task to start. - std::lock_guard lock(initMutex); - initCondition.notify_one(); - - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { - std::this_thread::sleep_for(std::chrono::milliseconds(ms)); - return HasReturnvaluesIF::RETURN_OK; -} - -void FixedTimeslotTask::taskFunctionality() { - // A local iterator for the Polling Sequence Table is created to - // find the start time for the first entry. - FixedSlotSequence::SlotListIter slotListIter = pollingSeqTable.current; - // Get start time for first entry. - chron_ms interval(slotListIter->pollingTimeMs); - auto currentStartTime { - std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()) - }; - if(interval.count() > 0) { - delayForInterval(¤tStartTime, interval); - } - - /* Enter the loop that defines the task behavior. */ - for (;;) { - if(terminateThread.load()) { - break; - } - //The component for this slot is executed and the next one is chosen. - this->pollingSeqTable.executeAndAdvance(); - if (not pollingSeqTable.slotFollowsImmediately()) { - // we need to wait before executing the current slot - //this gives us the time to wait: - interval = chron_ms(this->pollingSeqTable.getIntervalToPreviousSlotMs()); - delayForInterval(¤tStartTime, interval); - //TODO deadline missed check - } - } -} - -ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, - uint32_t slotTimeMs, int8_t executionStep) { - if (objectManager->get(componentId) != nullptr) { - pollingSeqTable.addSlot(componentId, slotTimeMs, executionStep, this); - return HasReturnvaluesIF::RETURN_OK; - } - - sif::error << "Component " << std::hex << componentId << - " not found, not adding it to pst" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; -} - -ReturnValue_t FixedTimeslotTask::checkSequence() const { - return pollingSeqTable.checkSequence(); -} - -uint32_t FixedTimeslotTask::getPeriodMs() const { - return period * 1000; -} - -bool FixedTimeslotTask::delayForInterval(chron_ms * previousWakeTimeMs, - const chron_ms interval) { - bool shouldDelay = false; - //Get current wakeup time - auto currentStartTime = - std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()); - /* Generate the tick time at which the task wants to wake. */ - auto nextTimeToWake_ms = (*previousWakeTimeMs) + interval; - - if (currentStartTime < *previousWakeTimeMs) { - /* The tick count has overflowed since this function was - lasted called. In this case the only time we should ever - actually delay is if the wake time has also overflowed, - and the wake time is greater than the tick time. When this - is the case it is as if neither time had overflowed. */ - if ((nextTimeToWake_ms < *previousWakeTimeMs) - && (nextTimeToWake_ms > currentStartTime)) { - shouldDelay = true; - } - } else { - /* The tick time has not overflowed. In this case we will - delay if either the wake time has overflowed, and/or the - tick time is less than the wake time. */ - if ((nextTimeToWake_ms < *previousWakeTimeMs) - || (nextTimeToWake_ms > currentStartTime)) { - shouldDelay = true; - } - } - - /* Update the wake time ready for the next call. */ - - (*previousWakeTimeMs) = nextTimeToWake_ms; - - if (shouldDelay) { - auto sleepTime = std::chrono::duration_cast( - nextTimeToWake_ms - currentStartTime); - std::this_thread::sleep_for(sleepTime); - return true; - } - //We are shifting the time in case the deadline was missed like rtems - (*previousWakeTimeMs) = currentStartTime; - return false; - -} - - - - +#include "../../osal/host/FixedTimeslotTask.h" + +#include "../../ipc/MutexFactory.h" +#include "../../osal/host/Mutex.h" +#include "../../osal/host/FixedTimeslotTask.h" + +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../tasks/ExecutableObjectIF.h" + +#include +#include + +#if defined(WIN32) +#include +#elif defined(LINUX) +#include +#endif + +FixedTimeslotTask::FixedTimeslotTask(const char *name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod setPeriod, + void (*setDeadlineMissedFunc)()) : + started(false), pollingSeqTable(setPeriod*1000), taskName(name), + period(setPeriod), deadlineMissedFunc(setDeadlineMissedFunc) { + // It is propably possible to set task priorities by using the native + // task handles for Windows / Linux + mainThread = std::thread(&FixedTimeslotTask::taskEntryPoint, this, this); +#if defined(WIN32) + /* List of possible priority classes: + * https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ + * nf-processthreadsapi-setpriorityclass + * And respective thread priority numbers: + * https://docs.microsoft.com/en-us/windows/ + * win32/procthread/scheduling-priorities */ + int result = SetPriorityClass( + reinterpret_cast(mainThread.native_handle()), + ABOVE_NORMAL_PRIORITY_CLASS); + if(result != 0) { + sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with code " + << GetLastError() << std::endl; + } + result = SetThreadPriority( + reinterpret_cast(mainThread.native_handle()), + THREAD_PRIORITY_NORMAL); + if(result != 0) { + sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with code " + << GetLastError() << std::endl; + } +#elif defined(LINUX) + // we can just copy and paste the code from linux here. +#endif +} + +FixedTimeslotTask::~FixedTimeslotTask(void) { + //Do not delete objects, we were responsible for ptrs only. + terminateThread = true; + if(mainThread.joinable()) { + mainThread.join(); + } + delete this; +} + +void FixedTimeslotTask::taskEntryPoint(void* argument) { + FixedTimeslotTask *originalTask(reinterpret_cast(argument)); + + if (not originalTask->started) { + // we have to suspend/block here until the task is started. + // if semaphores are implemented, use them here. + std::unique_lock lock(initMutex); + initCondition.wait(lock); + } + + this->taskFunctionality(); + sif::debug << "FixedTimeslotTask::taskEntryPoint: " + "Returned from taskFunctionality." << std::endl; +} + +ReturnValue_t FixedTimeslotTask::startTask() { + started = true; + + // Notify task to start. + std::lock_guard lock(initMutex); + initCondition.notify_one(); + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); + return HasReturnvaluesIF::RETURN_OK; +} + +void FixedTimeslotTask::taskFunctionality() { + // A local iterator for the Polling Sequence Table is created to + // find the start time for the first entry. + FixedSlotSequence::SlotListIter slotListIter = pollingSeqTable.current; + // Get start time for first entry. + chron_ms interval(slotListIter->pollingTimeMs); + auto currentStartTime { + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + }; + if(interval.count() > 0) { + delayForInterval(¤tStartTime, interval); + } + + /* Enter the loop that defines the task behavior. */ + for (;;) { + if(terminateThread.load()) { + break; + } + //The component for this slot is executed and the next one is chosen. + this->pollingSeqTable.executeAndAdvance(); + if (not pollingSeqTable.slotFollowsImmediately()) { + // we need to wait before executing the current slot + //this gives us the time to wait: + interval = chron_ms(this->pollingSeqTable.getIntervalToPreviousSlotMs()); + delayForInterval(¤tStartTime, interval); + //TODO deadline missed check + } + } +} + +ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, + uint32_t slotTimeMs, int8_t executionStep) { + if (objectManager->get(componentId) != nullptr) { + pollingSeqTable.addSlot(componentId, slotTimeMs, executionStep, this); + return HasReturnvaluesIF::RETURN_OK; + } + + sif::error << "Component " << std::hex << componentId << + " not found, not adding it to pst" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; +} + +ReturnValue_t FixedTimeslotTask::checkSequence() const { + return pollingSeqTable.checkSequence(); +} + +uint32_t FixedTimeslotTask::getPeriodMs() const { + return period * 1000; +} + +bool FixedTimeslotTask::delayForInterval(chron_ms * previousWakeTimeMs, + const chron_ms interval) { + bool shouldDelay = false; + //Get current wakeup time + auto currentStartTime = + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()); + /* Generate the tick time at which the task wants to wake. */ + auto nextTimeToWake_ms = (*previousWakeTimeMs) + interval; + + if (currentStartTime < *previousWakeTimeMs) { + /* The tick count has overflowed since this function was + lasted called. In this case the only time we should ever + actually delay is if the wake time has also overflowed, + and the wake time is greater than the tick time. When this + is the case it is as if neither time had overflowed. */ + if ((nextTimeToWake_ms < *previousWakeTimeMs) + && (nextTimeToWake_ms > currentStartTime)) { + shouldDelay = true; + } + } else { + /* The tick time has not overflowed. In this case we will + delay if either the wake time has overflowed, and/or the + tick time is less than the wake time. */ + if ((nextTimeToWake_ms < *previousWakeTimeMs) + || (nextTimeToWake_ms > currentStartTime)) { + shouldDelay = true; + } + } + + /* Update the wake time ready for the next call. */ + + (*previousWakeTimeMs) = nextTimeToWake_ms; + + if (shouldDelay) { + auto sleepTime = std::chrono::duration_cast( + nextTimeToWake_ms - currentStartTime); + std::this_thread::sleep_for(sleepTime); + return true; + } + //We are shifting the time in case the deadline was missed like rtems + (*previousWakeTimeMs) = currentStartTime; + return false; + +} + + + + diff --git a/osal/host/FixedTimeslotTask.h b/osal/host/FixedTimeslotTask.h index b12cc6d3..bbee94a6 100644 --- a/osal/host/FixedTimeslotTask.h +++ b/osal/host/FixedTimeslotTask.h @@ -1,130 +1,130 @@ -#ifndef FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ -#define FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ - -#include -#include -#include -#include - -#include -#include -#include -#include - -class ExecutableObjectIF; - -/** - * @brief This class represents a task for periodic activities with multiple - * steps and strict timeslot requirements for these steps. - * @details - * @ingroup task_handling - */ -class FixedTimeslotTask: public FixedTimeslotTaskIF { -public: - /** - * @brief Standard constructor of the class. - * @details - * The class is initialized without allocated objects. These need to be - * added with #addComponent. - * @param priority - * @param stack_size - * @param setPeriod - * @param setDeadlineMissedFunc - * The function pointer to the deadline missed function that shall be - * assigned. - */ - FixedTimeslotTask(const char *name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod setPeriod, - void (*setDeadlineMissedFunc)()); - /** - * @brief Currently, the executed object's lifetime is not coupled with - * the task object's lifetime, so the destructor is empty. - */ - virtual ~FixedTimeslotTask(void); - - /** - * @brief The method to start the task. - * @details The method starts the task with the respective system call. - * Entry point is the taskEntryPoint method described below. - * The address of the task object is passed as an argument - * to the system call. - */ - ReturnValue_t startTask(void); - - /** - * Add timeslot to the polling sequence table. - * @param componentId - * @param slotTimeMs - * @param executionStep - * @return - */ - ReturnValue_t addSlot(object_id_t componentId, - uint32_t slotTimeMs, int8_t executionStep); - - ReturnValue_t checkSequence() const; - - uint32_t getPeriodMs() const; - - ReturnValue_t sleepFor(uint32_t ms); - -protected: - using chron_ms = std::chrono::milliseconds; - - bool started; - //!< Typedef for the List of objects. - typedef std::vector ObjectList; - std::thread mainThread; - std::atomic terminateThread = false; - - //! Polling sequence table which contains the object to execute - //! and information like the timeslots and the passed execution step. - FixedSlotSequence pollingSeqTable; - - std::condition_variable initCondition; - std::mutex initMutex; - std::string taskName; - /** - * @brief The period of the task. - * @details - * The period determines the frequency of the task's execution. - * It is expressed in clock ticks. - */ - TaskPeriod period; - - /** - * @brief The pointer to the deadline-missed function. - * @details - * This pointer stores the function that is executed if the task's deadline - * is missed. So, each may react individually on a timing failure. - * The pointer may be NULL, then nothing happens on missing the deadline. - * The deadline is equal to the next execution of the periodic task. - */ - void (*deadlineMissedFunc)(void); - /** - * @brief This is the function executed in the new task's context. - * @details - * It converts the argument back to the thread object type and copies the - * class instance to the task context. - * The taskFunctionality method is called afterwards. - * @param A pointer to the task object itself is passed as argument. - */ - - void taskEntryPoint(void* argument); - /** - * @brief The function containing the actual functionality of the task. - * @details - * The method sets and starts the task's period, then enters a loop that is - * repeated as long as the isRunning attribute is true. Within the loop, - * all performOperation methods of the added objects are called. Afterwards - * the checkAndRestartPeriod system call blocks the task until the next - * period. On missing the deadline, the deadlineMissedFunction is executed. - */ - void taskFunctionality(void); - - bool delayForInterval(chron_ms * previousWakeTimeMs, - const chron_ms interval); -}; - - - -#endif /* FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ */ +#ifndef FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ +#define FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ + +#include "../../objectmanager/ObjectManagerIF.h" +#include "../../tasks/FixedSlotSequence.h" +#include "../../tasks/FixedTimeslotTaskIF.h" +#include "../../tasks/Typedef.h" + +#include +#include +#include +#include + +class ExecutableObjectIF; + +/** + * @brief This class represents a task for periodic activities with multiple + * steps and strict timeslot requirements for these steps. + * @details + * @ingroup task_handling + */ +class FixedTimeslotTask: public FixedTimeslotTaskIF { +public: + /** + * @brief Standard constructor of the class. + * @details + * The class is initialized without allocated objects. These need to be + * added with #addComponent. + * @param priority + * @param stack_size + * @param setPeriod + * @param setDeadlineMissedFunc + * The function pointer to the deadline missed function that shall be + * assigned. + */ + FixedTimeslotTask(const char *name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod setPeriod, + void (*setDeadlineMissedFunc)()); + /** + * @brief Currently, the executed object's lifetime is not coupled with + * the task object's lifetime, so the destructor is empty. + */ + virtual ~FixedTimeslotTask(void); + + /** + * @brief The method to start the task. + * @details The method starts the task with the respective system call. + * Entry point is the taskEntryPoint method described below. + * The address of the task object is passed as an argument + * to the system call. + */ + ReturnValue_t startTask(void); + + /** + * Add timeslot to the polling sequence table. + * @param componentId + * @param slotTimeMs + * @param executionStep + * @return + */ + ReturnValue_t addSlot(object_id_t componentId, + uint32_t slotTimeMs, int8_t executionStep); + + ReturnValue_t checkSequence() const; + + uint32_t getPeriodMs() const; + + ReturnValue_t sleepFor(uint32_t ms); + +protected: + using chron_ms = std::chrono::milliseconds; + + bool started; + //!< Typedef for the List of objects. + typedef std::vector ObjectList; + std::thread mainThread; + std::atomic terminateThread = false; + + //! Polling sequence table which contains the object to execute + //! and information like the timeslots and the passed execution step. + FixedSlotSequence pollingSeqTable; + + std::condition_variable initCondition; + std::mutex initMutex; + std::string taskName; + /** + * @brief The period of the task. + * @details + * The period determines the frequency of the task's execution. + * It is expressed in clock ticks. + */ + TaskPeriod period; + + /** + * @brief The pointer to the deadline-missed function. + * @details + * This pointer stores the function that is executed if the task's deadline + * is missed. So, each may react individually on a timing failure. + * The pointer may be NULL, then nothing happens on missing the deadline. + * The deadline is equal to the next execution of the periodic task. + */ + void (*deadlineMissedFunc)(void); + /** + * @brief This is the function executed in the new task's context. + * @details + * It converts the argument back to the thread object type and copies the + * class instance to the task context. + * The taskFunctionality method is called afterwards. + * @param A pointer to the task object itself is passed as argument. + */ + + void taskEntryPoint(void* argument); + /** + * @brief The function containing the actual functionality of the task. + * @details + * The method sets and starts the task's period, then enters a loop that is + * repeated as long as the isRunning attribute is true. Within the loop, + * all performOperation methods of the added objects are called. Afterwards + * the checkAndRestartPeriod system call blocks the task until the next + * period. On missing the deadline, the deadlineMissedFunction is executed. + */ + void taskFunctionality(void); + + bool delayForInterval(chron_ms * previousWakeTimeMs, + const chron_ms interval); +}; + + + +#endif /* FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ */ diff --git a/osal/host/MessageQueue.cpp b/osal/host/MessageQueue.cpp index 7af5fbd9..6fd42849 100644 --- a/osal/host/MessageQueue.cpp +++ b/osal/host/MessageQueue.cpp @@ -1,155 +1,155 @@ -#include -#include -#include -#include -#include - -MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize): - messageSize(maxMessageSize), messageDepth(messageDepth) { - queueLock = MutexFactory::instance()->createMutex(); - auto result = QueueMapManager::instance()->addMessageQueue(this, &mqId); - if(result != HasReturnvaluesIF::RETURN_OK) { - sif::error << "MessageQueue: Could not be created" << std::endl; - } -} - -MessageQueue::~MessageQueue() { - MutexFactory::instance()->deleteMutex(queueLock); -} - -ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessageIF* message, bool ignoreFault) { - return sendMessageFrom(sendTo, message, this->getId(), ignoreFault); -} - -ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) { - return sendToDefaultFrom(message, this->getId()); -} - -ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message, - MessageQueueId_t sentFrom, bool ignoreFault) { - return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault); -} - -ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) { - if (this->lastPartner != 0) { - return sendMessageFrom(this->lastPartner, message, this->getId()); - } else { - return MessageQueueIF::NO_REPLY_PARTNER; - } -} - -ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, - MessageQueueMessageIF* message, MessageQueueId_t sentFrom, - bool ignoreFault) { - return sendMessageFromMessageQueue(sendTo, message, sentFrom, - ignoreFault); -} - -ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message, - MessageQueueId_t* receivedFrom) { - ReturnValue_t status = this->receiveMessage(message); - if(status == HasReturnvaluesIF::RETURN_OK) { - *receivedFrom = this->lastPartner; - } - return status; -} - -ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { - if(messageQueue.empty()) { - return MessageQueueIF::EMPTY; - } - // not sure this will work.. - //*message = std::move(messageQueue.front()); - MutexHelper mutexLock(queueLock, 20); - MessageQueueMessage* currentMessage = &messageQueue.front(); - std::copy(currentMessage->getBuffer(), - currentMessage->getBuffer() + messageSize, message->getBuffer()); - messageQueue.pop(); - // The last partner is the first uint32_t field in the message - this->lastPartner = message->getSender(); - return HasReturnvaluesIF::RETURN_OK; -} - -MessageQueueId_t MessageQueue::getLastPartner() const { - return lastPartner; -} - -ReturnValue_t MessageQueue::flush(uint32_t* count) { - *count = messageQueue.size(); - // Clears the queue. - messageQueue = std::queue(); - return HasReturnvaluesIF::RETURN_OK; -} - -MessageQueueId_t MessageQueue::getId() const { - return mqId; -} - -void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) { - defaultDestinationSet = true; - this->defaultDestination = defaultDestination; -} - -MessageQueueId_t MessageQueue::getDefaultDestination() const { - return defaultDestination; -} - -bool MessageQueue::isDefaultDestinationSet() const { - return defaultDestinationSet; -} - - -// static core function to send messages. -ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, - MessageQueueMessageIF* message, MessageQueueId_t sentFrom, - bool ignoreFault) { - if(message->getMessageSize() > message->getMaximumMessageSize()) { - // Actually, this should never happen or an error will be emitted - // in MessageQueueMessage. - // But I will still return a failure here. - return HasReturnvaluesIF::RETURN_FAILED; - } - MessageQueue* targetQueue = dynamic_cast( - QueueMapManager::instance()->getMessageQueue(sendTo)); - if(targetQueue == nullptr) { - if(not ignoreFault) { - InternalErrorReporterIF* internalErrorReporter = - objectManager->get( - objects::INTERNAL_ERROR_REPORTER); - if (internalErrorReporter != nullptr) { - internalErrorReporter->queueMessageNotSent(); - } - } - // TODO: Better returnvalue - return HasReturnvaluesIF::RETURN_FAILED; - } - - if(targetQueue->messageQueue.size() < targetQueue->messageDepth) { - MutexHelper mutexLock(targetQueue->queueLock, 20); - // not ideal, works for now though. - MessageQueueMessage* mqmMessage = - dynamic_cast(message); - if(message != nullptr) { - targetQueue->messageQueue.push(*mqmMessage); - } - else { - sif::error << "MessageQueue::sendMessageFromMessageQueue: Message" - "is not MessageQueueMessage!" << std::endl; - } - - } - else { - return MessageQueueIF::FULL; - } - message->setSender(sentFrom); - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t MessageQueue::lockQueue(dur_millis_t lockTimeout) { - return queueLock->lockMutex(lockTimeout); -} - -ReturnValue_t MessageQueue::unlockQueue() { - return queueLock->unlockMutex(); -} +#include "../../osal/host/MessageQueue.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../osal/host/QueueMapManager.h" +#include "../../ipc/MutexFactory.h" +#include "../../ipc/MutexHelper.h" + +MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize): + messageSize(maxMessageSize), messageDepth(messageDepth) { + queueLock = MutexFactory::instance()->createMutex(); + auto result = QueueMapManager::instance()->addMessageQueue(this, &mqId); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "MessageQueue: Could not be created" << std::endl; + } +} + +MessageQueue::~MessageQueue() { + MutexFactory::instance()->deleteMutex(queueLock); +} + +ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, bool ignoreFault) { + return sendMessageFrom(sendTo, message, this->getId(), ignoreFault); +} + +ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) { + return sendToDefaultFrom(message, this->getId()); +} + +ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message, + MessageQueueId_t sentFrom, bool ignoreFault) { + return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault); +} + +ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) { + if (this->lastPartner != 0) { + return sendMessageFrom(this->lastPartner, message, this->getId()); + } else { + return MessageQueueIF::NO_REPLY_PARTNER; + } +} + +ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + return sendMessageFromMessageQueue(sendTo, message, sentFrom, + ignoreFault); +} + +ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message, + MessageQueueId_t* receivedFrom) { + ReturnValue_t status = this->receiveMessage(message); + if(status == HasReturnvaluesIF::RETURN_OK) { + *receivedFrom = this->lastPartner; + } + return status; +} + +ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { + if(messageQueue.empty()) { + return MessageQueueIF::EMPTY; + } + // not sure this will work.. + //*message = std::move(messageQueue.front()); + MutexHelper mutexLock(queueLock, 20); + MessageQueueMessage* currentMessage = &messageQueue.front(); + std::copy(currentMessage->getBuffer(), + currentMessage->getBuffer() + messageSize, message->getBuffer()); + messageQueue.pop(); + // The last partner is the first uint32_t field in the message + this->lastPartner = message->getSender(); + return HasReturnvaluesIF::RETURN_OK; +} + +MessageQueueId_t MessageQueue::getLastPartner() const { + return lastPartner; +} + +ReturnValue_t MessageQueue::flush(uint32_t* count) { + *count = messageQueue.size(); + // Clears the queue. + messageQueue = std::queue(); + return HasReturnvaluesIF::RETURN_OK; +} + +MessageQueueId_t MessageQueue::getId() const { + return mqId; +} + +void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) { + defaultDestinationSet = true; + this->defaultDestination = defaultDestination; +} + +MessageQueueId_t MessageQueue::getDefaultDestination() const { + return defaultDestination; +} + +bool MessageQueue::isDefaultDestinationSet() const { + return defaultDestinationSet; +} + + +// static core function to send messages. +ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + if(message->getMessageSize() > message->getMaximumMessageSize()) { + // Actually, this should never happen or an error will be emitted + // in MessageQueueMessage. + // But I will still return a failure here. + return HasReturnvaluesIF::RETURN_FAILED; + } + MessageQueue* targetQueue = dynamic_cast( + QueueMapManager::instance()->getMessageQueue(sendTo)); + if(targetQueue == nullptr) { + if(not ignoreFault) { + InternalErrorReporterIF* internalErrorReporter = + objectManager->get( + objects::INTERNAL_ERROR_REPORTER); + if (internalErrorReporter != nullptr) { + internalErrorReporter->queueMessageNotSent(); + } + } + // TODO: Better returnvalue + return HasReturnvaluesIF::RETURN_FAILED; + } + + if(targetQueue->messageQueue.size() < targetQueue->messageDepth) { + MutexHelper mutexLock(targetQueue->queueLock, 20); + // not ideal, works for now though. + MessageQueueMessage* mqmMessage = + dynamic_cast(message); + if(message != nullptr) { + targetQueue->messageQueue.push(*mqmMessage); + } + else { + sif::error << "MessageQueue::sendMessageFromMessageQueue: Message" + "is not MessageQueueMessage!" << std::endl; + } + + } + else { + return MessageQueueIF::FULL; + } + message->setSender(sentFrom); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t MessageQueue::lockQueue(dur_millis_t lockTimeout) { + return queueLock->lockMutex(lockTimeout); +} + +ReturnValue_t MessageQueue::unlockQueue() { + return queueLock->unlockMutex(); +} diff --git a/osal/host/MessageQueue.h b/osal/host/MessageQueue.h index 7fc77f7a..d2da2402 100644 --- a/osal/host/MessageQueue.h +++ b/osal/host/MessageQueue.h @@ -1,230 +1,230 @@ -#ifndef FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ -#define FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ - -#include -#include -#include -#include -#include - -#include -#include - -/** - * @brief This class manages sending and receiving of - * message queue messages. - * @details - * Message queues are used to pass asynchronous messages between processes. - * They work like post boxes, where all incoming messages are stored in FIFO - * order. This class creates a new receiving queue and provides methods to fetch - * received messages. Being a child of MessageQueueSender, this class also - * provides methods to send a message to a user-defined or a default destination. - * In addition it also provides a reply method to answer to the queue it - * received its last message from. - * - * The MessageQueue should be used as "post box" for a single owning object. - * So all message queue communication is "n-to-one". - * For creating the queue, as well as sending and receiving messages, the class - * makes use of the operating system calls provided. - * - * Please keep in mind that FreeRTOS offers different calls for message queue - * operations if called from an ISR. - * For now, the system context needs to be switched manually. - * @ingroup osal - * @ingroup message_queue - */ -class MessageQueue : public MessageQueueIF { - friend class MessageQueueSenderIF; -public: - /** - * @brief The constructor initializes and configures the message queue. - * @details - * By making use of the according operating system call, a message queue is - * created and initialized. The message depth - the maximum number of - * messages to be buffered - may be set with the help of a parameter, - * whereas the message size is automatically set to the maximum message - * queue message size. The operating system sets the message queue id, or - * in case of failure, it is set to zero. - * @param message_depth - * The number of messages to be buffered before passing an error to the - * sender. Default is three. - * @param max_message_size - * With this parameter, the maximum message size can be adjusted. - * This should be left default. - */ - MessageQueue(size_t messageDepth = 3, - size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE); - - /** Copying message queues forbidden */ - MessageQueue(const MessageQueue&) = delete; - MessageQueue& operator=(const MessageQueue&) = delete; - - /** - * @brief The destructor deletes the formerly created message queue. - * @details This is accomplished by using the delete call provided - * by the operating system. - */ - virtual ~MessageQueue(); - - /** - * @brief This operation sends a message to the given destination. - * @details It directly uses the sendMessage call of the MessageQueueSender - * parent, but passes its queue id as "sentFrom" parameter. - * @param sendTo This parameter specifies the message queue id of the - * destination message queue. - * @param message A pointer to a previously created message, which is sent. - * @param ignoreFault If set to true, the internal software fault counter - * is not incremented if queue is full. - */ - ReturnValue_t sendMessage(MessageQueueId_t sendTo, - MessageQueueMessageIF* message, bool ignoreFault = false) override; - /** - * @brief This operation sends a message to the default destination. - * @details As in the sendMessage method, this function uses the - * sendToDefault call of the MessageQueueSender parent class and adds its - * queue id as "sentFrom" information. - * @param message A pointer to a previously created message, which is sent. - */ - ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override; - /** - * @brief This operation sends a message to the last communication partner. - * @details This operation simplifies answering an incoming message by using - * the stored lastPartner information as destination. If there was no - * message received yet (i.e. lastPartner is zero), an error code is returned. - * @param message A pointer to a previously created message, which is sent. - */ - ReturnValue_t reply(MessageQueueMessageIF* message) override; - - /** - * @brief With the sendMessage call, a queue message is sent to a - * receiving queue. - * @details - * This method takes the message provided, adds the sentFrom information and - * passes it on to the destination provided with an operating system call. - * The OS's return value is returned. - * @param sendTo This parameter specifies the message queue id to send - * the message to. - * @param message This is a pointer to a previously created message, - * which is sent. - * @param sentFrom The sentFrom information can be set to inject the - * sender's queue id into the message. This variable is set to zero by - * default. - * @param ignoreFault If set to true, the internal software fault counter - * is not incremented if queue is full. - */ - virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, - MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE, - bool ignoreFault = false) override; - - /** - * @brief The sendToDefault method sends a queue message to the default - * destination. - * @details - * In all other aspects, it works identical to the sendMessage method. - * @param message This is a pointer to a previously created message, - * which is sent. - * @param sentFrom The sentFrom information can be set to inject the - * sender's queue id into the message. This variable is set to zero by - * default. - */ - virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message, - MessageQueueId_t sentFrom = NO_QUEUE, - bool ignoreFault = false) override; - - /** - * @brief This function reads available messages from the message queue - * and returns the sender. - * @details - * It works identically to the other receiveMessage call, but in addition - * returns the sender's queue id. - * @param message A pointer to a message in which the received data is stored. - * @param receivedFrom A pointer to a queue id in which the sender's id is stored. - */ - ReturnValue_t receiveMessage(MessageQueueMessageIF* message, - MessageQueueId_t *receivedFrom) override; - - /** - * @brief This function reads available messages from the message queue. - * @details - * If data is available it is stored in the passed message pointer. - * The message's original content is overwritten and the sendFrom - * information is stored in the lastPartner attribute. Else, the lastPartner - * information remains untouched, the message's content is cleared and the - * function returns immediately. - * @param message A pointer to a message in which the received data is stored. - */ - ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override; - /** - * Deletes all pending messages in the queue. - * @param count The number of flushed messages. - * @return RETURN_OK on success. - */ - ReturnValue_t flush(uint32_t* count) override; - /** - * @brief This method returns the message queue id of the last - * communication partner. - */ - MessageQueueId_t getLastPartner() const override; - /** - * @brief This method returns the message queue id of this class's - * message queue. - */ - MessageQueueId_t getId() const override; - - /** - * @brief This method is a simple setter for the default destination. - */ - void setDefaultDestination(MessageQueueId_t defaultDestination) override; - /** - * @brief This method is a simple getter for the default destination. - */ - MessageQueueId_t getDefaultDestination() const override; - - bool isDefaultDestinationSet() const override; - - ReturnValue_t lockQueue(dur_millis_t lockTimeout); - ReturnValue_t unlockQueue(); -protected: - /** - * @brief Implementation to be called from any send Call within - * MessageQueue and MessageQueueSenderIF. - * @details - * This method takes the message provided, adds the sentFrom information and - * passes it on to the destination provided with an operating system call. - * The OS's return value is returned. - * @param sendTo - * This parameter specifies the message queue id to send the message to. - * @param message - * This is a pointer to a previously created message, which is sent. - * @param sentFrom - * The sentFrom information can be set to inject the sender's queue id into - * the message. This variable is set to zero by default. - * @param ignoreFault - * If set to true, the internal software fault counter is not incremented - * if queue is full. - * @param context Specify whether call is made from task or from an ISR. - */ - static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo, - MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE, - bool ignoreFault=false); - - //static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault); - -private: - std::queue messageQueue; - /** - * @brief The class stores the queue id it got assigned. - * If initialization fails, the queue id is set to zero. - */ - MessageQueueId_t mqId = 0; - size_t messageSize = 0; - size_t messageDepth = 0; - - MutexIF* queueLock; - - bool defaultDestinationSet = false; - MessageQueueId_t defaultDestination = 0; - MessageQueueId_t lastPartner = 0; -}; - -#endif /* FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ */ +#ifndef FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ +#define FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ + +#include "../../internalError/InternalErrorReporterIF.h" +#include "../../ipc/MessageQueueIF.h" +#include "../../ipc/MessageQueueMessage.h" +#include "../../ipc/MutexIF.h" +#include "../../timemanager/Clock.h" + +#include +#include + +/** + * @brief This class manages sending and receiving of + * message queue messages. + * @details + * Message queues are used to pass asynchronous messages between processes. + * They work like post boxes, where all incoming messages are stored in FIFO + * order. This class creates a new receiving queue and provides methods to fetch + * received messages. Being a child of MessageQueueSender, this class also + * provides methods to send a message to a user-defined or a default destination. + * In addition it also provides a reply method to answer to the queue it + * received its last message from. + * + * The MessageQueue should be used as "post box" for a single owning object. + * So all message queue communication is "n-to-one". + * For creating the queue, as well as sending and receiving messages, the class + * makes use of the operating system calls provided. + * + * Please keep in mind that FreeRTOS offers different calls for message queue + * operations if called from an ISR. + * For now, the system context needs to be switched manually. + * @ingroup osal + * @ingroup message_queue + */ +class MessageQueue : public MessageQueueIF { + friend class MessageQueueSenderIF; +public: + /** + * @brief The constructor initializes and configures the message queue. + * @details + * By making use of the according operating system call, a message queue is + * created and initialized. The message depth - the maximum number of + * messages to be buffered - may be set with the help of a parameter, + * whereas the message size is automatically set to the maximum message + * queue message size. The operating system sets the message queue id, or + * in case of failure, it is set to zero. + * @param message_depth + * The number of messages to be buffered before passing an error to the + * sender. Default is three. + * @param max_message_size + * With this parameter, the maximum message size can be adjusted. + * This should be left default. + */ + MessageQueue(size_t messageDepth = 3, + size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE); + + /** Copying message queues forbidden */ + MessageQueue(const MessageQueue&) = delete; + MessageQueue& operator=(const MessageQueue&) = delete; + + /** + * @brief The destructor deletes the formerly created message queue. + * @details This is accomplished by using the delete call provided + * by the operating system. + */ + virtual ~MessageQueue(); + + /** + * @brief This operation sends a message to the given destination. + * @details It directly uses the sendMessage call of the MessageQueueSender + * parent, but passes its queue id as "sentFrom" parameter. + * @param sendTo This parameter specifies the message queue id of the + * destination message queue. + * @param message A pointer to a previously created message, which is sent. + * @param ignoreFault If set to true, the internal software fault counter + * is not incremented if queue is full. + */ + ReturnValue_t sendMessage(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, bool ignoreFault = false) override; + /** + * @brief This operation sends a message to the default destination. + * @details As in the sendMessage method, this function uses the + * sendToDefault call of the MessageQueueSender parent class and adds its + * queue id as "sentFrom" information. + * @param message A pointer to a previously created message, which is sent. + */ + ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override; + /** + * @brief This operation sends a message to the last communication partner. + * @details This operation simplifies answering an incoming message by using + * the stored lastPartner information as destination. If there was no + * message received yet (i.e. lastPartner is zero), an error code is returned. + * @param message A pointer to a previously created message, which is sent. + */ + ReturnValue_t reply(MessageQueueMessageIF* message) override; + + /** + * @brief With the sendMessage call, a queue message is sent to a + * receiving queue. + * @details + * This method takes the message provided, adds the sentFrom information and + * passes it on to the destination provided with an operating system call. + * The OS's return value is returned. + * @param sendTo This parameter specifies the message queue id to send + * the message to. + * @param message This is a pointer to a previously created message, + * which is sent. + * @param sentFrom The sentFrom information can be set to inject the + * sender's queue id into the message. This variable is set to zero by + * default. + * @param ignoreFault If set to true, the internal software fault counter + * is not incremented if queue is full. + */ + virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE, + bool ignoreFault = false) override; + + /** + * @brief The sendToDefault method sends a queue message to the default + * destination. + * @details + * In all other aspects, it works identical to the sendMessage method. + * @param message This is a pointer to a previously created message, + * which is sent. + * @param sentFrom The sentFrom information can be set to inject the + * sender's queue id into the message. This variable is set to zero by + * default. + */ + virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message, + MessageQueueId_t sentFrom = NO_QUEUE, + bool ignoreFault = false) override; + + /** + * @brief This function reads available messages from the message queue + * and returns the sender. + * @details + * It works identically to the other receiveMessage call, but in addition + * returns the sender's queue id. + * @param message A pointer to a message in which the received data is stored. + * @param receivedFrom A pointer to a queue id in which the sender's id is stored. + */ + ReturnValue_t receiveMessage(MessageQueueMessageIF* message, + MessageQueueId_t *receivedFrom) override; + + /** + * @brief This function reads available messages from the message queue. + * @details + * If data is available it is stored in the passed message pointer. + * The message's original content is overwritten and the sendFrom + * information is stored in the lastPartner attribute. Else, the lastPartner + * information remains untouched, the message's content is cleared and the + * function returns immediately. + * @param message A pointer to a message in which the received data is stored. + */ + ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override; + /** + * Deletes all pending messages in the queue. + * @param count The number of flushed messages. + * @return RETURN_OK on success. + */ + ReturnValue_t flush(uint32_t* count) override; + /** + * @brief This method returns the message queue id of the last + * communication partner. + */ + MessageQueueId_t getLastPartner() const override; + /** + * @brief This method returns the message queue id of this class's + * message queue. + */ + MessageQueueId_t getId() const override; + + /** + * @brief This method is a simple setter for the default destination. + */ + void setDefaultDestination(MessageQueueId_t defaultDestination) override; + /** + * @brief This method is a simple getter for the default destination. + */ + MessageQueueId_t getDefaultDestination() const override; + + bool isDefaultDestinationSet() const override; + + ReturnValue_t lockQueue(dur_millis_t lockTimeout); + ReturnValue_t unlockQueue(); +protected: + /** + * @brief Implementation to be called from any send Call within + * MessageQueue and MessageQueueSenderIF. + * @details + * This method takes the message provided, adds the sentFrom information and + * passes it on to the destination provided with an operating system call. + * The OS's return value is returned. + * @param sendTo + * This parameter specifies the message queue id to send the message to. + * @param message + * This is a pointer to a previously created message, which is sent. + * @param sentFrom + * The sentFrom information can be set to inject the sender's queue id into + * the message. This variable is set to zero by default. + * @param ignoreFault + * If set to true, the internal software fault counter is not incremented + * if queue is full. + * @param context Specify whether call is made from task or from an ISR. + */ + static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE, + bool ignoreFault=false); + + //static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault); + +private: + std::queue messageQueue; + /** + * @brief The class stores the queue id it got assigned. + * If initialization fails, the queue id is set to zero. + */ + MessageQueueId_t mqId = 0; + size_t messageSize = 0; + size_t messageDepth = 0; + + MutexIF* queueLock; + + bool defaultDestinationSet = false; + MessageQueueId_t defaultDestination = 0; + MessageQueueId_t lastPartner = 0; +}; + +#endif /* FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ */ diff --git a/osal/host/Mutex.cpp b/osal/host/Mutex.cpp index 03948c4c..28768507 100644 --- a/osal/host/Mutex.cpp +++ b/osal/host/Mutex.cpp @@ -1,40 +1,40 @@ -#include -#include - -const uint32_t MutexIF::POLLING = 0; -const uint32_t MutexIF::BLOCKING = 0xffffffff; - -ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { - if(timeoutMs == MutexIF::BLOCKING) { - mutex.lock(); - locked = true; - return HasReturnvaluesIF::RETURN_OK; - } - else if(timeoutMs == MutexIF::POLLING) { - if(mutex.try_lock()) { - locked = true; - return HasReturnvaluesIF::RETURN_OK; - } - } - else if(timeoutMs > MutexIF::POLLING){ - auto chronoMs = std::chrono::milliseconds(timeoutMs); - if(mutex.try_lock_for(chronoMs)) { - locked = true; - return HasReturnvaluesIF::RETURN_OK; - } - } - return MutexIF::MUTEX_TIMEOUT; -} - -ReturnValue_t Mutex::unlockMutex() { - if(not locked) { - return MutexIF::CURR_THREAD_DOES_NOT_OWN_MUTEX; - } - mutex.unlock(); - locked = false; - return HasReturnvaluesIF::RETURN_OK; -} - -std::timed_mutex* Mutex::getMutexHandle() { - return &mutex; -} +#include "../../osal/host/Mutex.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +const uint32_t MutexIF::POLLING = 0; +const uint32_t MutexIF::BLOCKING = 0xffffffff; + +ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { + if(timeoutMs == MutexIF::BLOCKING) { + mutex.lock(); + locked = true; + return HasReturnvaluesIF::RETURN_OK; + } + else if(timeoutMs == MutexIF::POLLING) { + if(mutex.try_lock()) { + locked = true; + return HasReturnvaluesIF::RETURN_OK; + } + } + else if(timeoutMs > MutexIF::POLLING){ + auto chronoMs = std::chrono::milliseconds(timeoutMs); + if(mutex.try_lock_for(chronoMs)) { + locked = true; + return HasReturnvaluesIF::RETURN_OK; + } + } + return MutexIF::MUTEX_TIMEOUT; +} + +ReturnValue_t Mutex::unlockMutex() { + if(not locked) { + return MutexIF::CURR_THREAD_DOES_NOT_OWN_MUTEX; + } + mutex.unlock(); + locked = false; + return HasReturnvaluesIF::RETURN_OK; +} + +std::timed_mutex* Mutex::getMutexHandle() { + return &mutex; +} diff --git a/osal/host/Mutex.h b/osal/host/Mutex.h index d882c457..4d49bac7 100644 --- a/osal/host/Mutex.h +++ b/osal/host/Mutex.h @@ -1,28 +1,28 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_MUTEX_H_ -#define FRAMEWORK_OSAL_FREERTOS_MUTEX_H_ - -#include - -#include - -/** - * @brief OS component to implement MUTual EXclusion - * - * @details - * Mutexes are binary semaphores which include a priority inheritance mechanism. - * Documentation: https://www.freertos.org/Real-time-embedded-RTOS-mutexes.html - * @ingroup osal - */ -class Mutex : public MutexIF { -public: - Mutex() = default; - ReturnValue_t lockMutex(uint32_t timeoutMs = MutexIF::BLOCKING) override; - ReturnValue_t unlockMutex() override; - - std::timed_mutex* getMutexHandle(); -private: - bool locked = false; - std::timed_mutex mutex; -}; - -#endif /* FRAMEWORK_FREERTOS_MUTEX_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_MUTEX_H_ +#define FRAMEWORK_OSAL_FREERTOS_MUTEX_H_ + +#include "../../ipc/MutexIF.h" + +#include + +/** + * @brief OS component to implement MUTual EXclusion + * + * @details + * Mutexes are binary semaphores which include a priority inheritance mechanism. + * Documentation: https://www.freertos.org/Real-time-embedded-RTOS-mutexes.html + * @ingroup osal + */ +class Mutex : public MutexIF { +public: + Mutex() = default; + ReturnValue_t lockMutex(uint32_t timeoutMs = MutexIF::BLOCKING) override; + ReturnValue_t unlockMutex() override; + + std::timed_mutex* getMutexHandle(); +private: + bool locked = false; + std::timed_mutex mutex; +}; + +#endif /* FRAMEWORK_FREERTOS_MUTEX_H_ */ diff --git a/osal/host/MutexFactory.cpp b/osal/host/MutexFactory.cpp index 25d9fa46..284ce59f 100644 --- a/osal/host/MutexFactory.cpp +++ b/osal/host/MutexFactory.cpp @@ -1,28 +1,28 @@ -#include -#include - -//TODO: Different variant than the lazy loading in QueueFactory. -//What's better and why? -> one is on heap the other on bss/data -//MutexFactory* MutexFactory::factoryInstance = new MutexFactory(); -MutexFactory* MutexFactory::factoryInstance = nullptr; - -MutexFactory::MutexFactory() { -} - -MutexFactory::~MutexFactory() { -} - -MutexFactory* MutexFactory::instance() { - if (factoryInstance == nullptr){ - factoryInstance = new MutexFactory(); - } - return MutexFactory::factoryInstance; -} - -MutexIF* MutexFactory::createMutex() { - return new Mutex(); -} - -void MutexFactory::deleteMutex(MutexIF* mutex) { - delete mutex; -} +#include "../../ipc/MutexFactory.h" +#include "../../osal/host/Mutex.h" + +//TODO: Different variant than the lazy loading in QueueFactory. +//What's better and why? -> one is on heap the other on bss/data +//MutexFactory* MutexFactory::factoryInstance = new MutexFactory(); +MutexFactory* MutexFactory::factoryInstance = nullptr; + +MutexFactory::MutexFactory() { +} + +MutexFactory::~MutexFactory() { +} + +MutexFactory* MutexFactory::instance() { + if (factoryInstance == nullptr){ + factoryInstance = new MutexFactory(); + } + return MutexFactory::factoryInstance; +} + +MutexIF* MutexFactory::createMutex() { + return new Mutex(); +} + +void MutexFactory::deleteMutex(MutexIF* mutex) { + delete mutex; +} diff --git a/osal/host/PeriodicTask.cpp b/osal/host/PeriodicTask.cpp index 1a5024ab..c4cf9f56 100644 --- a/osal/host/PeriodicTask.cpp +++ b/osal/host/PeriodicTask.cpp @@ -1,176 +1,176 @@ -#include -#include -#include - -#include -#include - -#include -#include - -#if defined(WIN32) -#include -#elif defined(LINUX) -#include -#endif - -PeriodicTask::PeriodicTask(const char *name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod setPeriod, - void (*setDeadlineMissedFunc)()) : - started(false), taskName(name), period(setPeriod), - deadlineMissedFunc(setDeadlineMissedFunc) { - // It is propably possible to set task priorities by using the native - // task handles for Windows / Linux - mainThread = std::thread(&PeriodicTask::taskEntryPoint, this, this); -#if defined(WIN32) - /* List of possible priority classes: - * https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ - * nf-processthreadsapi-setpriorityclass - * And respective thread priority numbers: - * https://docs.microsoft.com/en-us/windows/ - * win32/procthread/scheduling-priorities */ - int result = SetPriorityClass( - reinterpret_cast(mainThread.native_handle()), - ABOVE_NORMAL_PRIORITY_CLASS); - if(result != 0) { - sif::error << "PeriodicTask: Windows SetPriorityClass failed with code " - << GetLastError() << std::endl; - } - result = SetThreadPriority( - reinterpret_cast(mainThread.native_handle()), - THREAD_PRIORITY_NORMAL); - if(result != 0) { - sif::error << "PeriodicTask: Windows SetPriorityClass failed with code " - << GetLastError() << std::endl; - } -#elif defined(LINUX) - // we can just copy and paste the code from linux here. -#endif -} - -PeriodicTask::~PeriodicTask(void) { - //Do not delete objects, we were responsible for ptrs only. - terminateThread = true; - if(mainThread.joinable()) { - mainThread.join(); - } - delete this; -} - -void PeriodicTask::taskEntryPoint(void* argument) { - PeriodicTask *originalTask(reinterpret_cast(argument)); - - - if (not originalTask->started) { - // we have to suspend/block here until the task is started. - // if semaphores are implemented, use them here. - std::unique_lock lock(initMutex); - initCondition.wait(lock); - } - - this->taskFunctionality(); - sif::debug << "PeriodicTask::taskEntryPoint: " - "Returned from taskFunctionality." << std::endl; -} - -ReturnValue_t PeriodicTask::startTask() { - started = true; - - // Notify task to start. - std::lock_guard lock(initMutex); - initCondition.notify_one(); - - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) { - std::this_thread::sleep_for(std::chrono::milliseconds(ms)); - return HasReturnvaluesIF::RETURN_OK; -} - -void PeriodicTask::taskFunctionality() { - std::chrono::milliseconds periodChrono(static_cast(period*1000)); - auto currentStartTime { - std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()) - }; - auto nextStartTime{ currentStartTime }; - - /* Enter the loop that defines the task behavior. */ - for (;;) { - if(terminateThread.load()) { - break; - } - for (ObjectList::iterator it = objectList.begin(); - it != objectList.end(); ++it) { - (*it)->performOperation(); - } - if(not delayForInterval(¤tStartTime, periodChrono)) { - sif::warning << "PeriodicTask: " << taskName << - " missed deadline!\n" << std::flush; - if(deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); - } - } - } -} - -ReturnValue_t PeriodicTask::addComponent(object_id_t object) { - ExecutableObjectIF* newObject = objectManager->get( - object); - if (newObject == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - objectList.push_back(newObject); - return HasReturnvaluesIF::RETURN_OK; -} - -uint32_t PeriodicTask::getPeriodMs() const { - return period * 1000; -} - -bool PeriodicTask::delayForInterval(chron_ms* previousWakeTimeMs, - const chron_ms interval) { - bool shouldDelay = false; - //Get current wakeup time - auto currentStartTime = - std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()); - /* Generate the tick time at which the task wants to wake. */ - auto nextTimeToWake_ms = (*previousWakeTimeMs) + interval; - - if (currentStartTime < *previousWakeTimeMs) { - /* The tick count has overflowed since this function was - lasted called. In this case the only time we should ever - actually delay is if the wake time has also overflowed, - and the wake time is greater than the tick time. When this - is the case it is as if neither time had overflowed. */ - if ((nextTimeToWake_ms < *previousWakeTimeMs) - && (nextTimeToWake_ms > currentStartTime)) { - shouldDelay = true; - } - } else { - /* The tick time has not overflowed. In this case we will - delay if either the wake time has overflowed, and/or the - tick time is less than the wake time. */ - if ((nextTimeToWake_ms < *previousWakeTimeMs) - || (nextTimeToWake_ms > currentStartTime)) { - shouldDelay = true; - } - } - - /* Update the wake time ready for the next call. */ - - (*previousWakeTimeMs) = nextTimeToWake_ms; - - if (shouldDelay) { - auto sleepTime = std::chrono::duration_cast( - nextTimeToWake_ms - currentStartTime); - std::this_thread::sleep_for(sleepTime); - return true; - } - //We are shifting the time in case the deadline was missed like rtems - (*previousWakeTimeMs) = currentStartTime; - return false; - -} +#include "../../ipc/MutexFactory.h" +#include "../../osal/host/Mutex.h" +#include "../../osal/host/PeriodicTask.h" + +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../tasks/ExecutableObjectIF.h" + +#include +#include + +#if defined(WIN32) +#include +#elif defined(LINUX) +#include +#endif + +PeriodicTask::PeriodicTask(const char *name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod setPeriod, + void (*setDeadlineMissedFunc)()) : + started(false), taskName(name), period(setPeriod), + deadlineMissedFunc(setDeadlineMissedFunc) { + // It is propably possible to set task priorities by using the native + // task handles for Windows / Linux + mainThread = std::thread(&PeriodicTask::taskEntryPoint, this, this); +#if defined(WIN32) + /* List of possible priority classes: + * https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ + * nf-processthreadsapi-setpriorityclass + * And respective thread priority numbers: + * https://docs.microsoft.com/en-us/windows/ + * win32/procthread/scheduling-priorities */ + int result = SetPriorityClass( + reinterpret_cast(mainThread.native_handle()), + ABOVE_NORMAL_PRIORITY_CLASS); + if(result != 0) { + sif::error << "PeriodicTask: Windows SetPriorityClass failed with code " + << GetLastError() << std::endl; + } + result = SetThreadPriority( + reinterpret_cast(mainThread.native_handle()), + THREAD_PRIORITY_NORMAL); + if(result != 0) { + sif::error << "PeriodicTask: Windows SetPriorityClass failed with code " + << GetLastError() << std::endl; + } +#elif defined(LINUX) + // we can just copy and paste the code from linux here. +#endif +} + +PeriodicTask::~PeriodicTask(void) { + //Do not delete objects, we were responsible for ptrs only. + terminateThread = true; + if(mainThread.joinable()) { + mainThread.join(); + } + delete this; +} + +void PeriodicTask::taskEntryPoint(void* argument) { + PeriodicTask *originalTask(reinterpret_cast(argument)); + + + if (not originalTask->started) { + // we have to suspend/block here until the task is started. + // if semaphores are implemented, use them here. + std::unique_lock lock(initMutex); + initCondition.wait(lock); + } + + this->taskFunctionality(); + sif::debug << "PeriodicTask::taskEntryPoint: " + "Returned from taskFunctionality." << std::endl; +} + +ReturnValue_t PeriodicTask::startTask() { + started = true; + + // Notify task to start. + std::lock_guard lock(initMutex); + initCondition.notify_one(); + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) { + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); + return HasReturnvaluesIF::RETURN_OK; +} + +void PeriodicTask::taskFunctionality() { + std::chrono::milliseconds periodChrono(static_cast(period*1000)); + auto currentStartTime { + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + }; + auto nextStartTime{ currentStartTime }; + + /* Enter the loop that defines the task behavior. */ + for (;;) { + if(terminateThread.load()) { + break; + } + for (ObjectList::iterator it = objectList.begin(); + it != objectList.end(); ++it) { + (*it)->performOperation(); + } + if(not delayForInterval(¤tStartTime, periodChrono)) { + sif::warning << "PeriodicTask: " << taskName << + " missed deadline!\n" << std::flush; + if(deadlineMissedFunc != nullptr) { + this->deadlineMissedFunc(); + } + } + } +} + +ReturnValue_t PeriodicTask::addComponent(object_id_t object) { + ExecutableObjectIF* newObject = objectManager->get( + object); + if (newObject == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + objectList.push_back(newObject); + return HasReturnvaluesIF::RETURN_OK; +} + +uint32_t PeriodicTask::getPeriodMs() const { + return period * 1000; +} + +bool PeriodicTask::delayForInterval(chron_ms* previousWakeTimeMs, + const chron_ms interval) { + bool shouldDelay = false; + //Get current wakeup time + auto currentStartTime = + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()); + /* Generate the tick time at which the task wants to wake. */ + auto nextTimeToWake_ms = (*previousWakeTimeMs) + interval; + + if (currentStartTime < *previousWakeTimeMs) { + /* The tick count has overflowed since this function was + lasted called. In this case the only time we should ever + actually delay is if the wake time has also overflowed, + and the wake time is greater than the tick time. When this + is the case it is as if neither time had overflowed. */ + if ((nextTimeToWake_ms < *previousWakeTimeMs) + && (nextTimeToWake_ms > currentStartTime)) { + shouldDelay = true; + } + } else { + /* The tick time has not overflowed. In this case we will + delay if either the wake time has overflowed, and/or the + tick time is less than the wake time. */ + if ((nextTimeToWake_ms < *previousWakeTimeMs) + || (nextTimeToWake_ms > currentStartTime)) { + shouldDelay = true; + } + } + + /* Update the wake time ready for the next call. */ + + (*previousWakeTimeMs) = nextTimeToWake_ms; + + if (shouldDelay) { + auto sleepTime = std::chrono::duration_cast( + nextTimeToWake_ms - currentStartTime); + std::this_thread::sleep_for(sleepTime); + return true; + } + //We are shifting the time in case the deadline was missed like rtems + (*previousWakeTimeMs) = currentStartTime; + return false; + +} diff --git a/osal/host/PeriodicTask.h b/osal/host/PeriodicTask.h index d97bf089..7eb768cb 100644 --- a/osal/host/PeriodicTask.h +++ b/osal/host/PeriodicTask.h @@ -1,123 +1,123 @@ -#ifndef FRAMEWORK_OSAL_HOST_PERIODICTASK_H_ -#define FRAMEWORK_OSAL_HOST_PERIODICTASK_H_ - -#include -#include -#include - -#include -#include -#include -#include - -class ExecutableObjectIF; - -/** - * @brief This class represents a specialized task for - * periodic activities of multiple objects. - * @details - * - * @ingroup task_handling - */ -class PeriodicTask: public PeriodicTaskIF { -public: - /** - * @brief Standard constructor of the class. - * @details - * The class is initialized without allocated objects. These need to be - * added with #addComponent. - * @param priority - * @param stack_size - * @param setPeriod - * @param setDeadlineMissedFunc - * The function pointer to the deadline missed function that shall be - * assigned. - */ - PeriodicTask(const char *name, TaskPriority setPriority, TaskStackSize setStack, - TaskPeriod setPeriod,void (*setDeadlineMissedFunc)()); - /** - * @brief Currently, the executed object's lifetime is not coupled with - * the task object's lifetime, so the destructor is empty. - */ - virtual ~PeriodicTask(void); - - /** - * @brief The method to start the task. - * @details The method starts the task with the respective system call. - * Entry point is the taskEntryPoint method described below. - * The address of the task object is passed as an argument - * to the system call. - */ - ReturnValue_t startTask(void); - /** - * Adds an object to the list of objects to be executed. - * The objects are executed in the order added. - * @param object Id of the object to add. - * @return - * -@c RETURN_OK on success - * -@c RETURN_FAILED if the object could not be added. - */ - ReturnValue_t addComponent(object_id_t object); - - uint32_t getPeriodMs() const; - - ReturnValue_t sleepFor(uint32_t ms); - -protected: - using chron_ms = std::chrono::milliseconds; - bool started; - //!< Typedef for the List of objects. - typedef std::vector ObjectList; - std::thread mainThread; - std::atomic terminateThread = false; - - /** - * @brief This attribute holds a list of objects to be executed. - */ - ObjectList objectList; - - std::condition_variable initCondition; - std::mutex initMutex; - std::string taskName; - /** - * @brief The period of the task. - * @details - * The period determines the frequency of the task's execution. - * It is expressed in clock ticks. - */ - TaskPeriod period; - /** - * @brief The pointer to the deadline-missed function. - * @details - * This pointer stores the function that is executed if the task's deadline - * is missed. So, each may react individually on a timing failure. - * The pointer may be NULL, then nothing happens on missing the deadline. - * The deadline is equal to the next execution of the periodic task. - */ - void (*deadlineMissedFunc)(void); - /** - * @brief This is the function executed in the new task's context. - * @details - * It converts the argument back to the thread object type and copies the - * class instance to the task context. - * The taskFunctionality method is called afterwards. - * @param A pointer to the task object itself is passed as argument. - */ - - void taskEntryPoint(void* argument); - /** - * @brief The function containing the actual functionality of the task. - * @details - * The method sets and starts the task's period, then enters a loop that is - * repeated as long as the isRunning attribute is true. Within the loop, - * all performOperation methods of the added objects are called. Afterwards - * the checkAndRestartPeriod system call blocks the task until the next - * period. On missing the deadline, the deadlineMissedFunction is executed. - */ - void taskFunctionality(void); - - bool delayForInterval(chron_ms * previousWakeTimeMs, - const chron_ms interval); -}; - -#endif /* PERIODICTASK_H_ */ +#ifndef FRAMEWORK_OSAL_HOST_PERIODICTASK_H_ +#define FRAMEWORK_OSAL_HOST_PERIODICTASK_H_ + +#include "../../objectmanager/ObjectManagerIF.h" +#include "../../tasks/PeriodicTaskIF.h" +#include "../../tasks/Typedef.h" + +#include +#include +#include +#include + +class ExecutableObjectIF; + +/** + * @brief This class represents a specialized task for + * periodic activities of multiple objects. + * @details + * + * @ingroup task_handling + */ +class PeriodicTask: public PeriodicTaskIF { +public: + /** + * @brief Standard constructor of the class. + * @details + * The class is initialized without allocated objects. These need to be + * added with #addComponent. + * @param priority + * @param stack_size + * @param setPeriod + * @param setDeadlineMissedFunc + * The function pointer to the deadline missed function that shall be + * assigned. + */ + PeriodicTask(const char *name, TaskPriority setPriority, TaskStackSize setStack, + TaskPeriod setPeriod,void (*setDeadlineMissedFunc)()); + /** + * @brief Currently, the executed object's lifetime is not coupled with + * the task object's lifetime, so the destructor is empty. + */ + virtual ~PeriodicTask(void); + + /** + * @brief The method to start the task. + * @details The method starts the task with the respective system call. + * Entry point is the taskEntryPoint method described below. + * The address of the task object is passed as an argument + * to the system call. + */ + ReturnValue_t startTask(void); + /** + * Adds an object to the list of objects to be executed. + * The objects are executed in the order added. + * @param object Id of the object to add. + * @return + * -@c RETURN_OK on success + * -@c RETURN_FAILED if the object could not be added. + */ + ReturnValue_t addComponent(object_id_t object); + + uint32_t getPeriodMs() const; + + ReturnValue_t sleepFor(uint32_t ms); + +protected: + using chron_ms = std::chrono::milliseconds; + bool started; + //!< Typedef for the List of objects. + typedef std::vector ObjectList; + std::thread mainThread; + std::atomic terminateThread = false; + + /** + * @brief This attribute holds a list of objects to be executed. + */ + ObjectList objectList; + + std::condition_variable initCondition; + std::mutex initMutex; + std::string taskName; + /** + * @brief The period of the task. + * @details + * The period determines the frequency of the task's execution. + * It is expressed in clock ticks. + */ + TaskPeriod period; + /** + * @brief The pointer to the deadline-missed function. + * @details + * This pointer stores the function that is executed if the task's deadline + * is missed. So, each may react individually on a timing failure. + * The pointer may be NULL, then nothing happens on missing the deadline. + * The deadline is equal to the next execution of the periodic task. + */ + void (*deadlineMissedFunc)(void); + /** + * @brief This is the function executed in the new task's context. + * @details + * It converts the argument back to the thread object type and copies the + * class instance to the task context. + * The taskFunctionality method is called afterwards. + * @param A pointer to the task object itself is passed as argument. + */ + + void taskEntryPoint(void* argument); + /** + * @brief The function containing the actual functionality of the task. + * @details + * The method sets and starts the task's period, then enters a loop that is + * repeated as long as the isRunning attribute is true. Within the loop, + * all performOperation methods of the added objects are called. Afterwards + * the checkAndRestartPeriod system call blocks the task until the next + * period. On missing the deadline, the deadlineMissedFunction is executed. + */ + void taskFunctionality(void); + + bool delayForInterval(chron_ms * previousWakeTimeMs, + const chron_ms interval); +}; + +#endif /* PERIODICTASK_H_ */ diff --git a/osal/host/QueueFactory.cpp b/osal/host/QueueFactory.cpp index 225bb8c7..052671ca 100644 --- a/osal/host/QueueFactory.cpp +++ b/osal/host/QueueFactory.cpp @@ -1,41 +1,41 @@ -#include -#include -#include -#include - -QueueFactory* QueueFactory::factoryInstance = nullptr; - - -ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessageIF* message, MessageQueueId_t sentFrom, - bool ignoreFault) { - return MessageQueue::sendMessageFromMessageQueue(sendTo,message, - sentFrom,ignoreFault); - return HasReturnvaluesIF::RETURN_OK; -} - -QueueFactory* QueueFactory::instance() { - if (factoryInstance == nullptr) { - factoryInstance = new QueueFactory; - } - return factoryInstance; -} - -QueueFactory::QueueFactory() { -} - -QueueFactory::~QueueFactory() { -} - -MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, - size_t maxMessageSize) { - // A thread-safe queue can be implemented by using a combination - // of std::queue and std::mutex. This uses dynamic memory allocation - // which could be alleviated by using a custom allocator, external library - // (etl::queue) or simply using std::queue, we're on a host machine anyway. - return new MessageQueue(messageDepth, maxMessageSize); -} - -void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { - delete queue; -} +#include "../../ipc/QueueFactory.h" +#include "../../osal/host/MessageQueue.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include + +QueueFactory* QueueFactory::factoryInstance = nullptr; + + +ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + return MessageQueue::sendMessageFromMessageQueue(sendTo,message, + sentFrom,ignoreFault); + return HasReturnvaluesIF::RETURN_OK; +} + +QueueFactory* QueueFactory::instance() { + if (factoryInstance == nullptr) { + factoryInstance = new QueueFactory; + } + return factoryInstance; +} + +QueueFactory::QueueFactory() { +} + +QueueFactory::~QueueFactory() { +} + +MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, + size_t maxMessageSize) { + // A thread-safe queue can be implemented by using a combination + // of std::queue and std::mutex. This uses dynamic memory allocation + // which could be alleviated by using a custom allocator, external library + // (etl::queue) or simply using std::queue, we're on a host machine anyway. + return new MessageQueue(messageDepth, maxMessageSize); +} + +void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { + delete queue; +} diff --git a/osal/host/QueueMapManager.cpp b/osal/host/QueueMapManager.cpp index 89b9a948..35db204e 100644 --- a/osal/host/QueueMapManager.cpp +++ b/osal/host/QueueMapManager.cpp @@ -1,51 +1,51 @@ -#include -#include -#include - -QueueMapManager* QueueMapManager::mqManagerInstance = nullptr; - -QueueMapManager::QueueMapManager() { - mapLock = MutexFactory::instance()->createMutex(); -} - -QueueMapManager* QueueMapManager::instance() { - if (mqManagerInstance == nullptr){ - mqManagerInstance = new QueueMapManager(); - } - return QueueMapManager::mqManagerInstance; -} - -ReturnValue_t QueueMapManager::addMessageQueue( - MessageQueueIF* queueToInsert, MessageQueueId_t* id) { - // Not thread-safe, but it is assumed all message queues are created - // at software initialization now. If this is to be made thread-safe in - // the future, it propably would be sufficient to lock the increment - // operation here - uint32_t currentId = queueCounter++; - auto returnPair = queueMap.emplace(currentId, queueToInsert); - if(not returnPair.second) { - // this should never happen for the atomic variable. - sif::error << "QueueMapManager: This ID is already inside the map!" - << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - if (id != nullptr) { - *id = currentId; - } - return HasReturnvaluesIF::RETURN_OK; -} - -MessageQueueIF* QueueMapManager::getMessageQueue( - MessageQueueId_t messageQueueId) const { - MutexHelper(mapLock, 50); - auto queueIter = queueMap.find(messageQueueId); - if(queueIter != queueMap.end()) { - return queueIter->second; - } - else { - sif::warning << "QueueMapManager::getQueueHandle: The ID" << - messageQueueId << " does not exists in the map" << std::endl; - return nullptr; - } -} - +#include "../../ipc/MutexFactory.h" +#include "../../ipc/MutexHelper.h" +#include "../../osal/host/QueueMapManager.h" + +QueueMapManager* QueueMapManager::mqManagerInstance = nullptr; + +QueueMapManager::QueueMapManager() { + mapLock = MutexFactory::instance()->createMutex(); +} + +QueueMapManager* QueueMapManager::instance() { + if (mqManagerInstance == nullptr){ + mqManagerInstance = new QueueMapManager(); + } + return QueueMapManager::mqManagerInstance; +} + +ReturnValue_t QueueMapManager::addMessageQueue( + MessageQueueIF* queueToInsert, MessageQueueId_t* id) { + // Not thread-safe, but it is assumed all message queues are created + // at software initialization now. If this is to be made thread-safe in + // the future, it propably would be sufficient to lock the increment + // operation here + uint32_t currentId = queueCounter++; + auto returnPair = queueMap.emplace(currentId, queueToInsert); + if(not returnPair.second) { + // this should never happen for the atomic variable. + sif::error << "QueueMapManager: This ID is already inside the map!" + << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if (id != nullptr) { + *id = currentId; + } + return HasReturnvaluesIF::RETURN_OK; +} + +MessageQueueIF* QueueMapManager::getMessageQueue( + MessageQueueId_t messageQueueId) const { + MutexHelper(mapLock, 50); + auto queueIter = queueMap.find(messageQueueId); + if(queueIter != queueMap.end()) { + return queueIter->second; + } + else { + sif::warning << "QueueMapManager::getQueueHandle: The ID" << + messageQueueId << " does not exists in the map" << std::endl; + return nullptr; + } +} + diff --git a/osal/host/QueueMapManager.h b/osal/host/QueueMapManager.h index a2a1b658..acf20389 100644 --- a/osal/host/QueueMapManager.h +++ b/osal/host/QueueMapManager.h @@ -1,47 +1,47 @@ -#ifndef FRAMEWORK_OSAL_HOST_QUEUEMAP_H_ -#define FRAMEWORK_OSAL_HOST_QUEUEMAP_H_ - -#include -#include -#include -#include - -using QueueMap = std::unordered_map; - - -/** - * An internal map to map message queue IDs to message queues. - * This propably should be a singleton.. - */ -class QueueMapManager { -public: - //! Returns the single instance of SemaphoreFactory. - static QueueMapManager* instance(); - - /** - * Insert a message queue into the map and returns a message queue ID - * @param queue The message queue to insert. - * @param id The passed value will be set unless a nullptr is passed - * @return - */ - ReturnValue_t addMessageQueue(MessageQueueIF* queue, MessageQueueId_t* - id = nullptr); - /** - * Get the message queue handle by providing a message queue ID. - * @param messageQueueId - * @return - */ - MessageQueueIF* getMessageQueue(MessageQueueId_t messageQueueId) const; - -private: - //! External instantiation is forbidden. - QueueMapManager(); - uint32_t queueCounter = 1; - MutexIF* mapLock; - QueueMap queueMap; - static QueueMapManager* mqManagerInstance; -}; - - - -#endif /* FRAMEWORK_OSAL_HOST_QUEUEMAP_H_ */ +#ifndef FRAMEWORK_OSAL_HOST_QUEUEMAP_H_ +#define FRAMEWORK_OSAL_HOST_QUEUEMAP_H_ + +#include "../../ipc/MessageQueueSenderIF.h" +#include "../../osal/host/MessageQueue.h" +#include +#include + +using QueueMap = std::unordered_map; + + +/** + * An internal map to map message queue IDs to message queues. + * This propably should be a singleton.. + */ +class QueueMapManager { +public: + //! Returns the single instance of SemaphoreFactory. + static QueueMapManager* instance(); + + /** + * Insert a message queue into the map and returns a message queue ID + * @param queue The message queue to insert. + * @param id The passed value will be set unless a nullptr is passed + * @return + */ + ReturnValue_t addMessageQueue(MessageQueueIF* queue, MessageQueueId_t* + id = nullptr); + /** + * Get the message queue handle by providing a message queue ID. + * @param messageQueueId + * @return + */ + MessageQueueIF* getMessageQueue(MessageQueueId_t messageQueueId) const; + +private: + //! External instantiation is forbidden. + QueueMapManager(); + uint32_t queueCounter = 1; + MutexIF* mapLock; + QueueMap queueMap; + static QueueMapManager* mqManagerInstance; +}; + + + +#endif /* FRAMEWORK_OSAL_HOST_QUEUEMAP_H_ */ diff --git a/osal/host/SemaphoreFactory.cpp b/osal/host/SemaphoreFactory.cpp index 0c077f68..58040428 100644 --- a/osal/host/SemaphoreFactory.cpp +++ b/osal/host/SemaphoreFactory.cpp @@ -1,42 +1,42 @@ -#include -#include -#include -#include - -const uint32_t SemaphoreIF::POLLING = 0; -const uint32_t SemaphoreIF::BLOCKING = 0xFFFFFFFF; - -SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; - -SemaphoreFactory::SemaphoreFactory() { -} - -SemaphoreFactory::~SemaphoreFactory() { - delete factoryInstance; -} - -SemaphoreFactory* SemaphoreFactory::instance() { - if (factoryInstance == nullptr){ - factoryInstance = new SemaphoreFactory(); - } - return SemaphoreFactory::factoryInstance; -} - -SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t arguments) { - // Just gonna wait for full C++20 for now. - sif::error << "SemaphoreFactory: Binary Semaphore not implemented yet." - " Returning nullptr!\n" << std::flush; - return nullptr; -} - -SemaphoreIF* SemaphoreFactory::createCountingSemaphore(const uint8_t maxCount, - uint8_t initCount, uint32_t arguments) { - // Just gonna wait for full C++20 for now. - sif::error << "SemaphoreFactory: Counting Semaphore not implemented yet." - " Returning nullptr!\n" << std::flush; - return nullptr; -} - -void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { - delete semaphore; -} +#include "../../tasks/SemaphoreFactory.h" +#include "../../osal/linux/BinarySemaphore.h" +#include "../../osal/linux/CountingSemaphore.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +const uint32_t SemaphoreIF::POLLING = 0; +const uint32_t SemaphoreIF::BLOCKING = 0xFFFFFFFF; + +SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; + +SemaphoreFactory::SemaphoreFactory() { +} + +SemaphoreFactory::~SemaphoreFactory() { + delete factoryInstance; +} + +SemaphoreFactory* SemaphoreFactory::instance() { + if (factoryInstance == nullptr){ + factoryInstance = new SemaphoreFactory(); + } + return SemaphoreFactory::factoryInstance; +} + +SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t arguments) { + // Just gonna wait for full C++20 for now. + sif::error << "SemaphoreFactory: Binary Semaphore not implemented yet." + " Returning nullptr!\n" << std::flush; + return nullptr; +} + +SemaphoreIF* SemaphoreFactory::createCountingSemaphore(const uint8_t maxCount, + uint8_t initCount, uint32_t arguments) { + // Just gonna wait for full C++20 for now. + sif::error << "SemaphoreFactory: Counting Semaphore not implemented yet." + " Returning nullptr!\n" << std::flush; + return nullptr; +} + +void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { + delete semaphore; +} diff --git a/osal/host/TaskFactory.cpp b/osal/host/TaskFactory.cpp index 9db8ac4d..3f527130 100644 --- a/osal/host/TaskFactory.cpp +++ b/osal/host/TaskFactory.cpp @@ -1,55 +1,55 @@ -#include -#include -#include -#include -#include - -#include - -TaskFactory* TaskFactory::factoryInstance = new TaskFactory(); - -// Will propably not be used for hosted implementation -const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = 0; - -TaskFactory::TaskFactory() { -} - -TaskFactory::~TaskFactory() { -} - -TaskFactory* TaskFactory::instance() { - return TaskFactory::factoryInstance; -} - -PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, - TaskPriority taskPriority_,TaskStackSize stackSize_, - TaskPeriod periodInSeconds_, - TaskDeadlineMissedFunction deadLineMissedFunction_) { - // This is going to be interesting. Time now learn the C++ threading library - // :-) - return new PeriodicTask(name_, taskPriority_, stackSize_, periodInSeconds_, - deadLineMissedFunction_); -} - -FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_, - TaskPriority taskPriority_,TaskStackSize stackSize_, - TaskPeriod periodInSeconds_, - TaskDeadlineMissedFunction deadLineMissedFunction_) { - // This is going to be interesting. Time now learn the C++ threading library - // :-) - return new FixedTimeslotTask(name_, taskPriority_, stackSize_, - periodInSeconds_, deadLineMissedFunction_); -} - -ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) { - // This might block for some time! - delete task; - return HasReturnvaluesIF::RETURN_FAILED; -} - -ReturnValue_t TaskFactory::delayTask(uint32_t delayMs){ - std::this_thread::sleep_for(std::chrono::milliseconds(delayMs)); - return HasReturnvaluesIF::RETURN_OK; -} - - +#include "../../osal/host/FixedTimeslotTask.h" +#include "../../osal/host/PeriodicTask.h" +#include "../../tasks/TaskFactory.h" +#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../tasks/PeriodicTaskIF.h" + +#include + +TaskFactory* TaskFactory::factoryInstance = new TaskFactory(); + +// Will propably not be used for hosted implementation +const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = 0; + +TaskFactory::TaskFactory() { +} + +TaskFactory::~TaskFactory() { +} + +TaskFactory* TaskFactory::instance() { + return TaskFactory::factoryInstance; +} + +PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, + TaskPriority taskPriority_,TaskStackSize stackSize_, + TaskPeriod periodInSeconds_, + TaskDeadlineMissedFunction deadLineMissedFunction_) { + // This is going to be interesting. Time now learn the C++ threading library + // :-) + return new PeriodicTask(name_, taskPriority_, stackSize_, periodInSeconds_, + deadLineMissedFunction_); +} + +FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_, + TaskPriority taskPriority_,TaskStackSize stackSize_, + TaskPeriod periodInSeconds_, + TaskDeadlineMissedFunction deadLineMissedFunction_) { + // This is going to be interesting. Time now learn the C++ threading library + // :-) + return new FixedTimeslotTask(name_, taskPriority_, stackSize_, + periodInSeconds_, deadLineMissedFunction_); +} + +ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) { + // This might block for some time! + delete task; + return HasReturnvaluesIF::RETURN_FAILED; +} + +ReturnValue_t TaskFactory::delayTask(uint32_t delayMs){ + std::this_thread::sleep_for(std::chrono::milliseconds(delayMs)); + return HasReturnvaluesIF::RETURN_OK; +} + + From 2748a8b93b9d6fa9663cea0bd57c94e46d7f0f15 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 26 Aug 2020 17:42:13 +0200 Subject: [PATCH 258/653] added doc to dle encoder --- globalfunctions/DleEncoder.cpp | 219 +++++++++++++++++++-------------- globalfunctions/DleEncoder.h | 104 ++++++++++++---- 2 files changed, 203 insertions(+), 120 deletions(-) diff --git a/globalfunctions/DleEncoder.cpp b/globalfunctions/DleEncoder.cpp index 088c9d80..21dbd2e6 100644 --- a/globalfunctions/DleEncoder.cpp +++ b/globalfunctions/DleEncoder.cpp @@ -1,95 +1,124 @@ -#include "DleEncoder.h" - -DleEncoder::DleEncoder() { -} - -DleEncoder::~DleEncoder() { -} - -ReturnValue_t DleEncoder::decode(const uint8_t *sourceStream, - uint32_t sourceStreamLen, uint32_t *readLen, uint8_t *destStream, - uint32_t maxDestStreamlen, uint32_t *decodedLen) { - uint32_t encodedIndex = 0, decodedIndex = 0; - uint8_t nextByte; - if (*sourceStream != STX) { - return RETURN_FAILED; - } - ++encodedIndex; - while ((encodedIndex < sourceStreamLen) && (decodedIndex < maxDestStreamlen) - && (sourceStream[encodedIndex] != ETX) - && (sourceStream[encodedIndex] != STX)) { - if (sourceStream[encodedIndex] == DLE) { - nextByte = sourceStream[encodedIndex + 1]; - if (nextByte == 0x10) { - destStream[decodedIndex] = nextByte; - } else { - if ((nextByte == 0x42) || (nextByte == 0x43) - || (nextByte == 0x4D)) { - destStream[decodedIndex] = nextByte - 0x40; - } else { - return RETURN_FAILED; - } - } - ++encodedIndex; - } else { - destStream[decodedIndex] = sourceStream[encodedIndex]; - } - ++encodedIndex; - ++decodedIndex; - } - if (sourceStream[encodedIndex] != ETX) { - return RETURN_FAILED; - } else { - *readLen = ++encodedIndex; - *decodedLen = decodedIndex; - return RETURN_OK; - } -} - -ReturnValue_t DleEncoder::encode(const uint8_t* sourceStream, - uint32_t sourceLen, uint8_t* destStream, uint32_t maxDestLen, - uint32_t* encodedLen, bool addStxEtx) { - if (maxDestLen < 2) { - return RETURN_FAILED; - } - uint32_t encodedIndex = 0, sourceIndex = 0; - uint8_t nextByte; - if (addStxEtx) { - destStream[0] = STX; - ++encodedIndex; - } - while ((encodedIndex < maxDestLen) && (sourceIndex < sourceLen)) { - nextByte = sourceStream[sourceIndex]; - if ((nextByte == STX) || (nextByte == ETX) || (nextByte == 0x0D)) { - if (encodedIndex + 1 >= maxDestLen) { - return RETURN_FAILED; - } else { - destStream[encodedIndex] = DLE; - ++encodedIndex; - destStream[encodedIndex] = nextByte + 0x40; - } - } else if (nextByte == DLE) { - if (encodedIndex + 1 >= maxDestLen) { - return RETURN_FAILED; - } else { - destStream[encodedIndex] = DLE; - ++encodedIndex; - destStream[encodedIndex] = DLE; - } - } else { - destStream[encodedIndex] = nextByte; - } - ++encodedIndex; - ++sourceIndex; - } - if ((sourceIndex == sourceLen) && (encodedIndex < maxDestLen)) { - if (addStxEtx) { - destStream[encodedIndex] = ETX; - ++encodedIndex; - } - *encodedLen = encodedIndex; - return RETURN_OK; - } else { - return RETURN_FAILED; - } -} +#include "../globalfunctions/DleEncoder.h" + +DleEncoder::DleEncoder() {} + +DleEncoder::~DleEncoder() {} + +ReturnValue_t DleEncoder::encode(const uint8_t* sourceStream, + size_t sourceLen, uint8_t* destStream, size_t maxDestLen, + size_t* encodedLen, bool addStxEtx) { + if (maxDestLen < 2) { + return STREAM_TOO_SHORT; + } + size_t encodedIndex = 0, sourceIndex = 0; + uint8_t nextByte; + if (addStxEtx) { + destStream[0] = STX_CHAR; + ++encodedIndex; + } + + while (encodedIndex < maxDestLen and sourceIndex < sourceLen) + { + nextByte = sourceStream[sourceIndex]; + // STX, ETX and CR characters in the stream need to be escaped with DLE + if (nextByte == STX_CHAR or nextByte == ETX_CHAR or nextByte == CARRIAGE_RETURN) { + if (encodedIndex + 1 >= maxDestLen) { + return STREAM_TOO_SHORT; + } + else { + destStream[encodedIndex] = DLE_CHAR; + ++encodedIndex; + /* Escaped byte will be actual byte + 0x40. This prevents + * STX, ETX, and carriage return characters from appearing + * in the encoded data stream at all, so when polling an + * encoded stream, the transmission can be stopped at ETX. + * 0x40 was chosen at random with special requirements: + * - Prevent going from one control char to another + * - Prevent overflow for common characters */ + destStream[encodedIndex] = nextByte + 0x40; + } + } + // DLE characters are simply escaped with DLE. + else if (nextByte == DLE_CHAR) { + if (encodedIndex + 1 >= maxDestLen) { + return STREAM_TOO_SHORT; + } + else { + destStream[encodedIndex] = DLE_CHAR; + ++encodedIndex; + destStream[encodedIndex] = DLE_CHAR; + } + } + else { + destStream[encodedIndex] = nextByte; + } + ++encodedIndex; + ++sourceIndex; + } + + if (sourceIndex == sourceLen and encodedIndex < maxDestLen) { + if (addStxEtx) { + destStream[encodedIndex] = ETX_CHAR; + ++encodedIndex; + } + *encodedLen = encodedIndex; + return RETURN_OK; + } + else { + return STREAM_TOO_SHORT; + } +} + +ReturnValue_t DleEncoder::decode(const uint8_t *sourceStream, + size_t sourceStreamLen, size_t *readLen, uint8_t *destStream, + size_t maxDestStreamlen, size_t *decodedLen) { + size_t encodedIndex = 0, decodedIndex = 0; + uint8_t nextByte; + if (*sourceStream != STX_CHAR) { + return DECODING_ERROR; + } + ++encodedIndex; + + while ((encodedIndex < sourceStreamLen) && (decodedIndex < maxDestStreamlen) + && (sourceStream[encodedIndex] != ETX_CHAR) + && (sourceStream[encodedIndex] != STX_CHAR)) { + if (sourceStream[encodedIndex] == DLE_CHAR) { + nextByte = sourceStream[encodedIndex + 1]; + // The next byte is a DLE character that was escaped by another + // DLE character, so we can write it to the destination stream. + if (nextByte == DLE_CHAR) { + destStream[decodedIndex] = nextByte; + } + else { + /* The next byte is a STX, DTX or 0x0D character which + * was escaped by a DLE character. The actual byte was + * also encoded by adding + 0x40 to preven having control chars, + * in the stream at all, so we convert it back. */ + if (nextByte == 0x42 or nextByte == 0x43 or nextByte == 0x4D) { + destStream[decodedIndex] = nextByte - 0x40; + } + else { + return DECODING_ERROR; + } + } + ++encodedIndex; + } + else { + destStream[decodedIndex] = sourceStream[encodedIndex]; + } + + ++encodedIndex; + ++decodedIndex; + } + + if (sourceStream[encodedIndex] != ETX_CHAR) { + *readLen = ++encodedIndex; + return DECODING_ERROR; + } + else { + *readLen = ++encodedIndex; + *decodedLen = decodedIndex; + return RETURN_OK; + } +} + diff --git a/globalfunctions/DleEncoder.h b/globalfunctions/DleEncoder.h index ff3a2727..3c327a55 100644 --- a/globalfunctions/DleEncoder.h +++ b/globalfunctions/DleEncoder.h @@ -1,25 +1,79 @@ -#ifndef DLEENCODER_H_ -#define DLEENCODER_H_ - -#include "../returnvalues/HasReturnvaluesIF.h" - -class DleEncoder: public HasReturnvaluesIF { -private: - DleEncoder(); - virtual ~DleEncoder(); - -public: - static const uint8_t STX = 0x02; - static const uint8_t ETX = 0x03; - static const uint8_t DLE = 0x10; - - static ReturnValue_t decode(const uint8_t *sourceStream, - uint32_t sourceStreamLen, uint32_t *readLen, uint8_t *destStream, - uint32_t maxDestStreamlen, uint32_t *decodedLen); - - static ReturnValue_t encode(const uint8_t *sourceStream, uint32_t sourceLen, - uint8_t *destStream, uint32_t maxDestLen, uint32_t *encodedLen, - bool addStxEtx = true); -}; - -#endif /* DLEENCODER_H_ */ +#ifndef FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_ +#define FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_ + +#include "../returnvalues/HasReturnvaluesIF.h" +#include + +/** + * @brief This DLE Encoder (Data Link Encoder) can be used to encode and + * decode arbitrary data with ASCII control characters + * @details + * List of control codes: + * https://en.wikipedia.org/wiki/C0_and_C1_control_codes + * + * This encoder can be used to achieve a basic transport layer when using + * char based transmission systems. + * The passed source strean is converted into a encoded stream by adding + * a STX marker at the start of the stream and an ETX marker at the end of + * the stream. Any STX, ETX, DLE and CR occurences in the source stream are + * escaped by a DLE character. The encoder also replaces escaped control chars + * by another char, so STX, ETX and CR should not appear anywhere in the actual + * encoded data stream. + * + * When using a strictly char based reception of packets enoded with DLE, + * STX can be used to notify a reader that actual data will start to arrive + * while ETX can be used to notify the reader that the data has ended. + */ +class DleEncoder: public HasReturnvaluesIF { +private: + DleEncoder(); + virtual ~DleEncoder(); + +public: + static constexpr uint8_t INTERFACE_ID = CLASS_ID::DLE_ENCODER; + static constexpr ReturnValue_t STREAM_TOO_SHORT = MAKE_RETURN_CODE(0x01); + static constexpr ReturnValue_t DECODING_ERROR = MAKE_RETURN_CODE(0x02); + + //! Start Of Text character. First character is encoded stream + static constexpr uint8_t STX_CHAR = 0x02; + //! End Of Text character. Last character in encoded stream + static constexpr uint8_t ETX_CHAR = 0x03; + //! Data Link Escape character. Used to escape STX, ETX and DLE occurences + //! in the source stream. + static constexpr uint8_t DLE_CHAR = 0x10; + static constexpr uint8_t CARRIAGE_RETURN = 0x0D; + + /** + * Encodes the give data stream by preceding it with the STX marker + * and ending it with an ETX marker. STX, ETX and DLE characters inside + * the stream are escaped by DLE characters and also replaced by adding + * 0x40 (which is reverted in the decoing process). + * @param sourceStream + * @param sourceLen + * @param destStream + * @param maxDestLen + * @param encodedLen + * @param addStxEtx + * Adding STX and ETX can be omitted, if they are added manually. + * @return + */ + static ReturnValue_t encode(const uint8_t *sourceStream, size_t sourceLen, + uint8_t *destStream, size_t maxDestLen, size_t *encodedLen, + bool addStxEtx = true); + + /** + * Converts an encoded stream back. + * @param sourceStream + * @param sourceStreamLen + * @param readLen + * @param destStream + * @param maxDestStreamlen + * @param decodedLen + * @return + */ + static ReturnValue_t decode(const uint8_t *sourceStream, + size_t sourceStreamLen, size_t *readLen, uint8_t *destStream, + size_t maxDestStreamlen, size_t *decodedLen); +}; + +#endif /* FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_ */ From a8f2cf910b025c22f93d1ca1f070285e6d48773f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 26 Aug 2020 17:43:20 +0200 Subject: [PATCH 259/653] taken over dle encoder from upstream master --- globalfunctions/DleEncoder.cpp | 219 ++++++++++++++------------------- globalfunctions/DleEncoder.h | 104 ++++------------ 2 files changed, 120 insertions(+), 203 deletions(-) diff --git a/globalfunctions/DleEncoder.cpp b/globalfunctions/DleEncoder.cpp index 21dbd2e6..088c9d80 100644 --- a/globalfunctions/DleEncoder.cpp +++ b/globalfunctions/DleEncoder.cpp @@ -1,124 +1,95 @@ -#include "../globalfunctions/DleEncoder.h" - -DleEncoder::DleEncoder() {} - -DleEncoder::~DleEncoder() {} - -ReturnValue_t DleEncoder::encode(const uint8_t* sourceStream, - size_t sourceLen, uint8_t* destStream, size_t maxDestLen, - size_t* encodedLen, bool addStxEtx) { - if (maxDestLen < 2) { - return STREAM_TOO_SHORT; - } - size_t encodedIndex = 0, sourceIndex = 0; - uint8_t nextByte; - if (addStxEtx) { - destStream[0] = STX_CHAR; - ++encodedIndex; - } - - while (encodedIndex < maxDestLen and sourceIndex < sourceLen) - { - nextByte = sourceStream[sourceIndex]; - // STX, ETX and CR characters in the stream need to be escaped with DLE - if (nextByte == STX_CHAR or nextByte == ETX_CHAR or nextByte == CARRIAGE_RETURN) { - if (encodedIndex + 1 >= maxDestLen) { - return STREAM_TOO_SHORT; - } - else { - destStream[encodedIndex] = DLE_CHAR; - ++encodedIndex; - /* Escaped byte will be actual byte + 0x40. This prevents - * STX, ETX, and carriage return characters from appearing - * in the encoded data stream at all, so when polling an - * encoded stream, the transmission can be stopped at ETX. - * 0x40 was chosen at random with special requirements: - * - Prevent going from one control char to another - * - Prevent overflow for common characters */ - destStream[encodedIndex] = nextByte + 0x40; - } - } - // DLE characters are simply escaped with DLE. - else if (nextByte == DLE_CHAR) { - if (encodedIndex + 1 >= maxDestLen) { - return STREAM_TOO_SHORT; - } - else { - destStream[encodedIndex] = DLE_CHAR; - ++encodedIndex; - destStream[encodedIndex] = DLE_CHAR; - } - } - else { - destStream[encodedIndex] = nextByte; - } - ++encodedIndex; - ++sourceIndex; - } - - if (sourceIndex == sourceLen and encodedIndex < maxDestLen) { - if (addStxEtx) { - destStream[encodedIndex] = ETX_CHAR; - ++encodedIndex; - } - *encodedLen = encodedIndex; - return RETURN_OK; - } - else { - return STREAM_TOO_SHORT; - } -} - -ReturnValue_t DleEncoder::decode(const uint8_t *sourceStream, - size_t sourceStreamLen, size_t *readLen, uint8_t *destStream, - size_t maxDestStreamlen, size_t *decodedLen) { - size_t encodedIndex = 0, decodedIndex = 0; - uint8_t nextByte; - if (*sourceStream != STX_CHAR) { - return DECODING_ERROR; - } - ++encodedIndex; - - while ((encodedIndex < sourceStreamLen) && (decodedIndex < maxDestStreamlen) - && (sourceStream[encodedIndex] != ETX_CHAR) - && (sourceStream[encodedIndex] != STX_CHAR)) { - if (sourceStream[encodedIndex] == DLE_CHAR) { - nextByte = sourceStream[encodedIndex + 1]; - // The next byte is a DLE character that was escaped by another - // DLE character, so we can write it to the destination stream. - if (nextByte == DLE_CHAR) { - destStream[decodedIndex] = nextByte; - } - else { - /* The next byte is a STX, DTX or 0x0D character which - * was escaped by a DLE character. The actual byte was - * also encoded by adding + 0x40 to preven having control chars, - * in the stream at all, so we convert it back. */ - if (nextByte == 0x42 or nextByte == 0x43 or nextByte == 0x4D) { - destStream[decodedIndex] = nextByte - 0x40; - } - else { - return DECODING_ERROR; - } - } - ++encodedIndex; - } - else { - destStream[decodedIndex] = sourceStream[encodedIndex]; - } - - ++encodedIndex; - ++decodedIndex; - } - - if (sourceStream[encodedIndex] != ETX_CHAR) { - *readLen = ++encodedIndex; - return DECODING_ERROR; - } - else { - *readLen = ++encodedIndex; - *decodedLen = decodedIndex; - return RETURN_OK; - } -} - +#include "DleEncoder.h" + +DleEncoder::DleEncoder() { +} + +DleEncoder::~DleEncoder() { +} + +ReturnValue_t DleEncoder::decode(const uint8_t *sourceStream, + uint32_t sourceStreamLen, uint32_t *readLen, uint8_t *destStream, + uint32_t maxDestStreamlen, uint32_t *decodedLen) { + uint32_t encodedIndex = 0, decodedIndex = 0; + uint8_t nextByte; + if (*sourceStream != STX) { + return RETURN_FAILED; + } + ++encodedIndex; + while ((encodedIndex < sourceStreamLen) && (decodedIndex < maxDestStreamlen) + && (sourceStream[encodedIndex] != ETX) + && (sourceStream[encodedIndex] != STX)) { + if (sourceStream[encodedIndex] == DLE) { + nextByte = sourceStream[encodedIndex + 1]; + if (nextByte == 0x10) { + destStream[decodedIndex] = nextByte; + } else { + if ((nextByte == 0x42) || (nextByte == 0x43) + || (nextByte == 0x4D)) { + destStream[decodedIndex] = nextByte - 0x40; + } else { + return RETURN_FAILED; + } + } + ++encodedIndex; + } else { + destStream[decodedIndex] = sourceStream[encodedIndex]; + } + ++encodedIndex; + ++decodedIndex; + } + if (sourceStream[encodedIndex] != ETX) { + return RETURN_FAILED; + } else { + *readLen = ++encodedIndex; + *decodedLen = decodedIndex; + return RETURN_OK; + } +} + +ReturnValue_t DleEncoder::encode(const uint8_t* sourceStream, + uint32_t sourceLen, uint8_t* destStream, uint32_t maxDestLen, + uint32_t* encodedLen, bool addStxEtx) { + if (maxDestLen < 2) { + return RETURN_FAILED; + } + uint32_t encodedIndex = 0, sourceIndex = 0; + uint8_t nextByte; + if (addStxEtx) { + destStream[0] = STX; + ++encodedIndex; + } + while ((encodedIndex < maxDestLen) && (sourceIndex < sourceLen)) { + nextByte = sourceStream[sourceIndex]; + if ((nextByte == STX) || (nextByte == ETX) || (nextByte == 0x0D)) { + if (encodedIndex + 1 >= maxDestLen) { + return RETURN_FAILED; + } else { + destStream[encodedIndex] = DLE; + ++encodedIndex; + destStream[encodedIndex] = nextByte + 0x40; + } + } else if (nextByte == DLE) { + if (encodedIndex + 1 >= maxDestLen) { + return RETURN_FAILED; + } else { + destStream[encodedIndex] = DLE; + ++encodedIndex; + destStream[encodedIndex] = DLE; + } + } else { + destStream[encodedIndex] = nextByte; + } + ++encodedIndex; + ++sourceIndex; + } + if ((sourceIndex == sourceLen) && (encodedIndex < maxDestLen)) { + if (addStxEtx) { + destStream[encodedIndex] = ETX; + ++encodedIndex; + } + *encodedLen = encodedIndex; + return RETURN_OK; + } else { + return RETURN_FAILED; + } +} diff --git a/globalfunctions/DleEncoder.h b/globalfunctions/DleEncoder.h index 3c327a55..ff3a2727 100644 --- a/globalfunctions/DleEncoder.h +++ b/globalfunctions/DleEncoder.h @@ -1,79 +1,25 @@ -#ifndef FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_ -#define FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_ - -#include "../returnvalues/HasReturnvaluesIF.h" -#include - -/** - * @brief This DLE Encoder (Data Link Encoder) can be used to encode and - * decode arbitrary data with ASCII control characters - * @details - * List of control codes: - * https://en.wikipedia.org/wiki/C0_and_C1_control_codes - * - * This encoder can be used to achieve a basic transport layer when using - * char based transmission systems. - * The passed source strean is converted into a encoded stream by adding - * a STX marker at the start of the stream and an ETX marker at the end of - * the stream. Any STX, ETX, DLE and CR occurences in the source stream are - * escaped by a DLE character. The encoder also replaces escaped control chars - * by another char, so STX, ETX and CR should not appear anywhere in the actual - * encoded data stream. - * - * When using a strictly char based reception of packets enoded with DLE, - * STX can be used to notify a reader that actual data will start to arrive - * while ETX can be used to notify the reader that the data has ended. - */ -class DleEncoder: public HasReturnvaluesIF { -private: - DleEncoder(); - virtual ~DleEncoder(); - -public: - static constexpr uint8_t INTERFACE_ID = CLASS_ID::DLE_ENCODER; - static constexpr ReturnValue_t STREAM_TOO_SHORT = MAKE_RETURN_CODE(0x01); - static constexpr ReturnValue_t DECODING_ERROR = MAKE_RETURN_CODE(0x02); - - //! Start Of Text character. First character is encoded stream - static constexpr uint8_t STX_CHAR = 0x02; - //! End Of Text character. Last character in encoded stream - static constexpr uint8_t ETX_CHAR = 0x03; - //! Data Link Escape character. Used to escape STX, ETX and DLE occurences - //! in the source stream. - static constexpr uint8_t DLE_CHAR = 0x10; - static constexpr uint8_t CARRIAGE_RETURN = 0x0D; - - /** - * Encodes the give data stream by preceding it with the STX marker - * and ending it with an ETX marker. STX, ETX and DLE characters inside - * the stream are escaped by DLE characters and also replaced by adding - * 0x40 (which is reverted in the decoing process). - * @param sourceStream - * @param sourceLen - * @param destStream - * @param maxDestLen - * @param encodedLen - * @param addStxEtx - * Adding STX and ETX can be omitted, if they are added manually. - * @return - */ - static ReturnValue_t encode(const uint8_t *sourceStream, size_t sourceLen, - uint8_t *destStream, size_t maxDestLen, size_t *encodedLen, - bool addStxEtx = true); - - /** - * Converts an encoded stream back. - * @param sourceStream - * @param sourceStreamLen - * @param readLen - * @param destStream - * @param maxDestStreamlen - * @param decodedLen - * @return - */ - static ReturnValue_t decode(const uint8_t *sourceStream, - size_t sourceStreamLen, size_t *readLen, uint8_t *destStream, - size_t maxDestStreamlen, size_t *decodedLen); -}; - -#endif /* FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_ */ +#ifndef DLEENCODER_H_ +#define DLEENCODER_H_ + +#include "../returnvalues/HasReturnvaluesIF.h" + +class DleEncoder: public HasReturnvaluesIF { +private: + DleEncoder(); + virtual ~DleEncoder(); + +public: + static const uint8_t STX = 0x02; + static const uint8_t ETX = 0x03; + static const uint8_t DLE = 0x10; + + static ReturnValue_t decode(const uint8_t *sourceStream, + uint32_t sourceStreamLen, uint32_t *readLen, uint8_t *destStream, + uint32_t maxDestStreamlen, uint32_t *decodedLen); + + static ReturnValue_t encode(const uint8_t *sourceStream, uint32_t sourceLen, + uint8_t *destStream, uint32_t maxDestLen, uint32_t *encodedLen, + bool addStxEtx = true); +}; + +#endif /* DLEENCODER_H_ */ From df850116ffc924ff823e1238868994c594249094 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 26 Aug 2020 17:43:47 +0200 Subject: [PATCH 260/653] dle encoder doc added --- globalfunctions/DleEncoder.cpp | 219 +++++++++++++++++++-------------- globalfunctions/DleEncoder.h | 104 ++++++++++++---- 2 files changed, 203 insertions(+), 120 deletions(-) diff --git a/globalfunctions/DleEncoder.cpp b/globalfunctions/DleEncoder.cpp index 088c9d80..21dbd2e6 100644 --- a/globalfunctions/DleEncoder.cpp +++ b/globalfunctions/DleEncoder.cpp @@ -1,95 +1,124 @@ -#include "DleEncoder.h" - -DleEncoder::DleEncoder() { -} - -DleEncoder::~DleEncoder() { -} - -ReturnValue_t DleEncoder::decode(const uint8_t *sourceStream, - uint32_t sourceStreamLen, uint32_t *readLen, uint8_t *destStream, - uint32_t maxDestStreamlen, uint32_t *decodedLen) { - uint32_t encodedIndex = 0, decodedIndex = 0; - uint8_t nextByte; - if (*sourceStream != STX) { - return RETURN_FAILED; - } - ++encodedIndex; - while ((encodedIndex < sourceStreamLen) && (decodedIndex < maxDestStreamlen) - && (sourceStream[encodedIndex] != ETX) - && (sourceStream[encodedIndex] != STX)) { - if (sourceStream[encodedIndex] == DLE) { - nextByte = sourceStream[encodedIndex + 1]; - if (nextByte == 0x10) { - destStream[decodedIndex] = nextByte; - } else { - if ((nextByte == 0x42) || (nextByte == 0x43) - || (nextByte == 0x4D)) { - destStream[decodedIndex] = nextByte - 0x40; - } else { - return RETURN_FAILED; - } - } - ++encodedIndex; - } else { - destStream[decodedIndex] = sourceStream[encodedIndex]; - } - ++encodedIndex; - ++decodedIndex; - } - if (sourceStream[encodedIndex] != ETX) { - return RETURN_FAILED; - } else { - *readLen = ++encodedIndex; - *decodedLen = decodedIndex; - return RETURN_OK; - } -} - -ReturnValue_t DleEncoder::encode(const uint8_t* sourceStream, - uint32_t sourceLen, uint8_t* destStream, uint32_t maxDestLen, - uint32_t* encodedLen, bool addStxEtx) { - if (maxDestLen < 2) { - return RETURN_FAILED; - } - uint32_t encodedIndex = 0, sourceIndex = 0; - uint8_t nextByte; - if (addStxEtx) { - destStream[0] = STX; - ++encodedIndex; - } - while ((encodedIndex < maxDestLen) && (sourceIndex < sourceLen)) { - nextByte = sourceStream[sourceIndex]; - if ((nextByte == STX) || (nextByte == ETX) || (nextByte == 0x0D)) { - if (encodedIndex + 1 >= maxDestLen) { - return RETURN_FAILED; - } else { - destStream[encodedIndex] = DLE; - ++encodedIndex; - destStream[encodedIndex] = nextByte + 0x40; - } - } else if (nextByte == DLE) { - if (encodedIndex + 1 >= maxDestLen) { - return RETURN_FAILED; - } else { - destStream[encodedIndex] = DLE; - ++encodedIndex; - destStream[encodedIndex] = DLE; - } - } else { - destStream[encodedIndex] = nextByte; - } - ++encodedIndex; - ++sourceIndex; - } - if ((sourceIndex == sourceLen) && (encodedIndex < maxDestLen)) { - if (addStxEtx) { - destStream[encodedIndex] = ETX; - ++encodedIndex; - } - *encodedLen = encodedIndex; - return RETURN_OK; - } else { - return RETURN_FAILED; - } -} +#include "../globalfunctions/DleEncoder.h" + +DleEncoder::DleEncoder() {} + +DleEncoder::~DleEncoder() {} + +ReturnValue_t DleEncoder::encode(const uint8_t* sourceStream, + size_t sourceLen, uint8_t* destStream, size_t maxDestLen, + size_t* encodedLen, bool addStxEtx) { + if (maxDestLen < 2) { + return STREAM_TOO_SHORT; + } + size_t encodedIndex = 0, sourceIndex = 0; + uint8_t nextByte; + if (addStxEtx) { + destStream[0] = STX_CHAR; + ++encodedIndex; + } + + while (encodedIndex < maxDestLen and sourceIndex < sourceLen) + { + nextByte = sourceStream[sourceIndex]; + // STX, ETX and CR characters in the stream need to be escaped with DLE + if (nextByte == STX_CHAR or nextByte == ETX_CHAR or nextByte == CARRIAGE_RETURN) { + if (encodedIndex + 1 >= maxDestLen) { + return STREAM_TOO_SHORT; + } + else { + destStream[encodedIndex] = DLE_CHAR; + ++encodedIndex; + /* Escaped byte will be actual byte + 0x40. This prevents + * STX, ETX, and carriage return characters from appearing + * in the encoded data stream at all, so when polling an + * encoded stream, the transmission can be stopped at ETX. + * 0x40 was chosen at random with special requirements: + * - Prevent going from one control char to another + * - Prevent overflow for common characters */ + destStream[encodedIndex] = nextByte + 0x40; + } + } + // DLE characters are simply escaped with DLE. + else if (nextByte == DLE_CHAR) { + if (encodedIndex + 1 >= maxDestLen) { + return STREAM_TOO_SHORT; + } + else { + destStream[encodedIndex] = DLE_CHAR; + ++encodedIndex; + destStream[encodedIndex] = DLE_CHAR; + } + } + else { + destStream[encodedIndex] = nextByte; + } + ++encodedIndex; + ++sourceIndex; + } + + if (sourceIndex == sourceLen and encodedIndex < maxDestLen) { + if (addStxEtx) { + destStream[encodedIndex] = ETX_CHAR; + ++encodedIndex; + } + *encodedLen = encodedIndex; + return RETURN_OK; + } + else { + return STREAM_TOO_SHORT; + } +} + +ReturnValue_t DleEncoder::decode(const uint8_t *sourceStream, + size_t sourceStreamLen, size_t *readLen, uint8_t *destStream, + size_t maxDestStreamlen, size_t *decodedLen) { + size_t encodedIndex = 0, decodedIndex = 0; + uint8_t nextByte; + if (*sourceStream != STX_CHAR) { + return DECODING_ERROR; + } + ++encodedIndex; + + while ((encodedIndex < sourceStreamLen) && (decodedIndex < maxDestStreamlen) + && (sourceStream[encodedIndex] != ETX_CHAR) + && (sourceStream[encodedIndex] != STX_CHAR)) { + if (sourceStream[encodedIndex] == DLE_CHAR) { + nextByte = sourceStream[encodedIndex + 1]; + // The next byte is a DLE character that was escaped by another + // DLE character, so we can write it to the destination stream. + if (nextByte == DLE_CHAR) { + destStream[decodedIndex] = nextByte; + } + else { + /* The next byte is a STX, DTX or 0x0D character which + * was escaped by a DLE character. The actual byte was + * also encoded by adding + 0x40 to preven having control chars, + * in the stream at all, so we convert it back. */ + if (nextByte == 0x42 or nextByte == 0x43 or nextByte == 0x4D) { + destStream[decodedIndex] = nextByte - 0x40; + } + else { + return DECODING_ERROR; + } + } + ++encodedIndex; + } + else { + destStream[decodedIndex] = sourceStream[encodedIndex]; + } + + ++encodedIndex; + ++decodedIndex; + } + + if (sourceStream[encodedIndex] != ETX_CHAR) { + *readLen = ++encodedIndex; + return DECODING_ERROR; + } + else { + *readLen = ++encodedIndex; + *decodedLen = decodedIndex; + return RETURN_OK; + } +} + diff --git a/globalfunctions/DleEncoder.h b/globalfunctions/DleEncoder.h index ff3a2727..3c327a55 100644 --- a/globalfunctions/DleEncoder.h +++ b/globalfunctions/DleEncoder.h @@ -1,25 +1,79 @@ -#ifndef DLEENCODER_H_ -#define DLEENCODER_H_ - -#include "../returnvalues/HasReturnvaluesIF.h" - -class DleEncoder: public HasReturnvaluesIF { -private: - DleEncoder(); - virtual ~DleEncoder(); - -public: - static const uint8_t STX = 0x02; - static const uint8_t ETX = 0x03; - static const uint8_t DLE = 0x10; - - static ReturnValue_t decode(const uint8_t *sourceStream, - uint32_t sourceStreamLen, uint32_t *readLen, uint8_t *destStream, - uint32_t maxDestStreamlen, uint32_t *decodedLen); - - static ReturnValue_t encode(const uint8_t *sourceStream, uint32_t sourceLen, - uint8_t *destStream, uint32_t maxDestLen, uint32_t *encodedLen, - bool addStxEtx = true); -}; - -#endif /* DLEENCODER_H_ */ +#ifndef FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_ +#define FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_ + +#include "../returnvalues/HasReturnvaluesIF.h" +#include + +/** + * @brief This DLE Encoder (Data Link Encoder) can be used to encode and + * decode arbitrary data with ASCII control characters + * @details + * List of control codes: + * https://en.wikipedia.org/wiki/C0_and_C1_control_codes + * + * This encoder can be used to achieve a basic transport layer when using + * char based transmission systems. + * The passed source strean is converted into a encoded stream by adding + * a STX marker at the start of the stream and an ETX marker at the end of + * the stream. Any STX, ETX, DLE and CR occurences in the source stream are + * escaped by a DLE character. The encoder also replaces escaped control chars + * by another char, so STX, ETX and CR should not appear anywhere in the actual + * encoded data stream. + * + * When using a strictly char based reception of packets enoded with DLE, + * STX can be used to notify a reader that actual data will start to arrive + * while ETX can be used to notify the reader that the data has ended. + */ +class DleEncoder: public HasReturnvaluesIF { +private: + DleEncoder(); + virtual ~DleEncoder(); + +public: + static constexpr uint8_t INTERFACE_ID = CLASS_ID::DLE_ENCODER; + static constexpr ReturnValue_t STREAM_TOO_SHORT = MAKE_RETURN_CODE(0x01); + static constexpr ReturnValue_t DECODING_ERROR = MAKE_RETURN_CODE(0x02); + + //! Start Of Text character. First character is encoded stream + static constexpr uint8_t STX_CHAR = 0x02; + //! End Of Text character. Last character in encoded stream + static constexpr uint8_t ETX_CHAR = 0x03; + //! Data Link Escape character. Used to escape STX, ETX and DLE occurences + //! in the source stream. + static constexpr uint8_t DLE_CHAR = 0x10; + static constexpr uint8_t CARRIAGE_RETURN = 0x0D; + + /** + * Encodes the give data stream by preceding it with the STX marker + * and ending it with an ETX marker. STX, ETX and DLE characters inside + * the stream are escaped by DLE characters and also replaced by adding + * 0x40 (which is reverted in the decoing process). + * @param sourceStream + * @param sourceLen + * @param destStream + * @param maxDestLen + * @param encodedLen + * @param addStxEtx + * Adding STX and ETX can be omitted, if they are added manually. + * @return + */ + static ReturnValue_t encode(const uint8_t *sourceStream, size_t sourceLen, + uint8_t *destStream, size_t maxDestLen, size_t *encodedLen, + bool addStxEtx = true); + + /** + * Converts an encoded stream back. + * @param sourceStream + * @param sourceStreamLen + * @param readLen + * @param destStream + * @param maxDestStreamlen + * @param decodedLen + * @return + */ + static ReturnValue_t decode(const uint8_t *sourceStream, + size_t sourceStreamLen, size_t *readLen, uint8_t *destStream, + size_t maxDestStreamlen, size_t *decodedLen); +}; + +#endif /* FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_ */ From 281f13e27ba915bc987f7a4023a37a4a73305cf6 Mon Sep 17 00:00:00 2001 From: gaisser Date: Wed, 26 Aug 2020 19:58:18 +0200 Subject: [PATCH 261/653] Update 'globalfunctions/DleEncoder.h' Corrected some spelling mistakes --- globalfunctions/DleEncoder.h | 158 +++++++++++++++++------------------ 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/globalfunctions/DleEncoder.h b/globalfunctions/DleEncoder.h index 3c327a55..6d073f9a 100644 --- a/globalfunctions/DleEncoder.h +++ b/globalfunctions/DleEncoder.h @@ -1,79 +1,79 @@ -#ifndef FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_ -#define FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_ - -#include "../returnvalues/HasReturnvaluesIF.h" -#include - -/** - * @brief This DLE Encoder (Data Link Encoder) can be used to encode and - * decode arbitrary data with ASCII control characters - * @details - * List of control codes: - * https://en.wikipedia.org/wiki/C0_and_C1_control_codes - * - * This encoder can be used to achieve a basic transport layer when using - * char based transmission systems. - * The passed source strean is converted into a encoded stream by adding - * a STX marker at the start of the stream and an ETX marker at the end of - * the stream. Any STX, ETX, DLE and CR occurences in the source stream are - * escaped by a DLE character. The encoder also replaces escaped control chars - * by another char, so STX, ETX and CR should not appear anywhere in the actual - * encoded data stream. - * - * When using a strictly char based reception of packets enoded with DLE, - * STX can be used to notify a reader that actual data will start to arrive - * while ETX can be used to notify the reader that the data has ended. - */ -class DleEncoder: public HasReturnvaluesIF { -private: - DleEncoder(); - virtual ~DleEncoder(); - -public: - static constexpr uint8_t INTERFACE_ID = CLASS_ID::DLE_ENCODER; - static constexpr ReturnValue_t STREAM_TOO_SHORT = MAKE_RETURN_CODE(0x01); - static constexpr ReturnValue_t DECODING_ERROR = MAKE_RETURN_CODE(0x02); - - //! Start Of Text character. First character is encoded stream - static constexpr uint8_t STX_CHAR = 0x02; - //! End Of Text character. Last character in encoded stream - static constexpr uint8_t ETX_CHAR = 0x03; - //! Data Link Escape character. Used to escape STX, ETX and DLE occurences - //! in the source stream. - static constexpr uint8_t DLE_CHAR = 0x10; - static constexpr uint8_t CARRIAGE_RETURN = 0x0D; - - /** - * Encodes the give data stream by preceding it with the STX marker - * and ending it with an ETX marker. STX, ETX and DLE characters inside - * the stream are escaped by DLE characters and also replaced by adding - * 0x40 (which is reverted in the decoing process). - * @param sourceStream - * @param sourceLen - * @param destStream - * @param maxDestLen - * @param encodedLen - * @param addStxEtx - * Adding STX and ETX can be omitted, if they are added manually. - * @return - */ - static ReturnValue_t encode(const uint8_t *sourceStream, size_t sourceLen, - uint8_t *destStream, size_t maxDestLen, size_t *encodedLen, - bool addStxEtx = true); - - /** - * Converts an encoded stream back. - * @param sourceStream - * @param sourceStreamLen - * @param readLen - * @param destStream - * @param maxDestStreamlen - * @param decodedLen - * @return - */ - static ReturnValue_t decode(const uint8_t *sourceStream, - size_t sourceStreamLen, size_t *readLen, uint8_t *destStream, - size_t maxDestStreamlen, size_t *decodedLen); -}; - -#endif /* FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_ */ +#ifndef FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_ +#define FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_ + +#include "../returnvalues/HasReturnvaluesIF.h" +#include + +/** + * @brief This DLE Encoder (Data Link Encoder) can be used to encode and + * decode arbitrary data with ASCII control characters + * @details + * List of control codes: + * https://en.wikipedia.org/wiki/C0_and_C1_control_codes + * + * This encoder can be used to achieve a basic transport layer when using + * char based transmission systems. + * The passed source strean is converted into a encoded stream by adding + * a STX marker at the start of the stream and an ETX marker at the end of + * the stream. Any STX, ETX, DLE and CR occurrences in the source stream are + * escaped by a DLE character. The encoder also replaces escaped control chars + * by another char, so STX, ETX and CR should not appear anywhere in the actual + * encoded data stream. + * + * When using a strictly char based reception of packets encoded with DLE, + * STX can be used to notify a reader that actual data will start to arrive + * while ETX can be used to notify the reader that the data has ended. + */ +class DleEncoder: public HasReturnvaluesIF { +private: + DleEncoder(); + virtual ~DleEncoder(); + +public: + static constexpr uint8_t INTERFACE_ID = CLASS_ID::DLE_ENCODER; + static constexpr ReturnValue_t STREAM_TOO_SHORT = MAKE_RETURN_CODE(0x01); + static constexpr ReturnValue_t DECODING_ERROR = MAKE_RETURN_CODE(0x02); + + //! Start Of Text character. First character is encoded stream + static constexpr uint8_t STX_CHAR = 0x02; + //! End Of Text character. Last character in encoded stream + static constexpr uint8_t ETX_CHAR = 0x03; + //! Data Link Escape character. Used to escape STX, ETX and DLE occurrences + //! in the source stream. + static constexpr uint8_t DLE_CHAR = 0x10; + static constexpr uint8_t CARRIAGE_RETURN = 0x0D; + + /** + * Encodes the give data stream by preceding it with the STX marker + * and ending it with an ETX marker. STX, ETX and DLE characters inside + * the stream are escaped by DLE characters and also replaced by adding + * 0x40 (which is reverted in the decoding process). + * @param sourceStream + * @param sourceLen + * @param destStream + * @param maxDestLen + * @param encodedLen + * @param addStxEtx + * Adding STX and ETX can be omitted, if they are added manually. + * @return + */ + static ReturnValue_t encode(const uint8_t *sourceStream, size_t sourceLen, + uint8_t *destStream, size_t maxDestLen, size_t *encodedLen, + bool addStxEtx = true); + + /** + * Converts an encoded stream back. + * @param sourceStream + * @param sourceStreamLen + * @param readLen + * @param destStream + * @param maxDestStreamlen + * @param decodedLen + * @return + */ + static ReturnValue_t decode(const uint8_t *sourceStream, + size_t sourceStreamLen, size_t *readLen, uint8_t *destStream, + size_t maxDestStreamlen, size_t *decodedLen); +}; + +#endif /* FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_ */ From 76f145ddcfe2bd0ed6e201d70873cfe3927d80df Mon Sep 17 00:00:00 2001 From: gaisser Date: Wed, 26 Aug 2020 19:59:58 +0200 Subject: [PATCH 262/653] Update 'globalfunctions/DleEncoder.cpp' Just a missing char --- globalfunctions/DleEncoder.cpp | 248 ++++++++++++++++----------------- 1 file changed, 124 insertions(+), 124 deletions(-) diff --git a/globalfunctions/DleEncoder.cpp b/globalfunctions/DleEncoder.cpp index 21dbd2e6..8520389d 100644 --- a/globalfunctions/DleEncoder.cpp +++ b/globalfunctions/DleEncoder.cpp @@ -1,124 +1,124 @@ -#include "../globalfunctions/DleEncoder.h" - -DleEncoder::DleEncoder() {} - -DleEncoder::~DleEncoder() {} - -ReturnValue_t DleEncoder::encode(const uint8_t* sourceStream, - size_t sourceLen, uint8_t* destStream, size_t maxDestLen, - size_t* encodedLen, bool addStxEtx) { - if (maxDestLen < 2) { - return STREAM_TOO_SHORT; - } - size_t encodedIndex = 0, sourceIndex = 0; - uint8_t nextByte; - if (addStxEtx) { - destStream[0] = STX_CHAR; - ++encodedIndex; - } - - while (encodedIndex < maxDestLen and sourceIndex < sourceLen) - { - nextByte = sourceStream[sourceIndex]; - // STX, ETX and CR characters in the stream need to be escaped with DLE - if (nextByte == STX_CHAR or nextByte == ETX_CHAR or nextByte == CARRIAGE_RETURN) { - if (encodedIndex + 1 >= maxDestLen) { - return STREAM_TOO_SHORT; - } - else { - destStream[encodedIndex] = DLE_CHAR; - ++encodedIndex; - /* Escaped byte will be actual byte + 0x40. This prevents - * STX, ETX, and carriage return characters from appearing - * in the encoded data stream at all, so when polling an - * encoded stream, the transmission can be stopped at ETX. - * 0x40 was chosen at random with special requirements: - * - Prevent going from one control char to another - * - Prevent overflow for common characters */ - destStream[encodedIndex] = nextByte + 0x40; - } - } - // DLE characters are simply escaped with DLE. - else if (nextByte == DLE_CHAR) { - if (encodedIndex + 1 >= maxDestLen) { - return STREAM_TOO_SHORT; - } - else { - destStream[encodedIndex] = DLE_CHAR; - ++encodedIndex; - destStream[encodedIndex] = DLE_CHAR; - } - } - else { - destStream[encodedIndex] = nextByte; - } - ++encodedIndex; - ++sourceIndex; - } - - if (sourceIndex == sourceLen and encodedIndex < maxDestLen) { - if (addStxEtx) { - destStream[encodedIndex] = ETX_CHAR; - ++encodedIndex; - } - *encodedLen = encodedIndex; - return RETURN_OK; - } - else { - return STREAM_TOO_SHORT; - } -} - -ReturnValue_t DleEncoder::decode(const uint8_t *sourceStream, - size_t sourceStreamLen, size_t *readLen, uint8_t *destStream, - size_t maxDestStreamlen, size_t *decodedLen) { - size_t encodedIndex = 0, decodedIndex = 0; - uint8_t nextByte; - if (*sourceStream != STX_CHAR) { - return DECODING_ERROR; - } - ++encodedIndex; - - while ((encodedIndex < sourceStreamLen) && (decodedIndex < maxDestStreamlen) - && (sourceStream[encodedIndex] != ETX_CHAR) - && (sourceStream[encodedIndex] != STX_CHAR)) { - if (sourceStream[encodedIndex] == DLE_CHAR) { - nextByte = sourceStream[encodedIndex + 1]; - // The next byte is a DLE character that was escaped by another - // DLE character, so we can write it to the destination stream. - if (nextByte == DLE_CHAR) { - destStream[decodedIndex] = nextByte; - } - else { - /* The next byte is a STX, DTX or 0x0D character which - * was escaped by a DLE character. The actual byte was - * also encoded by adding + 0x40 to preven having control chars, - * in the stream at all, so we convert it back. */ - if (nextByte == 0x42 or nextByte == 0x43 or nextByte == 0x4D) { - destStream[decodedIndex] = nextByte - 0x40; - } - else { - return DECODING_ERROR; - } - } - ++encodedIndex; - } - else { - destStream[decodedIndex] = sourceStream[encodedIndex]; - } - - ++encodedIndex; - ++decodedIndex; - } - - if (sourceStream[encodedIndex] != ETX_CHAR) { - *readLen = ++encodedIndex; - return DECODING_ERROR; - } - else { - *readLen = ++encodedIndex; - *decodedLen = decodedIndex; - return RETURN_OK; - } -} - +#include "../globalfunctions/DleEncoder.h" + +DleEncoder::DleEncoder() {} + +DleEncoder::~DleEncoder() {} + +ReturnValue_t DleEncoder::encode(const uint8_t* sourceStream, + size_t sourceLen, uint8_t* destStream, size_t maxDestLen, + size_t* encodedLen, bool addStxEtx) { + if (maxDestLen < 2) { + return STREAM_TOO_SHORT; + } + size_t encodedIndex = 0, sourceIndex = 0; + uint8_t nextByte; + if (addStxEtx) { + destStream[0] = STX_CHAR; + ++encodedIndex; + } + + while (encodedIndex < maxDestLen and sourceIndex < sourceLen) + { + nextByte = sourceStream[sourceIndex]; + // STX, ETX and CR characters in the stream need to be escaped with DLE + if (nextByte == STX_CHAR or nextByte == ETX_CHAR or nextByte == CARRIAGE_RETURN) { + if (encodedIndex + 1 >= maxDestLen) { + return STREAM_TOO_SHORT; + } + else { + destStream[encodedIndex] = DLE_CHAR; + ++encodedIndex; + /* Escaped byte will be actual byte + 0x40. This prevents + * STX, ETX, and carriage return characters from appearing + * in the encoded data stream at all, so when polling an + * encoded stream, the transmission can be stopped at ETX. + * 0x40 was chosen at random with special requirements: + * - Prevent going from one control char to another + * - Prevent overflow for common characters */ + destStream[encodedIndex] = nextByte + 0x40; + } + } + // DLE characters are simply escaped with DLE. + else if (nextByte == DLE_CHAR) { + if (encodedIndex + 1 >= maxDestLen) { + return STREAM_TOO_SHORT; + } + else { + destStream[encodedIndex] = DLE_CHAR; + ++encodedIndex; + destStream[encodedIndex] = DLE_CHAR; + } + } + else { + destStream[encodedIndex] = nextByte; + } + ++encodedIndex; + ++sourceIndex; + } + + if (sourceIndex == sourceLen and encodedIndex < maxDestLen) { + if (addStxEtx) { + destStream[encodedIndex] = ETX_CHAR; + ++encodedIndex; + } + *encodedLen = encodedIndex; + return RETURN_OK; + } + else { + return STREAM_TOO_SHORT; + } +} + +ReturnValue_t DleEncoder::decode(const uint8_t *sourceStream, + size_t sourceStreamLen, size_t *readLen, uint8_t *destStream, + size_t maxDestStreamlen, size_t *decodedLen) { + size_t encodedIndex = 0, decodedIndex = 0; + uint8_t nextByte; + if (*sourceStream != STX_CHAR) { + return DECODING_ERROR; + } + ++encodedIndex; + + while ((encodedIndex < sourceStreamLen) && (decodedIndex < maxDestStreamlen) + && (sourceStream[encodedIndex] != ETX_CHAR) + && (sourceStream[encodedIndex] != STX_CHAR)) { + if (sourceStream[encodedIndex] == DLE_CHAR) { + nextByte = sourceStream[encodedIndex + 1]; + // The next byte is a DLE character that was escaped by another + // DLE character, so we can write it to the destination stream. + if (nextByte == DLE_CHAR) { + destStream[decodedIndex] = nextByte; + } + else { + /* The next byte is a STX, DTX or 0x0D character which + * was escaped by a DLE character. The actual byte was + * also encoded by adding + 0x40 to prevent having control chars, + * in the stream at all, so we convert it back. */ + if (nextByte == 0x42 or nextByte == 0x43 or nextByte == 0x4D) { + destStream[decodedIndex] = nextByte - 0x40; + } + else { + return DECODING_ERROR; + } + } + ++encodedIndex; + } + else { + destStream[decodedIndex] = sourceStream[encodedIndex]; + } + + ++encodedIndex; + ++decodedIndex; + } + + if (sourceStream[encodedIndex] != ETX_CHAR) { + *readLen = ++encodedIndex; + return DECODING_ERROR; + } + else { + *readLen = ++encodedIndex; + *decodedLen = decodedIndex; + return RETURN_OK; + } +} + From 02be87aa03f0919d7f8ba629d6afc7fb9bd02076 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 27 Aug 2020 15:57:47 +0200 Subject: [PATCH 263/653] init after task creation moved to task functionality --- osal/FreeRTOS/PeriodicTask.cpp | 281 +++++++++++++++++---------------- osal/FreeRTOS/PeriodicTask.h | 256 +++++++++++++++--------------- 2 files changed, 271 insertions(+), 266 deletions(-) diff --git a/osal/FreeRTOS/PeriodicTask.cpp b/osal/FreeRTOS/PeriodicTask.cpp index ce981877..f99e8a4e 100644 --- a/osal/FreeRTOS/PeriodicTask.cpp +++ b/osal/FreeRTOS/PeriodicTask.cpp @@ -1,138 +1,143 @@ -#include "PeriodicTask.h" - -#include "../../serviceinterface/ServiceInterfaceStream.h" -#include "../../tasks/ExecutableObjectIF.h" - -PeriodicTask::PeriodicTask(const char *name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod setPeriod, - TaskDeadlineMissedFunction deadlineMissedFunc) : - started(false), handle(NULL), period(setPeriod), deadlineMissedFunc( - deadlineMissedFunc) -{ - configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); - BaseType_t status = xTaskCreate(taskEntryPoint, name, - stackSize, this, setPriority, &handle); - if(status != pdPASS){ - sif::debug << "PeriodicTask Insufficient heap memory remaining. " - "Status: " << status << std::endl; - } - -} - -PeriodicTask::~PeriodicTask(void) { - //Do not delete objects, we were responsible for ptrs only. -} - -void PeriodicTask::taskEntryPoint(void* argument) { - // The argument is re-interpreted as PeriodicTask. The Task object is - // global, so it is found from any place. - PeriodicTask *originalTask(reinterpret_cast(argument)); - /* Task should not start until explicitly requested, - * but in FreeRTOS, tasks start as soon as they are created if the scheduler - * is running but not if the scheduler is not running. - * To be able to accommodate both cases we check a member which is set in - * #startTask(). If it is not set and we get here, the scheduler was started - * before #startTask() was called and we need to suspend if it is set, - * the scheduler was not running before #startTask() was called and we - * can continue */ - - if (not originalTask->started) { - vTaskSuspend(NULL); - } - - originalTask->taskFunctionality(); - sif::debug << "Polling task " << originalTask->handle - << " returned from taskFunctionality." << std::endl; -} - -ReturnValue_t PeriodicTask::startTask() { - started = true; - - // We must not call resume if scheduler is not started yet - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { - vTaskResume(handle); - } - - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) { - vTaskDelay(pdMS_TO_TICKS(ms)); - return HasReturnvaluesIF::RETURN_OK; -} - -void PeriodicTask::taskFunctionality() { - TickType_t xLastWakeTime; - const TickType_t xPeriod = pdMS_TO_TICKS(this->period * 1000.); - /* The xLastWakeTime variable needs to be initialized with the current tick - count. Note that this is the only time the variable is written to - explicitly. After this assignment, xLastWakeTime is updated automatically - internally within vTaskDelayUntil(). */ - xLastWakeTime = xTaskGetTickCount(); - /* Enter the loop that defines the task behavior. */ - for (;;) { - for (auto const& object: objectList) { - object->performOperation(); - } - - checkMissedDeadline(xLastWakeTime, xPeriod); - - vTaskDelayUntil(&xLastWakeTime, xPeriod); - - } -} - -ReturnValue_t PeriodicTask::addComponent(object_id_t object) { - ExecutableObjectIF* newObject = objectManager->get( - object); - if (newObject == nullptr) { - sif::error << "PeriodicTask::addComponent: Invalid object. Make sure" - "it implement ExecutableObjectIF" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - objectList.push_back(newObject); - newObject->setTaskIF(this); - - return HasReturnvaluesIF::RETURN_OK; -} - -uint32_t PeriodicTask::getPeriodMs() const { - return period * 1000; -} - -void PeriodicTask::checkMissedDeadline(const TickType_t xLastWakeTime, - const TickType_t interval) { - /* Check whether deadline was missed while also taking overflows - * into account. Drawing this on paper with a timeline helps to understand - * it. */ - TickType_t currentTickCount = xTaskGetTickCount(); - TickType_t timeToWake = xLastWakeTime + interval; - // Time to wake has not overflown. - if(timeToWake > xLastWakeTime) { - /* If the current time has overflown exclusively or the current - * tick count is simply larger than the time to wake, a deadline was - * missed */ - if((currentTickCount < xLastWakeTime) or (currentTickCount > timeToWake)) { - handleMissedDeadline(); - } - } - /* Time to wake has overflown. A deadline was missed if the current time - * is larger than the time to wake */ - else if((timeToWake < xLastWakeTime) and (currentTickCount > timeToWake)) { - handleMissedDeadline(); - } -} - -TaskHandle_t PeriodicTask::getTaskHandle() { - return handle; -} - -void PeriodicTask::handleMissedDeadline() { -#ifdef DEBUG - sif::warning << "PeriodicTask: " << pcTaskGetName(NULL) << - " missed deadline!\n" << std::flush; -#endif - if(deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); - } -} +#include "PeriodicTask.h" + +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../tasks/ExecutableObjectIF.h" + +PeriodicTask::PeriodicTask(const char *name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod setPeriod, + TaskDeadlineMissedFunction deadlineMissedFunc) : + started(false), handle(NULL), period(setPeriod), deadlineMissedFunc( + deadlineMissedFunc) +{ + configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); + BaseType_t status = xTaskCreate(taskEntryPoint, name, + stackSize, this, setPriority, &handle); + if(status != pdPASS){ + sif::debug << "PeriodicTask Insufficient heap memory remaining. " + "Status: " << status << std::endl; + } + +} + +PeriodicTask::~PeriodicTask(void) { + //Do not delete objects, we were responsible for ptrs only. +} + +void PeriodicTask::taskEntryPoint(void* argument) { + // The argument is re-interpreted as PeriodicTask. The Task object is + // global, so it is found from any place. + PeriodicTask *originalTask(reinterpret_cast(argument)); + /* Task should not start until explicitly requested, + * but in FreeRTOS, tasks start as soon as they are created if the scheduler + * is running but not if the scheduler is not running. + * To be able to accommodate both cases we check a member which is set in + * #startTask(). If it is not set and we get here, the scheduler was started + * before #startTask() was called and we need to suspend if it is set, + * the scheduler was not running before #startTask() was called and we + * can continue */ + + if (not originalTask->started) { + vTaskSuspend(NULL); + } + + originalTask->taskFunctionality(); + sif::debug << "Polling task " << originalTask->handle + << " returned from taskFunctionality." << std::endl; +} + +ReturnValue_t PeriodicTask::startTask() { + started = true; + + // We must not call resume if scheduler is not started yet + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + vTaskResume(handle); + } + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) { + vTaskDelay(pdMS_TO_TICKS(ms)); + return HasReturnvaluesIF::RETURN_OK; +} + +void PeriodicTask::taskFunctionality() { + TickType_t xLastWakeTime; + const TickType_t xPeriod = pdMS_TO_TICKS(this->period * 1000.); + + for (auto const& object: objectList) { + object->initializeAfterTaskCreation(); + } + + /* The xLastWakeTime variable needs to be initialized with the current tick + count. Note that this is the only time the variable is written to + explicitly. After this assignment, xLastWakeTime is updated automatically + internally within vTaskDelayUntil(). */ + xLastWakeTime = xTaskGetTickCount(); + /* Enter the loop that defines the task behavior. */ + for (;;) { + for (auto const& object: objectList) { + object->performOperation(); + } + + checkMissedDeadline(xLastWakeTime, xPeriod); + + vTaskDelayUntil(&xLastWakeTime, xPeriod); + + } +} + +ReturnValue_t PeriodicTask::addComponent(object_id_t object) { + ExecutableObjectIF* newObject = objectManager->get( + object); + if (newObject == nullptr) { + sif::error << "PeriodicTask::addComponent: Invalid object. Make sure" + "it implement ExecutableObjectIF" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + objectList.push_back(newObject); + newObject->setTaskIF(this); + + return HasReturnvaluesIF::RETURN_OK; +} + +uint32_t PeriodicTask::getPeriodMs() const { + return period * 1000; +} + +void PeriodicTask::checkMissedDeadline(const TickType_t xLastWakeTime, + const TickType_t interval) { + /* Check whether deadline was missed while also taking overflows + * into account. Drawing this on paper with a timeline helps to understand + * it. */ + TickType_t currentTickCount = xTaskGetTickCount(); + TickType_t timeToWake = xLastWakeTime + interval; + // Time to wake has not overflown. + if(timeToWake > xLastWakeTime) { + /* If the current time has overflown exclusively or the current + * tick count is simply larger than the time to wake, a deadline was + * missed */ + if((currentTickCount < xLastWakeTime) or (currentTickCount > timeToWake)) { + handleMissedDeadline(); + } + } + /* Time to wake has overflown. A deadline was missed if the current time + * is larger than the time to wake */ + else if((timeToWake < xLastWakeTime) and (currentTickCount > timeToWake)) { + handleMissedDeadline(); + } +} + +TaskHandle_t PeriodicTask::getTaskHandle() { + return handle; +} + +void PeriodicTask::handleMissedDeadline() { +#ifdef DEBUG + sif::warning << "PeriodicTask: " << pcTaskGetName(NULL) << + " missed deadline!\n" << std::flush; +#endif + if(deadlineMissedFunc != nullptr) { + this->deadlineMissedFunc(); + } +} diff --git a/osal/FreeRTOS/PeriodicTask.h b/osal/FreeRTOS/PeriodicTask.h index ea170aba..1cdc3df7 100644 --- a/osal/FreeRTOS/PeriodicTask.h +++ b/osal/FreeRTOS/PeriodicTask.h @@ -1,128 +1,128 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_PERIODICTASK_H_ -#define FRAMEWORK_OSAL_FREERTOS_PERIODICTASK_H_ - -#include "../../objectmanager/ObjectManagerIF.h" -#include "../../tasks/PeriodicTaskIF.h" -#include "../../tasks/Typedef.h" -#include "FreeRTOSTaskIF.h" - - -#include -#include - -#include - -class ExecutableObjectIF; - -/** - * @brief This class represents a specialized task for - * periodic activities of multiple objects. - * @ingroup task_handling - */ -class PeriodicTask: public PeriodicTaskIF, public FreeRTOSTaskIF { -public: - /** - * Keep in Mind that you need to call before this vTaskStartScheduler()! - * A lot of task parameters are set in "FreeRTOSConfig.h". - * TODO: why does this need to be called before vTaskStartScheduler? - * @details - * The class is initialized without allocated objects. - * These need to be added with #addComponent. - * @param priority - * Sets the priority of a task. Values depend on freeRTOS configuration, - * high number means high priority. - * @param stack_size - * The stack size reserved by the operating system for the task. - * @param setPeriod - * The length of the period with which the task's - * functionality will be executed. It is expressed in clock ticks. - * @param setDeadlineMissedFunc - * The function pointer to the deadline missed function that shall - * be assigned. - */ - PeriodicTask(TaskName name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod setPeriod, - TaskDeadlineMissedFunction deadlineMissedFunc); - /** - * @brief Currently, the executed object's lifetime is not coupled with - * the task object's lifetime, so the destructor is empty. - */ - virtual ~PeriodicTask(void); - - /** - * @brief The method to start the task. - * @details The method starts the task with the respective system call. - * Entry point is the taskEntryPoint method described below. - * The address of the task object is passed as an argument - * to the system call. - */ - ReturnValue_t startTask() override; - /** - * Adds an object to the list of objects to be executed. - * The objects are executed in the order added. - * @param object Id of the object to add. - * @return - * -@c RETURN_OK on success - * -@c RETURN_FAILED if the object could not be added. - */ - ReturnValue_t addComponent(object_id_t object) override; - - uint32_t getPeriodMs() const override; - - ReturnValue_t sleepFor(uint32_t ms) override; - - TaskHandle_t getTaskHandle() override; -protected: - bool started; - TaskHandle_t handle; - - //! Typedef for the List of objects. - typedef std::vector ObjectList; - /** - * @brief This attribute holds a list of objects to be executed. - */ - ObjectList objectList; - /** - * @brief The period of the task. - * @details - * The period determines the frequency of the task's execution. - * It is expressed in clock ticks. - */ - TaskPeriod period; - /** - * @brief The pointer to the deadline-missed function. - * @details - * This pointer stores the function that is executed if the task's deadline - * is missed so each may react individually on a timing failure. - * The pointer may be NULL, then nothing happens on missing the deadline. - * The deadline is equal to the next execution of the periodic task. - */ - void (*deadlineMissedFunc)(void); - /** - * @brief This is the function executed in the new task's context. - * @details - * It converts the argument back to the thread object type and copies the - * class instance to the task context. The taskFunctionality method is - * called afterwards. - * @param A pointer to the task object itself is passed as argument. - */ - - static void taskEntryPoint(void* argument); - /** - * @brief The function containing the actual functionality of the task. - * @details - * The method sets and starts the task's period, then enters a loop that is - * repeated as long as the isRunning attribute is true. Within the loop, - * all performOperation methods of the added objects are called. - * Afterwards the checkAndRestartPeriod system call blocks the task until - * the next period. - * On missing the deadline, the deadlineMissedFunction is executed. - */ - void taskFunctionality(void); - - void checkMissedDeadline(const TickType_t xLastWakeTime, - const TickType_t interval); - void handleMissedDeadline(); -}; - -#endif /* PERIODICTASK_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_PERIODICTASK_H_ +#define FRAMEWORK_OSAL_FREERTOS_PERIODICTASK_H_ + +#include "../../osal/FreeRTOS/FreeRTOSTaskIF.h" +#include "../../objectmanager/ObjectManagerIF.h" +#include "../../tasks/PeriodicTaskIF.h" +#include "../../tasks/Typedef.h" + + +#include +#include + +#include + +class ExecutableObjectIF; + +/** + * @brief This class represents a specialized task for + * periodic activities of multiple objects. + * @ingroup task_handling + */ +class PeriodicTask: public PeriodicTaskIF, public FreeRTOSTaskIF { +public: + /** + * Keep in Mind that you need to call before this vTaskStartScheduler()! + * A lot of task parameters are set in "FreeRTOSConfig.h". + * TODO: why does this need to be called before vTaskStartScheduler? + * @details + * The class is initialized without allocated objects. + * These need to be added with #addComponent. + * @param priority + * Sets the priority of a task. Values depend on freeRTOS configuration, + * high number means high priority. + * @param stack_size + * The stack size reserved by the operating system for the task. + * @param setPeriod + * The length of the period with which the task's + * functionality will be executed. It is expressed in clock ticks. + * @param setDeadlineMissedFunc + * The function pointer to the deadline missed function that shall + * be assigned. + */ + PeriodicTask(TaskName name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod setPeriod, + TaskDeadlineMissedFunction deadlineMissedFunc); + /** + * @brief Currently, the executed object's lifetime is not coupled with + * the task object's lifetime, so the destructor is empty. + */ + virtual ~PeriodicTask(void); + + /** + * @brief The method to start the task. + * @details The method starts the task with the respective system call. + * Entry point is the taskEntryPoint method described below. + * The address of the task object is passed as an argument + * to the system call. + */ + ReturnValue_t startTask() override; + /** + * Adds an object to the list of objects to be executed. + * The objects are executed in the order added. + * @param object Id of the object to add. + * @return + * -@c RETURN_OK on success + * -@c RETURN_FAILED if the object could not be added. + */ + ReturnValue_t addComponent(object_id_t object) override; + + uint32_t getPeriodMs() const override; + + ReturnValue_t sleepFor(uint32_t ms) override; + + TaskHandle_t getTaskHandle() override; +protected: + bool started; + TaskHandle_t handle; + + //! Typedef for the List of objects. + typedef std::vector ObjectList; + /** + * @brief This attribute holds a list of objects to be executed. + */ + ObjectList objectList; + /** + * @brief The period of the task. + * @details + * The period determines the frequency of the task's execution. + * It is expressed in clock ticks. + */ + TaskPeriod period; + /** + * @brief The pointer to the deadline-missed function. + * @details + * This pointer stores the function that is executed if the task's deadline + * is missed so each may react individually on a timing failure. + * The pointer may be NULL, then nothing happens on missing the deadline. + * The deadline is equal to the next execution of the periodic task. + */ + void (*deadlineMissedFunc)(void); + /** + * @brief This is the function executed in the new task's context. + * @details + * It converts the argument back to the thread object type and copies the + * class instance to the task context. The taskFunctionality method is + * called afterwards. + * @param A pointer to the task object itself is passed as argument. + */ + + static void taskEntryPoint(void* argument); + /** + * @brief The function containing the actual functionality of the task. + * @details + * The method sets and starts the task's period, then enters a loop that is + * repeated as long as the isRunning attribute is true. Within the loop, + * all performOperation methods of the added objects are called. + * Afterwards the checkAndRestartPeriod system call blocks the task until + * the next period. + * On missing the deadline, the deadlineMissedFunction is executed. + */ + void taskFunctionality(void); + + void checkMissedDeadline(const TickType_t xLastWakeTime, + const TickType_t interval); + void handleMissedDeadline(); +}; + +#endif /* PERIODICTASK_H_ */ From 66cf2d3559b93ff78ebb043dafc4ea2abb4d6efa Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 27 Aug 2020 16:05:31 +0200 Subject: [PATCH 264/653] timeslot update for FreeRTOS --- devicehandlers/FixedSequenceSlot.cpp | 20 -- osal/FreeRTOS/FixedTimeslotTask.cpp | 328 +++++++++--------- osal/FreeRTOS/FixedTimeslotTask.h | 203 ++++++----- tasks/FixedSequenceSlot.cpp | 17 + {devicehandlers => tasks}/FixedSequenceSlot.h | 117 +++---- .../FixedSlotSequence.cpp | 270 +++++++------- {devicehandlers => tasks}/FixedSlotSequence.h | 311 +++++++++-------- 7 files changed, 647 insertions(+), 619 deletions(-) delete mode 100644 devicehandlers/FixedSequenceSlot.cpp create mode 100644 tasks/FixedSequenceSlot.cpp rename {devicehandlers => tasks}/FixedSequenceSlot.h (56%) rename {devicehandlers => tasks}/FixedSlotSequence.cpp (61%) rename {devicehandlers => tasks}/FixedSlotSequence.h (90%) diff --git a/devicehandlers/FixedSequenceSlot.cpp b/devicehandlers/FixedSequenceSlot.cpp deleted file mode 100644 index 667aba1d..00000000 --- a/devicehandlers/FixedSequenceSlot.cpp +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @file PollingSlot.cpp - * @brief This file defines the PollingSlot class. - * @date 19.12.2012 - * @author baetz - */ - -#include "FixedSequenceSlot.h" -#include "../objectmanager/SystemObjectIF.h" -#include - -FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime, - int8_t setSequenceId, PeriodicTaskIF* executingTask) : - handler(NULL), pollingTimeMs(setTime), opcode(setSequenceId) { - handler = objectManager->get(handlerId); - handler->setTaskIF(executingTask); -} - -FixedSequenceSlot::~FixedSequenceSlot() {} - diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index 4873dde4..772c4bca 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -1,162 +1,166 @@ -#include "FixedTimeslotTask.h" - -#include "../../serviceinterface/ServiceInterfaceStream.h" - -uint32_t FixedTimeslotTask::deadlineMissedCount = 0; -const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE; - -FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod overallPeriod, - void (*setDeadlineMissedFunc)()) : - started(false), handle(NULL), pst(overallPeriod * 1000) { - configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); - xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle); - // All additional attributes are applied to the object. - this->deadlineMissedFunc = setDeadlineMissedFunc; -} - -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)); - /* Task should not start until explicitly requested, - * but in FreeRTOS, tasks start as soon as they are created if the scheduler - * is running but not if the scheduler is not running. - * To be able to accommodate both cases we check a member which is set in - * #startTask(). If it is not set and we get here, the scheduler was started - * before #startTask() was called and we need to suspend if it is set, - * the scheduler was not running before #startTask() was called and we - * can continue */ - - if (not originalTask->started) { - vTaskSuspend(NULL); - } - - originalTask->taskFunctionality(); - sif::debug << "Polling task " << originalTask->handle - << " returned from taskFunctionality." << std::endl; -} - -void FixedTimeslotTask::missedDeadlineCounter() { - FixedTimeslotTask::deadlineMissedCount++; - if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) { - sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount - << " deadlines." << std::endl; - } -} - -ReturnValue_t FixedTimeslotTask::startTask() { - started = true; - - // We must not call resume if scheduler is not started yet - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { - vTaskResume(handle); - } - - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, - uint32_t slotTimeMs, int8_t executionStep) { - if (objectManager->get(componentId) != nullptr) { - pst.addSlot(componentId, slotTimeMs, executionStep, this); - return HasReturnvaluesIF::RETURN_OK; - } - - sif::error << "Component " << std::hex << componentId << - " not found, not adding it to pst" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; -} - -uint32_t FixedTimeslotTask::getPeriodMs() const { - return pst.getLengthMs(); -} - -ReturnValue_t FixedTimeslotTask::checkSequence() const { - return pst.checkSequence(); -} - -void FixedTimeslotTask::taskFunctionality() { - // A local iterator for the Polling Sequence Table is created to find the - // start time for the first entry. - auto slotListIter = pst.current; - - //The start time for the first entry is read. - uint32_t intervalMs = slotListIter->pollingTimeMs; - TickType_t interval = pdMS_TO_TICKS(intervalMs); - - TickType_t xLastWakeTime; - /* The xLastWakeTime variable needs to be initialized with the current tick - count. Note that this is the only time the variable is written to - explicitly. After this assignment, xLastWakeTime is updated automatically - internally within vTaskDelayUntil(). */ - xLastWakeTime = xTaskGetTickCount(); - - // wait for first entry's start time - if(interval > 0) { - vTaskDelayUntil(&xLastWakeTime, interval); - } - - /* Enter the loop that defines the task behavior. */ - for (;;) { - //The component for this slot is executed and the next one is chosen. - this->pst.executeAndAdvance(); - if (not pst.slotFollowsImmediately()) { - // Get the interval till execution of the next slot. - intervalMs = this->pst.getIntervalToPreviousSlotMs(); - interval = pdMS_TO_TICKS(intervalMs); - - checkMissedDeadline(xLastWakeTime, interval); - - // Wait for the interval. This exits immediately if a deadline was - // missed while also updating the last wake time. - vTaskDelayUntil(&xLastWakeTime, interval); - } - } -} - -void FixedTimeslotTask::checkMissedDeadline(const TickType_t xLastWakeTime, - const TickType_t interval) { - /* Check whether deadline was missed while also taking overflows - * into account. Drawing this on paper with a timeline helps to understand - * it. */ - TickType_t currentTickCount = xTaskGetTickCount(); - TickType_t timeToWake = xLastWakeTime + interval; - // Time to wake has not overflown. - if(timeToWake > xLastWakeTime) { - /* If the current time has overflown exclusively or the current - * tick count is simply larger than the time to wake, a deadline was - * missed */ - if((currentTickCount < xLastWakeTime) or (currentTickCount > timeToWake)) { - handleMissedDeadline(); - } - } - /* Time to wake has overflown. A deadline was missed if the current time - * is larger than the time to wake */ - else if((timeToWake < xLastWakeTime) and (currentTickCount > timeToWake)) { - handleMissedDeadline(); - } -} - -void FixedTimeslotTask::handleMissedDeadline() { -#ifdef DEBUG - sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) << - " missed deadline!\n" << std::flush; -#endif - if(deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); - } -} - -ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { - vTaskDelay(pdMS_TO_TICKS(ms)); - return HasReturnvaluesIF::RETURN_OK; -} - -TaskHandle_t FixedTimeslotTask::getTaskHandle() { - return handle; -} +#include "FixedTimeslotTask.h" + +#include "../../serviceinterface/ServiceInterfaceStream.h" + +uint32_t FixedTimeslotTask::deadlineMissedCount = 0; +const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE; + +FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod overallPeriod, + void (*setDeadlineMissedFunc)()) : + started(false), handle(nullptr), pst(overallPeriod * 1000) { + configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); + xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle); + // All additional attributes are applied to the object. + this->deadlineMissedFunc = setDeadlineMissedFunc; +} + +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)); + /* Task should not start until explicitly requested, + * but in FreeRTOS, tasks start as soon as they are created if the scheduler + * is running but not if the scheduler is not running. + * To be able to accommodate both cases we check a member which is set in + * #startTask(). If it is not set and we get here, the scheduler was started + * before #startTask() was called and we need to suspend if it is set, + * the scheduler was not running before #startTask() was called and we + * can continue */ + + if (not originalTask->started) { + vTaskSuspend(NULL); + } + + originalTask->taskFunctionality(); + sif::debug << "Polling task " << originalTask->handle + << " returned from taskFunctionality." << std::endl; +} + +void FixedTimeslotTask::missedDeadlineCounter() { + FixedTimeslotTask::deadlineMissedCount++; + if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) { + sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount + << " deadlines." << std::endl; + } +} + +ReturnValue_t FixedTimeslotTask::startTask() { + started = true; + + // We must not call resume if scheduler is not started yet + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + vTaskResume(handle); + } + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, + uint32_t slotTimeMs, int8_t executionStep) { + ExecutableObjectIF* handler = + objectManager->get(componentId); + if (handler != nullptr) { + pst.addSlot(componentId, slotTimeMs, executionStep, handler, this); + return HasReturnvaluesIF::RETURN_OK; + } + + sif::error << "Component " << std::hex << componentId << + " not found, not adding it to pst" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; +} + +uint32_t FixedTimeslotTask::getPeriodMs() const { + return pst.getLengthMs(); +} + +ReturnValue_t FixedTimeslotTask::checkSequence() const { + return pst.checkSequence(); +} + +void FixedTimeslotTask::taskFunctionality() { + // A local iterator for the Polling Sequence Table is created to find the + // start time for the first entry. + auto slotListIter = pst.current; + + pst.intializeSequenceAfterTaskCreation(); + + //The start time for the first entry is read. + uint32_t intervalMs = slotListIter->pollingTimeMs; + TickType_t interval = pdMS_TO_TICKS(intervalMs); + + TickType_t xLastWakeTime; + /* The xLastWakeTime variable needs to be initialized with the current tick + count. Note that this is the only time the variable is written to + explicitly. After this assignment, xLastWakeTime is updated automatically + internally within vTaskDelayUntil(). */ + xLastWakeTime = xTaskGetTickCount(); + + // wait for first entry's start time + if(interval > 0) { + vTaskDelayUntil(&xLastWakeTime, interval); + } + + /* Enter the loop that defines the task behavior. */ + for (;;) { + //The component for this slot is executed and the next one is chosen. + this->pst.executeAndAdvance(); + if (not pst.slotFollowsImmediately()) { + // Get the interval till execution of the next slot. + intervalMs = this->pst.getIntervalToPreviousSlotMs(); + interval = pdMS_TO_TICKS(intervalMs); + + checkMissedDeadline(xLastWakeTime, interval); + + // Wait for the interval. This exits immediately if a deadline was + // missed while also updating the last wake time. + vTaskDelayUntil(&xLastWakeTime, interval); + } + } +} + +void FixedTimeslotTask::checkMissedDeadline(const TickType_t xLastWakeTime, + const TickType_t interval) { + /* Check whether deadline was missed while also taking overflows + * into account. Drawing this on paper with a timeline helps to understand + * it. */ + TickType_t currentTickCount = xTaskGetTickCount(); + TickType_t timeToWake = xLastWakeTime + interval; + // Time to wake has not overflown. + if(timeToWake > xLastWakeTime) { + /* If the current time has overflown exclusively or the current + * tick count is simply larger than the time to wake, a deadline was + * missed */ + if((currentTickCount < xLastWakeTime) or (currentTickCount > timeToWake)) { + handleMissedDeadline(); + } + } + /* Time to wake has overflown. A deadline was missed if the current time + * is larger than the time to wake */ + else if((timeToWake < xLastWakeTime) and (currentTickCount > timeToWake)) { + handleMissedDeadline(); + } +} + +void FixedTimeslotTask::handleMissedDeadline() { +#ifdef DEBUG + sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) << + " missed deadline!\n" << std::flush; +#endif + if(deadlineMissedFunc != nullptr) { + this->deadlineMissedFunc(); + } +} + +ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { + vTaskDelay(pdMS_TO_TICKS(ms)); + return HasReturnvaluesIF::RETURN_OK; +} + +TaskHandle_t FixedTimeslotTask::getTaskHandle() { + return handle; +} diff --git a/osal/FreeRTOS/FixedTimeslotTask.h b/osal/FreeRTOS/FixedTimeslotTask.h index 84264c4c..42af14b8 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.h +++ b/osal/FreeRTOS/FixedTimeslotTask.h @@ -1,102 +1,101 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ -#define FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ - -#include "FreeRTOSTaskIF.h" -#include "../../devicehandlers/FixedSlotSequence.h" -#include "../../tasks/FixedTimeslotTaskIF.h" -#include "../../tasks/Typedef.h" - - -#include -#include - -class FixedTimeslotTask: public FixedTimeslotTaskIF, public FreeRTOSTaskIF { -public: - - /** - * Keep in mind that you need to call before vTaskStartScheduler()! - * A lot of task parameters are set in "FreeRTOSConfig.h". - * @param name Name of the task, lenght limited by configMAX_TASK_NAME_LEN - * @param setPriority Number of priorities specified by - * configMAX_PRIORITIES. High taskPriority_ number means high priority. - * @param setStack Stack size in words (not bytes!). - * Lower limit specified by configMINIMAL_STACK_SIZE - * @param overallPeriod Period in seconds. - * @param setDeadlineMissedFunc Callback if a deadline was missed. - * @return Pointer to the newly created task. - */ - FixedTimeslotTask(TaskName name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod overallPeriod, - void (*setDeadlineMissedFunc)()); - - /** - * @brief The destructor of the class. - * @details - * The destructor frees all heap memory that was allocated on thread - * initialization for the PST and the device handlers. This is done by - * calling the PST's destructor. - */ - virtual ~FixedTimeslotTask(void); - - ReturnValue_t startTask(void); - /** - * This static function can be used as #deadlineMissedFunc. - * It counts missedDeadlines and prints the number of missed deadlines - * every 10th time. - */ - static void missedDeadlineCounter(); - /** - * A helper variable to count missed deadlines. - */ - static uint32_t deadlineMissedCount; - - ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, - int8_t executionStep) override; - - uint32_t getPeriodMs() const override; - - ReturnValue_t checkSequence() const override; - - ReturnValue_t sleepFor(uint32_t ms) override; - - TaskHandle_t getTaskHandle() override; - -protected: - bool started; - TaskHandle_t handle; - - FixedSlotSequence pst; - - /** - * @brief This attribute holds a function pointer that is executed when - * a deadline was missed. - * @details - * Another function may be announced to determine the actions to perform - * when a deadline was missed. Currently, only one function for missing - * any deadline is allowed. If not used, it shall be declared NULL. - */ - void (*deadlineMissedFunc)(void); - /** - * @brief This is the entry point for a new task. - * @details - * This method starts the task by calling taskFunctionality(), as soon as - * all requirements (task scheduler has started and startTask() - * has been called) are met. - */ - static void taskEntryPoint(void* argument); - - /** - * @brief This function holds the main functionality of the thread. - * @details - * Core function holding the main functionality of the task - * It links the functionalities provided by FixedSlotSequence with the - * OS's System Calls to keep the timing of the periods. - */ - void taskFunctionality(void); - - void checkMissedDeadline(const TickType_t xLastWakeTime, - const TickType_t interval); - void handleMissedDeadline(); -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ +#define FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ + +#include "../../osal/FreeRTOS/FreeRTOSTaskIF.h" +#include "../../tasks/FixedSlotSequence.h" +#include "../../tasks/FixedTimeslotTaskIF.h" +#include "../../tasks/Typedef.h" + +#include +#include + +class FixedTimeslotTask: public FixedTimeslotTaskIF, public FreeRTOSTaskIF { +public: + + /** + * Keep in mind that you need to call before vTaskStartScheduler()! + * A lot of task parameters are set in "FreeRTOSConfig.h". + * @param name Name of the task, lenght limited by configMAX_TASK_NAME_LEN + * @param setPriority Number of priorities specified by + * configMAX_PRIORITIES. High taskPriority_ number means high priority. + * @param setStack Stack size in words (not bytes!). + * Lower limit specified by configMINIMAL_STACK_SIZE + * @param overallPeriod Period in seconds. + * @param setDeadlineMissedFunc Callback if a deadline was missed. + * @return Pointer to the newly created task. + */ + FixedTimeslotTask(TaskName name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod overallPeriod, + void (*setDeadlineMissedFunc)()); + + /** + * @brief The destructor of the class. + * @details + * The destructor frees all heap memory that was allocated on thread + * initialization for the PST and the device handlers. This is done by + * calling the PST's destructor. + */ + virtual ~FixedTimeslotTask(void); + + ReturnValue_t startTask(void); + /** + * This static function can be used as #deadlineMissedFunc. + * It counts missedDeadlines and prints the number of missed deadlines + * every 10th time. + */ + static void missedDeadlineCounter(); + /** + * A helper variable to count missed deadlines. + */ + static uint32_t deadlineMissedCount; + + ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, + int8_t executionStep) override; + + uint32_t getPeriodMs() const override; + + ReturnValue_t checkSequence() const override; + + ReturnValue_t sleepFor(uint32_t ms) override; + + TaskHandle_t getTaskHandle() override; + +protected: + bool started; + TaskHandle_t handle; + + FixedSlotSequence pst; + + /** + * @brief This attribute holds a function pointer that is executed when + * a deadline was missed. + * @details + * Another function may be announced to determine the actions to perform + * when a deadline was missed. Currently, only one function for missing + * any deadline is allowed. If not used, it shall be declared NULL. + */ + void (*deadlineMissedFunc)(void); + /** + * @brief This is the entry point for a new task. + * @details + * This method starts the task by calling taskFunctionality(), as soon as + * all requirements (task scheduler has started and startTask() + * has been called) are met. + */ + static void taskEntryPoint(void* argument); + + /** + * @brief This function holds the main functionality of the thread. + * @details + * Core function holding the main functionality of the task + * It links the functionalities provided by FixedSlotSequence with the + * OS's System Calls to keep the timing of the periods. + */ + void taskFunctionality(void); + + void checkMissedDeadline(const TickType_t xLastWakeTime, + const TickType_t interval); + void handleMissedDeadline(); +}; + +#endif /* POLLINGTASK_H_ */ diff --git a/tasks/FixedSequenceSlot.cpp b/tasks/FixedSequenceSlot.cpp new file mode 100644 index 00000000..5fe49523 --- /dev/null +++ b/tasks/FixedSequenceSlot.cpp @@ -0,0 +1,17 @@ +#include "FixedSequenceSlot.h" +#include "../objectmanager/SystemObjectIF.h" +#include + +FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime, + int8_t setSequenceId, ExecutableObjectIF* executableObject, + PeriodicTaskIF* executingTask) : + pollingTimeMs(setTime), opcode(setSequenceId) { + if(executableObject == nullptr) { + return; + } + this->executableObject = executableObject; + this->executableObject->setTaskIF(executingTask); +} + +FixedSequenceSlot::~FixedSequenceSlot() {} + diff --git a/devicehandlers/FixedSequenceSlot.h b/tasks/FixedSequenceSlot.h similarity index 56% rename from devicehandlers/FixedSequenceSlot.h rename to tasks/FixedSequenceSlot.h index 73504955..9cf5894c 100644 --- a/devicehandlers/FixedSequenceSlot.h +++ b/tasks/FixedSequenceSlot.h @@ -1,60 +1,57 @@ -/** - * @file FixedSequenceSlot.h - * @brief This file defines the PollingSlot class. - * @date 19.12.2012 - * @author baetz - */ - -#ifndef FIXEDSEQUENCESLOT_H_ -#define FIXEDSEQUENCESLOT_H_ - -#include "../objectmanager/ObjectManagerIF.h" -#include "../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. - */ -class FixedSequenceSlot { -public: - FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs, - int8_t setSequenceId, PeriodicTaskIF* executingTask ); - virtual ~FixedSequenceSlot(); - - /** - * @brief Handler identifies which device handler object is executed in this slot. - */ - 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 ms. - * It must be smaller than the period length of the polling sequence. - */ - uint32_t pollingTimeMs; - - /** - * @brief This value defines the type of device communication. - * - * @details The state of this value decides what communication routine is - * called in the PST executable or the device handler object. - */ - uint8_t opcode; - - /** - * @brief Operator overload for the comparison operator to - * allow sorting by polling time. - * @param fixedSequenceSlot - * @return - */ - bool operator <(const FixedSequenceSlot & fixedSequenceSlot) const { - return pollingTimeMs < fixedSequenceSlot.pollingTimeMs; - } -}; - - -#endif /* FIXEDSEQUENCESLOT_H_ */ +#ifndef FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_ +#define FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_ + +#include "../objectmanager/ObjectManagerIF.h" +#include "../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. + * @author baetz + */ +class FixedSequenceSlot { +public: + FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs, + int8_t setSequenceId, ExecutableObjectIF* executableObject, + PeriodicTaskIF* executingTask); + virtual ~FixedSequenceSlot(); + + /** + * @brief Handler identifies which object is executed in this slot. + */ + ExecutableObjectIF* executableObject = nullptr; + + /** + * @brief This attribute defines when a device handler object is executed. + * @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. + */ + uint32_t pollingTimeMs; + + /** + * @brief This value defines the type of device communication. + * + * @details The state of this value decides what communication routine is + * called in the PST executable or the device handler object. + */ + uint8_t opcode; + + /** + * @brief Operator overload for the comparison operator to + * allow sorting by polling time. + * @param fixedSequenceSlot + * @return + */ + bool operator <(const FixedSequenceSlot & fixedSequenceSlot) const { + return pollingTimeMs < fixedSequenceSlot.pollingTimeMs; + } +}; + + +#endif /* FIXEDSEQUENCESLOT_H_ */ diff --git a/devicehandlers/FixedSlotSequence.cpp b/tasks/FixedSlotSequence.cpp similarity index 61% rename from devicehandlers/FixedSlotSequence.cpp rename to tasks/FixedSlotSequence.cpp index 38d4dcea..78f512ca 100644 --- a/devicehandlers/FixedSlotSequence.cpp +++ b/tasks/FixedSlotSequence.cpp @@ -1,123 +1,147 @@ -#include "FixedSlotSequence.h" -#include "../serviceinterface/ServiceInterfaceStream.h" - -FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) : - lengthMs(setLengthMs) { - current = slotList.begin(); -} - -FixedSlotSequence::~FixedSlotSequence() { - // Call the destructor on each list entry. - slotList.clear(); -} - -void FixedSlotSequence::executeAndAdvance() { - current->handler->performOperation(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::getIntervalToNextSlotMs() { - uint32_t oldTime; - SlotListIter slotListIter = current; - // Get the pollingTimeMs of the current slot object. - oldTime = slotListIter->pollingTimeMs; - // Advance to the next object. - slotListIter++; - // Find the next interval which is not 0. - while (slotListIter != slotList.end()) { - if (oldTime != slotListIter->pollingTimeMs) { - return slotListIter->pollingTimeMs - oldTime; - } else { - slotListIter++; - } - } - // 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. - slotListIter = slotList.begin(); - return lengthMs - oldTime + slotListIter->pollingTimeMs; -} - -uint32_t FixedSlotSequence::getIntervalToPreviousSlotMs() { - uint32_t currentTime; - SlotListIter slotListIter = current; - // Get the pollingTimeMs of the current slot object. - currentTime = slotListIter->pollingTimeMs; - - //if it is the first slot, calculate difference to last slot - if (slotListIter == slotList.begin()){ - return lengthMs - (--slotList.end())->pollingTimeMs + currentTime; - } - // get previous slot - slotListIter--; - - return currentTime - slotListIter->pollingTimeMs; -} - -bool FixedSlotSequence::slotFollowsImmediately() { - uint32_t currentTime = current->pollingTimeMs; - SlotListIter fixedSequenceIter = this->current; - // Get the pollingTimeMs of the current slot object. - if (fixedSequenceIter == slotList.begin()) - return false; - fixedSequenceIter--; - if (fixedSequenceIter->pollingTimeMs == currentTime) { - return true; - } else { - return false; - } -} - -uint32_t FixedSlotSequence::getLengthMs() const { - return this->lengthMs; -} - -ReturnValue_t FixedSlotSequence::checkSequence() const { - if(slotList.empty()) { - sif::error << "Fixed Slot Sequence: Slot list is empty!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - - auto slotIt = slotList.begin(); - uint32_t count = 0; - uint32_t time = 0; - while (slotIt != slotList.end()) { - if (slotIt->handler == nullptr) { - sif::error << "FixedSlotSequene::initialize: ObjectId does not exist!" - << std::endl; - count++; - } else if (slotIt->pollingTimeMs < time) { - sif::error << "FixedSlotSequence::initialize: Time: " - << slotIt->pollingTimeMs - << " is smaller than previous with " << time << std::endl; - count++; - } else { - // All ok, print slot. - //info << "Current slot polling time: " << std::endl; - //info << std::dec << slotIt->pollingTimeMs << std::endl; - } - time = slotIt->pollingTimeMs; - slotIt++; - } - //info << "Number of elements in slot list: " - // << slotList.size() << std::endl; - 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.insert(FixedSequenceSlot(componentId, slotTimeMs, executionStep, - executingTask)); - this->current = slotList.begin(); -} +#include "FixedSlotSequence.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include + +FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) : + lengthMs(setLengthMs) { + current = slotList.begin(); +} + +FixedSlotSequence::~FixedSlotSequence() { + // Call the destructor on each list entry. + slotList.clear(); +} + +void FixedSlotSequence::executeAndAdvance() { + current->executableObject->performOperation(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::getIntervalToNextSlotMs() { + uint32_t oldTime; + SlotListIter slotListIter = current; + // Get the pollingTimeMs of the current slot object. + oldTime = slotListIter->pollingTimeMs; + // Advance to the next object. + slotListIter++; + // Find the next interval which is not 0. + while (slotListIter != slotList.end()) { + if (oldTime != slotListIter->pollingTimeMs) { + return slotListIter->pollingTimeMs - oldTime; + } else { + slotListIter++; + } + } + // 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. + slotListIter = slotList.begin(); + return lengthMs - oldTime + slotListIter->pollingTimeMs; +} + +uint32_t FixedSlotSequence::getIntervalToPreviousSlotMs() { + uint32_t currentTime; + SlotListIter slotListIter = current; + // Get the pollingTimeMs of the current slot object. + currentTime = slotListIter->pollingTimeMs; + + //if it is the first slot, calculate difference to last slot + if (slotListIter == slotList.begin()){ + return lengthMs - (--slotList.end())->pollingTimeMs + currentTime; + } + // get previous slot + slotListIter--; + + return currentTime - slotListIter->pollingTimeMs; +} + +bool FixedSlotSequence::slotFollowsImmediately() { + uint32_t currentTime = current->pollingTimeMs; + SlotListIter fixedSequenceIter = this->current; + // Get the pollingTimeMs of the current slot object. + if (fixedSequenceIter == slotList.begin()) + return false; + fixedSequenceIter--; + if (fixedSequenceIter->pollingTimeMs == currentTime) { + return true; + } else { + return false; + } +} + +uint32_t FixedSlotSequence::getLengthMs() const { + return this->lengthMs; +} + +void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs, + int8_t executionStep, ExecutableObjectIF* executableObject, + PeriodicTaskIF* executingTask) { + this->slotList.insert(FixedSequenceSlot(componentId, slotTimeMs, + executionStep, executableObject, executingTask)); + this->current = slotList.begin(); +} + +ReturnValue_t FixedSlotSequence::checkSequence() const { + if(slotList.empty()) { + sif::error << "Fixed Slot Sequence: Slot list is empty!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + uint32_t count = 0; + uint32_t time = 0; + for(const auto& slot: slotList) { + if (slot.executableObject == nullptr) { + count++; + } + else if (slot.pollingTimeMs < time) { + sif::error << "FixedSlotSequence::initialize: Time: " + << slot.pollingTimeMs << " is smaller than previous with " + << time << std::endl; + count++; + } + else { + // All ok, print slot. + //sif::info << "Current slot polling time: " << std::endl; + //sif::info << std::dec << slotIt->pollingTimeMs << std::endl; + } + time = slot.pollingTimeMs; + + } + //sif::info << "Number of elements in slot list: " + // << slotList.size() << std::endl; + if (count > 0) { + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t FixedSlotSequence::intializeSequenceAfterTaskCreation() const { + std::set uniqueObjects; + uint32_t count = 0; + for(const auto& slot: slotList) { + // Ensure that each unique object is initialized once. + if(uniqueObjects.find(slot.executableObject) == uniqueObjects.end()) { + ReturnValue_t result = + slot.executableObject->initializeAfterTaskCreation(); + if(result != HasReturnvaluesIF::RETURN_OK) { + count++; + } + uniqueObjects.emplace(slot.executableObject); + } + } + if (count > 0) { + sif::error << "FixedSlotSequence::intializeSequenceAfterTaskCreation:" + "Counted " << count << " failed initializations!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/devicehandlers/FixedSlotSequence.h b/tasks/FixedSlotSequence.h similarity index 90% rename from devicehandlers/FixedSlotSequence.h rename to tasks/FixedSlotSequence.h index be6dc2d1..8aa04a27 100644 --- a/devicehandlers/FixedSlotSequence.h +++ b/tasks/FixedSlotSequence.h @@ -1,152 +1,159 @@ -#ifndef FRAMEWORK_DEVICEHANDLERS_FIXEDSLOTSEQUENCE_H_ -#define FRAMEWORK_DEVICEHANDLERS_FIXEDSLOTSEQUENCE_H_ - -#include "FixedSequenceSlot.h" -#include "../objectmanager/SystemObject.h" -#include - -/** - * @brief This class is the representation of a Polling Sequence Table in software. - * - * @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 thepolling 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 - * which device handler shall be executed within a given polling period. - * 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 FixedSlotSequence { -public: - using SlotList = std::multiset; - using SlotListIter = std::multiset::iterator; - - /** - * @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. - * @param Object ID of the object to add - * @param setTime Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask - * will be called inside the slot period. - * @param setSequenceId ID which can be used to distinguish - * different task operations - * @param - * @param - */ - 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 milliseconds within - * which the handler execution shall take place. - * If the next slot has the same time as the current one, it is ignored - * until a slot with different time or the end of the PST is found. - */ - uint32_t getIntervalToNextSlotMs(); - - /** - * @brief This method returns the time difference between the current - * slot and the previous slot - * - * @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 previous - * one (or the last one, if the slot is the first one) it calculates and - * returns the interval in milliseconds that the handler execution shall - * be delayed. - */ - uint32_t getIntervalToPreviousSlotMs(); - - /** - * @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 - * PollingSlot 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. - */ - SlotListIter current; - - /** - * Iterate through slotList and check successful creation. - * Checks if timing is ok (must be ascending) and if all handlers were found. - * @return - */ - ReturnValue_t checkSequence() const; - -protected: - - /** - * @brief This list contains all PollingSlot objects, defining order and - * execution time of the device handler objects. - * - * @details - * The slot list is a std:list object that contains all created - * PollingSlot instances. They are NOT ordered automatically, so by - * adding entries, the correct order needs to be ensured. By iterating - * through this list the polling sequence is executed. Two entries with - * identical polling times are executed immediately one after another. - */ - SlotList slotList; - - uint32_t lengthMs; -}; - -#endif /* FIXEDSLOTSEQUENCE_H_ */ +#ifndef FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_ +#define FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_ + +#include "FixedSequenceSlot.h" +#include "../objectmanager/SystemObject.h" + +#include + +/** + * @brief This class is the representation of a Polling Sequence Table in software. + * @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 thepolling 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 + * which device handler shall be executed within a given polling period. + * 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 FixedSlotSequence { +public: + using SlotList = std::multiset; + using SlotListIter = std::multiset::iterator; + + /** + * @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. + * @param Object ID of the object to add + * @param setTime Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask + * will be called inside the slot period. + * @param setSequenceId ID which can be used to distinguish + * different task operations + * @param + * @param + */ + void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId, + ExecutableObjectIF* executableObject, 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 milliseconds within + * which the handler execution shall take place. + * If the next slot has the same time as the current one, it is ignored + * until a slot with different time or the end of the PST is found. + */ + uint32_t getIntervalToNextSlotMs(); + + /** + * @brief This method returns the time difference between the current + * slot and the previous slot + * + * @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 previous + * one (or the last one, if the slot is the first one) it calculates and + * returns the interval in milliseconds that the handler execution shall + * be delayed. + */ + uint32_t getIntervalToPreviousSlotMs(); + + /** + * @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 + * PollingSlot 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. + */ + SlotListIter current; + + /** + * @brief Check and initialize slot list. + * @details + * Checks if timing is ok (must be ascending) and if all handlers were found. + * Also calls any initialization steps which are required after task + * creation. + * @return + */ + ReturnValue_t checkSequence() const; + + ReturnValue_t intializeSequenceAfterTaskCreation() const; + +protected: + + /** + * @brief This list contains all PollingSlot objects, defining order and + * execution time of the device handler objects. + * + * @details + * The slot list is a std:list object that contains all created + * PollingSlot instances. They are NOT ordered automatically, so by + * adding entries, the correct order needs to be ensured. By iterating + * through this list the polling sequence is executed. Two entries with + * identical polling times are executed immediately one after another. + */ + SlotList slotList; + + uint32_t lengthMs; + + bool isEmpty = false; +}; + +#endif /* FIXEDSLOTSEQUENCE_H_ */ From 89d3fe509504382980aff1bbeaf9be1ffd508136 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 27 Aug 2020 16:11:40 +0200 Subject: [PATCH 265/653] integrated change manually --- osal/FreeRTOS/PeriodicTask.cpp | 286 ++++++++++++++++----------------- 1 file changed, 143 insertions(+), 143 deletions(-) diff --git a/osal/FreeRTOS/PeriodicTask.cpp b/osal/FreeRTOS/PeriodicTask.cpp index f99e8a4e..990d38d6 100644 --- a/osal/FreeRTOS/PeriodicTask.cpp +++ b/osal/FreeRTOS/PeriodicTask.cpp @@ -1,143 +1,143 @@ -#include "PeriodicTask.h" - -#include "../../serviceinterface/ServiceInterfaceStream.h" -#include "../../tasks/ExecutableObjectIF.h" - -PeriodicTask::PeriodicTask(const char *name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod setPeriod, - TaskDeadlineMissedFunction deadlineMissedFunc) : - started(false), handle(NULL), period(setPeriod), deadlineMissedFunc( - deadlineMissedFunc) -{ - configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); - BaseType_t status = xTaskCreate(taskEntryPoint, name, - stackSize, this, setPriority, &handle); - if(status != pdPASS){ - sif::debug << "PeriodicTask Insufficient heap memory remaining. " - "Status: " << status << std::endl; - } - -} - -PeriodicTask::~PeriodicTask(void) { - //Do not delete objects, we were responsible for ptrs only. -} - -void PeriodicTask::taskEntryPoint(void* argument) { - // The argument is re-interpreted as PeriodicTask. The Task object is - // global, so it is found from any place. - PeriodicTask *originalTask(reinterpret_cast(argument)); - /* Task should not start until explicitly requested, - * but in FreeRTOS, tasks start as soon as they are created if the scheduler - * is running but not if the scheduler is not running. - * To be able to accommodate both cases we check a member which is set in - * #startTask(). If it is not set and we get here, the scheduler was started - * before #startTask() was called and we need to suspend if it is set, - * the scheduler was not running before #startTask() was called and we - * can continue */ - - if (not originalTask->started) { - vTaskSuspend(NULL); - } - - originalTask->taskFunctionality(); - sif::debug << "Polling task " << originalTask->handle - << " returned from taskFunctionality." << std::endl; -} - -ReturnValue_t PeriodicTask::startTask() { - started = true; - - // We must not call resume if scheduler is not started yet - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { - vTaskResume(handle); - } - - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) { - vTaskDelay(pdMS_TO_TICKS(ms)); - return HasReturnvaluesIF::RETURN_OK; -} - -void PeriodicTask::taskFunctionality() { - TickType_t xLastWakeTime; - const TickType_t xPeriod = pdMS_TO_TICKS(this->period * 1000.); - - for (auto const& object: objectList) { - object->initializeAfterTaskCreation(); - } - - /* The xLastWakeTime variable needs to be initialized with the current tick - count. Note that this is the only time the variable is written to - explicitly. After this assignment, xLastWakeTime is updated automatically - internally within vTaskDelayUntil(). */ - xLastWakeTime = xTaskGetTickCount(); - /* Enter the loop that defines the task behavior. */ - for (;;) { - for (auto const& object: objectList) { - object->performOperation(); - } - - checkMissedDeadline(xLastWakeTime, xPeriod); - - vTaskDelayUntil(&xLastWakeTime, xPeriod); - - } -} - -ReturnValue_t PeriodicTask::addComponent(object_id_t object) { - ExecutableObjectIF* newObject = objectManager->get( - object); - if (newObject == nullptr) { - sif::error << "PeriodicTask::addComponent: Invalid object. Make sure" - "it implement ExecutableObjectIF" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - objectList.push_back(newObject); - newObject->setTaskIF(this); - - return HasReturnvaluesIF::RETURN_OK; -} - -uint32_t PeriodicTask::getPeriodMs() const { - return period * 1000; -} - -void PeriodicTask::checkMissedDeadline(const TickType_t xLastWakeTime, - const TickType_t interval) { - /* Check whether deadline was missed while also taking overflows - * into account. Drawing this on paper with a timeline helps to understand - * it. */ - TickType_t currentTickCount = xTaskGetTickCount(); - TickType_t timeToWake = xLastWakeTime + interval; - // Time to wake has not overflown. - if(timeToWake > xLastWakeTime) { - /* If the current time has overflown exclusively or the current - * tick count is simply larger than the time to wake, a deadline was - * missed */ - if((currentTickCount < xLastWakeTime) or (currentTickCount > timeToWake)) { - handleMissedDeadline(); - } - } - /* Time to wake has overflown. A deadline was missed if the current time - * is larger than the time to wake */ - else if((timeToWake < xLastWakeTime) and (currentTickCount > timeToWake)) { - handleMissedDeadline(); - } -} - -TaskHandle_t PeriodicTask::getTaskHandle() { - return handle; -} - -void PeriodicTask::handleMissedDeadline() { -#ifdef DEBUG - sif::warning << "PeriodicTask: " << pcTaskGetName(NULL) << - " missed deadline!\n" << std::flush; -#endif - if(deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); - } -} +#include "PeriodicTask.h" + +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../tasks/ExecutableObjectIF.h" + +PeriodicTask::PeriodicTask(const char *name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod setPeriod, + TaskDeadlineMissedFunction deadlineMissedFunc) : + started(false), handle(NULL), period(setPeriod), deadlineMissedFunc( + deadlineMissedFunc) +{ + configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); + BaseType_t status = xTaskCreate(taskEntryPoint, name, + stackSize, this, setPriority, &handle); + if(status != pdPASS){ + sif::debug << "PeriodicTask Insufficient heap memory remaining. " + "Status: " << status << std::endl; + } + +} + +PeriodicTask::~PeriodicTask(void) { + //Do not delete objects, we were responsible for ptrs only. +} + +void PeriodicTask::taskEntryPoint(void* argument) { + // The argument is re-interpreted as PeriodicTask. The Task object is + // global, so it is found from any place. + PeriodicTask *originalTask(reinterpret_cast(argument)); + /* Task should not start until explicitly requested, + * but in FreeRTOS, tasks start as soon as they are created if the scheduler + * is running but not if the scheduler is not running. + * To be able to accommodate both cases we check a member which is set in + * #startTask(). If it is not set and we get here, the scheduler was started + * before #startTask() was called and we need to suspend if it is set, + * the scheduler was not running before #startTask() was called and we + * can continue */ + + if (not originalTask->started) { + vTaskSuspend(NULL); + } + + originalTask->taskFunctionality(); + sif::debug << "Polling task " << originalTask->handle + << " returned from taskFunctionality." << std::endl; +} + +ReturnValue_t PeriodicTask::startTask() { + started = true; + + // We must not call resume if scheduler is not started yet + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + vTaskResume(handle); + } + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) { + vTaskDelay(pdMS_TO_TICKS(ms)); + return HasReturnvaluesIF::RETURN_OK; +} + +void PeriodicTask::taskFunctionality() { + TickType_t xLastWakeTime; + const TickType_t xPeriod = pdMS_TO_TICKS(this->period * 1000.); + + for (auto const &object: objectList) { + object->initializeAfterTaskCreation(); + } + + /* The xLastWakeTime variable needs to be initialized with the current tick + count. Note that this is the only time the variable is written to + explicitly. After this assignment, xLastWakeTime is updated automatically + internally within vTaskDelayUntil(). */ + xLastWakeTime = xTaskGetTickCount(); + /* Enter the loop that defines the task behavior. */ + for (;;) { + for (auto const& object: objectList) { + object->performOperation(); + } + + checkMissedDeadline(xLastWakeTime, xPeriod); + + vTaskDelayUntil(&xLastWakeTime, xPeriod); + + } +} + +ReturnValue_t PeriodicTask::addComponent(object_id_t object) { + ExecutableObjectIF* newObject = objectManager->get( + object); + if (newObject == nullptr) { + sif::error << "PeriodicTask::addComponent: Invalid object. Make sure" + "it implement ExecutableObjectIF" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + objectList.push_back(newObject); + newObject->setTaskIF(this); + + return HasReturnvaluesIF::RETURN_OK; +} + +uint32_t PeriodicTask::getPeriodMs() const { + return period * 1000; +} + +void PeriodicTask::checkMissedDeadline(const TickType_t xLastWakeTime, + const TickType_t interval) { + /* Check whether deadline was missed while also taking overflows + * into account. Drawing this on paper with a timeline helps to understand + * it. */ + TickType_t currentTickCount = xTaskGetTickCount(); + TickType_t timeToWake = xLastWakeTime + interval; + // Time to wake has not overflown. + if(timeToWake > xLastWakeTime) { + /* If the current time has overflown exclusively or the current + * tick count is simply larger than the time to wake, a deadline was + * missed */ + if((currentTickCount < xLastWakeTime) or (currentTickCount > timeToWake)) { + handleMissedDeadline(); + } + } + /* Time to wake has overflown. A deadline was missed if the current time + * is larger than the time to wake */ + else if((timeToWake < xLastWakeTime) and (currentTickCount > timeToWake)) { + handleMissedDeadline(); + } +} + +TaskHandle_t PeriodicTask::getTaskHandle() { + return handle; +} + +void PeriodicTask::handleMissedDeadline() { +#ifdef DEBUG + sif::warning << "PeriodicTask: " << pcTaskGetName(NULL) << + " missed deadline!\n" << std::flush; +#endif + if(deadlineMissedFunc != nullptr) { + this->deadlineMissedFunc(); + } +} From 4530b1954811727d0f32eea4fd25b8378a153db0 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 27 Aug 2020 16:13:36 +0200 Subject: [PATCH 266/653] header update --- osal/FreeRTOS/PeriodicTask.h | 254 +++++++++++++++++------------------ 1 file changed, 126 insertions(+), 128 deletions(-) diff --git a/osal/FreeRTOS/PeriodicTask.h b/osal/FreeRTOS/PeriodicTask.h index 1cdc3df7..87b8b6d2 100644 --- a/osal/FreeRTOS/PeriodicTask.h +++ b/osal/FreeRTOS/PeriodicTask.h @@ -1,128 +1,126 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_PERIODICTASK_H_ -#define FRAMEWORK_OSAL_FREERTOS_PERIODICTASK_H_ - -#include "../../osal/FreeRTOS/FreeRTOSTaskIF.h" -#include "../../objectmanager/ObjectManagerIF.h" -#include "../../tasks/PeriodicTaskIF.h" -#include "../../tasks/Typedef.h" - - -#include -#include - -#include - -class ExecutableObjectIF; - -/** - * @brief This class represents a specialized task for - * periodic activities of multiple objects. - * @ingroup task_handling - */ -class PeriodicTask: public PeriodicTaskIF, public FreeRTOSTaskIF { -public: - /** - * Keep in Mind that you need to call before this vTaskStartScheduler()! - * A lot of task parameters are set in "FreeRTOSConfig.h". - * TODO: why does this need to be called before vTaskStartScheduler? - * @details - * The class is initialized without allocated objects. - * These need to be added with #addComponent. - * @param priority - * Sets the priority of a task. Values depend on freeRTOS configuration, - * high number means high priority. - * @param stack_size - * The stack size reserved by the operating system for the task. - * @param setPeriod - * The length of the period with which the task's - * functionality will be executed. It is expressed in clock ticks. - * @param setDeadlineMissedFunc - * The function pointer to the deadline missed function that shall - * be assigned. - */ - PeriodicTask(TaskName name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod setPeriod, - TaskDeadlineMissedFunction deadlineMissedFunc); - /** - * @brief Currently, the executed object's lifetime is not coupled with - * the task object's lifetime, so the destructor is empty. - */ - virtual ~PeriodicTask(void); - - /** - * @brief The method to start the task. - * @details The method starts the task with the respective system call. - * Entry point is the taskEntryPoint method described below. - * The address of the task object is passed as an argument - * to the system call. - */ - ReturnValue_t startTask() override; - /** - * Adds an object to the list of objects to be executed. - * The objects are executed in the order added. - * @param object Id of the object to add. - * @return - * -@c RETURN_OK on success - * -@c RETURN_FAILED if the object could not be added. - */ - ReturnValue_t addComponent(object_id_t object) override; - - uint32_t getPeriodMs() const override; - - ReturnValue_t sleepFor(uint32_t ms) override; - - TaskHandle_t getTaskHandle() override; -protected: - bool started; - TaskHandle_t handle; - - //! Typedef for the List of objects. - typedef std::vector ObjectList; - /** - * @brief This attribute holds a list of objects to be executed. - */ - ObjectList objectList; - /** - * @brief The period of the task. - * @details - * The period determines the frequency of the task's execution. - * It is expressed in clock ticks. - */ - TaskPeriod period; - /** - * @brief The pointer to the deadline-missed function. - * @details - * This pointer stores the function that is executed if the task's deadline - * is missed so each may react individually on a timing failure. - * The pointer may be NULL, then nothing happens on missing the deadline. - * The deadline is equal to the next execution of the periodic task. - */ - void (*deadlineMissedFunc)(void); - /** - * @brief This is the function executed in the new task's context. - * @details - * It converts the argument back to the thread object type and copies the - * class instance to the task context. The taskFunctionality method is - * called afterwards. - * @param A pointer to the task object itself is passed as argument. - */ - - static void taskEntryPoint(void* argument); - /** - * @brief The function containing the actual functionality of the task. - * @details - * The method sets and starts the task's period, then enters a loop that is - * repeated as long as the isRunning attribute is true. Within the loop, - * all performOperation methods of the added objects are called. - * Afterwards the checkAndRestartPeriod system call blocks the task until - * the next period. - * On missing the deadline, the deadlineMissedFunction is executed. - */ - void taskFunctionality(void); - - void checkMissedDeadline(const TickType_t xLastWakeTime, - const TickType_t interval); - void handleMissedDeadline(); -}; - -#endif /* PERIODICTASK_H_ */ +#ifndef FSFW_OSAL_FREERTOS_PERIODICTASK_H_ +#define FSFW_OSAL_FREERTOS_PERIODICTASK_H_ + +#include "FreeRTOSTaskIF.h" +#include "../../objectmanager/ObjectManagerIF.h" +#include "../../tasks/PeriodicTaskIF.h" +#include "../../tasks/Typedef.h" + +#include +#include + +#include + +class ExecutableObjectIF; + +/** + * @brief This class represents a specialized task for + * periodic activities of multiple objects. + * @ingroup task_handling + */ +class PeriodicTask: public PeriodicTaskIF, public FreeRTOSTaskIF { +public: + /** + * Keep in Mind that you need to call before this vTaskStartScheduler()! + * A lot of task parameters are set in "FreeRTOSConfig.h". + * @details + * The class is initialized without allocated objects. + * These need to be added with #addComponent. + * @param priority + * Sets the priority of a task. Values depend on freeRTOS configuration, + * high number means high priority. + * @param stack_size + * The stack size reserved by the operating system for the task. + * @param setPeriod + * The length of the period with which the task's + * functionality will be executed. It is expressed in clock ticks. + * @param setDeadlineMissedFunc + * The function pointer to the deadline missed function that shall + * be assigned. + */ + PeriodicTask(TaskName name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod setPeriod, + TaskDeadlineMissedFunction deadlineMissedFunc); + /** + * @brief Currently, the executed object's lifetime is not coupled with + * the task object's lifetime, so the destructor is empty. + */ + virtual ~PeriodicTask(void); + + /** + * @brief The method to start the task. + * @details The method starts the task with the respective system call. + * Entry point is the taskEntryPoint method described below. + * The address of the task object is passed as an argument + * to the system call. + */ + ReturnValue_t startTask() override; + /** + * Adds an object to the list of objects to be executed. + * The objects are executed in the order added. + * @param object Id of the object to add. + * @return + * -@c RETURN_OK on success + * -@c RETURN_FAILED if the object could not be added. + */ + ReturnValue_t addComponent(object_id_t object) override; + + uint32_t getPeriodMs() const override; + + ReturnValue_t sleepFor(uint32_t ms) override; + + TaskHandle_t getTaskHandle() override; +protected: + bool started; + TaskHandle_t handle; + + //! Typedef for the List of objects. + typedef std::vector ObjectList; + /** + * @brief This attribute holds a list of objects to be executed. + */ + ObjectList objectList; + /** + * @brief The period of the task. + * @details + * The period determines the frequency of the task's execution. + * It is expressed in clock ticks. + */ + TaskPeriod period; + /** + * @brief The pointer to the deadline-missed function. + * @details + * This pointer stores the function that is executed if the task's deadline + * is missed so each may react individually on a timing failure. + * The pointer may be NULL, then nothing happens on missing the deadline. + * The deadline is equal to the next execution of the periodic task. + */ + void (*deadlineMissedFunc)(void); + /** + * @brief This is the function executed in the new task's context. + * @details + * It converts the argument back to the thread object type and copies the + * class instance to the task context. The taskFunctionality method is + * called afterwards. + * @param A pointer to the task object itself is passed as argument. + */ + + static void taskEntryPoint(void* argument); + /** + * @brief The function containing the actual functionality of the task. + * @details + * The method sets and starts the task's period, then enters a loop that is + * repeated as long as the isRunning attribute is true. Within the loop, + * all performOperation methods of the added objects are called. + * Afterwards the checkAndRestartPeriod system call blocks the task until + * the next period. + * On missing the deadline, the deadlineMissedFunction is executed. + */ + void taskFunctionality(void); + + void checkMissedDeadline(const TickType_t xLastWakeTime, + const TickType_t interval); + void handleMissedDeadline(); +}; + +#endif /* FSFW_OSAL_FREERTOS_PERIODICTASK_H_ */ From 64022212f97e6726feb6a5768f44897180081e20 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 27 Aug 2020 16:20:32 +0200 Subject: [PATCH 267/653] removed is empty flag --- tasks/FixedSlotSequence.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/tasks/FixedSlotSequence.h b/tasks/FixedSlotSequence.h index 8aa04a27..026d5a3d 100644 --- a/tasks/FixedSlotSequence.h +++ b/tasks/FixedSlotSequence.h @@ -152,8 +152,6 @@ protected: SlotList slotList; uint32_t lengthMs; - - bool isEmpty = false; }; #endif /* FIXEDSLOTSEQUENCE_H_ */ From aacda3afc242dad3c20b9d959a2417dbae5822ed Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 27 Aug 2020 16:26:00 +0200 Subject: [PATCH 268/653] interface adapted --- osal/FreeRTOS/BinSemaphUsingTask.cpp | 186 +++++++++--------- osal/FreeRTOS/BinSemaphUsingTask.h | 151 +++++++-------- osal/FreeRTOS/BinarySemaphore.cpp | 33 ++-- osal/FreeRTOS/BinarySemaphore.h | 12 +- osal/FreeRTOS/CountingSemaphUsingTask.cpp | 224 +++++++++++----------- osal/FreeRTOS/CountingSemaphUsingTask.h | 202 +++++++++---------- osal/FreeRTOS/CountingSemaphore.cpp | 86 ++++----- osal/FreeRTOS/CountingSemaphore.h | 68 +++---- osal/FreeRTOS/SemaphoreFactory.cpp | 120 ++++++------ tasks/SemaphoreIF.h | 140 +++++++------- 10 files changed, 616 insertions(+), 606 deletions(-) diff --git a/osal/FreeRTOS/BinSemaphUsingTask.cpp b/osal/FreeRTOS/BinSemaphUsingTask.cpp index d3351888..8c831bbe 100644 --- a/osal/FreeRTOS/BinSemaphUsingTask.cpp +++ b/osal/FreeRTOS/BinSemaphUsingTask.cpp @@ -1,91 +1,95 @@ -#include -#include -#include - -BinarySemaphoreUsingTask::BinarySemaphoreUsingTask() { - handle = TaskManagement::getCurrentTaskHandle(); - if(handle == nullptr) { - sif::error << "Could not retrieve task handle. Please ensure the" - "constructor was called inside a task." << std::endl; - } - xTaskNotifyGive(handle); -} - -BinarySemaphoreUsingTask::~BinarySemaphoreUsingTask() { - // Clear notification value on destruction. - xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr); -} - -ReturnValue_t BinarySemaphoreUsingTask::acquire(uint32_t timeoutMs) { - TickType_t timeout = SemaphoreIF::POLLING; - if(timeoutMs == SemaphoreIF::BLOCKING) { - timeout = SemaphoreIF::BLOCKING; - } - else if(timeoutMs > SemaphoreIF::POLLING){ - timeout = pdMS_TO_TICKS(timeoutMs); - } - return acquireWithTickTimeout(timeout); -} - -ReturnValue_t BinarySemaphoreUsingTask::acquireWithTickTimeout( - TickType_t timeoutTicks) { - BaseType_t returncode = ulTaskNotifyTake(pdTRUE, timeoutTicks); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - return SemaphoreIF::SEMAPHORE_TIMEOUT; - } -} - -ReturnValue_t BinarySemaphoreUsingTask::release() { - return release(this->handle); -} - -ReturnValue_t BinarySemaphoreUsingTask::release( - TaskHandle_t taskHandle) { - if(getSemaphoreCounter(taskHandle) == 1) { - return SemaphoreIF::SEMAPHORE_NOT_OWNED; - } - BaseType_t returncode = xTaskNotifyGive(taskHandle); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - // This should never happen. - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -TaskHandle_t BinarySemaphoreUsingTask::getTaskHandle() { - return handle; -} - -uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter() const { - return getSemaphoreCounter(this->handle); -} - -uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter( - TaskHandle_t taskHandle) { - uint32_t notificationValue; - xTaskNotifyAndQuery(taskHandle, 0, eNoAction, ¬ificationValue); - return notificationValue; -} - -// Be careful with the stack size here. This is called from an ISR! -ReturnValue_t BinarySemaphoreUsingTask::releaseFromISR( - TaskHandle_t taskHandle, BaseType_t * higherPriorityTaskWoken) { - if(getSemaphoreCounterFromISR(taskHandle, higherPriorityTaskWoken) == 1) { - return SemaphoreIF::SEMAPHORE_NOT_OWNED; - } - vTaskNotifyGiveFromISR(taskHandle, higherPriorityTaskWoken); - return HasReturnvaluesIF::RETURN_OK; -} - -uint8_t BinarySemaphoreUsingTask::getSemaphoreCounterFromISR( - TaskHandle_t taskHandle, BaseType_t* higherPriorityTaskWoken) { - uint32_t notificationValue = 0; - xTaskNotifyAndQueryFromISR(taskHandle, 0, eNoAction, ¬ificationValue, - higherPriorityTaskWoken); - return notificationValue; -} +#include "../../osal/FreeRTOS/BinSemaphUsingTask.h" +#include "../../osal/FreeRTOS/TaskManagement.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +BinarySemaphoreUsingTask::BinarySemaphoreUsingTask() { + handle = TaskManagement::getCurrentTaskHandle(); + if(handle == nullptr) { + sif::error << "Could not retrieve task handle. Please ensure the" + "constructor was called inside a task." << std::endl; + } + xTaskNotifyGive(handle); +} + +BinarySemaphoreUsingTask::~BinarySemaphoreUsingTask() { + // Clear notification value on destruction. + xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr); +} + +ReturnValue_t BinarySemaphoreUsingTask::acquire(TimeoutType timeoutType, + uint32_t timeoutMs) { + TickType_t timeout = 0; + if(timeoutType == TimeoutType::POLLING) { + timeout = 0; + } + else if(timeoutType == TimeoutType::WAITING){ + timeout = pdMS_TO_TICKS(timeoutMs); + } + else { + timeout = portMAX_DELAY; + } + return acquireWithTickTimeout(timeoutType, timeout); +} + +ReturnValue_t BinarySemaphoreUsingTask::acquireWithTickTimeout( + TimeoutType timeoutType, TickType_t timeoutTicks) { + BaseType_t returncode = ulTaskNotifyTake(pdTRUE, timeoutTicks); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SemaphoreIF::SEMAPHORE_TIMEOUT; + } +} + +ReturnValue_t BinarySemaphoreUsingTask::release() { + return release(this->handle); +} + +ReturnValue_t BinarySemaphoreUsingTask::release( + TaskHandle_t taskHandle) { + if(getSemaphoreCounter(taskHandle) == 1) { + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } + BaseType_t returncode = xTaskNotifyGive(taskHandle); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + // This should never happen. + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +TaskHandle_t BinarySemaphoreUsingTask::getTaskHandle() { + return handle; +} + +uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter() const { + return getSemaphoreCounter(this->handle); +} + +uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter( + TaskHandle_t taskHandle) { + uint32_t notificationValue; + xTaskNotifyAndQuery(taskHandle, 0, eNoAction, ¬ificationValue); + return notificationValue; +} + +// Be careful with the stack size here. This is called from an ISR! +ReturnValue_t BinarySemaphoreUsingTask::releaseFromISR( + TaskHandle_t taskHandle, BaseType_t * higherPriorityTaskWoken) { + if(getSemaphoreCounterFromISR(taskHandle, higherPriorityTaskWoken) == 1) { + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } + vTaskNotifyGiveFromISR(taskHandle, higherPriorityTaskWoken); + return HasReturnvaluesIF::RETURN_OK; +} + +uint8_t BinarySemaphoreUsingTask::getSemaphoreCounterFromISR( + TaskHandle_t taskHandle, BaseType_t* higherPriorityTaskWoken) { + uint32_t notificationValue = 0; + xTaskNotifyAndQueryFromISR(taskHandle, 0, eNoAction, ¬ificationValue, + higherPriorityTaskWoken); + return notificationValue; +} diff --git a/osal/FreeRTOS/BinSemaphUsingTask.h b/osal/FreeRTOS/BinSemaphUsingTask.h index 43772e5a..2d2cf159 100644 --- a/osal/FreeRTOS/BinSemaphUsingTask.h +++ b/osal/FreeRTOS/BinSemaphUsingTask.h @@ -1,75 +1,76 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ -#define FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ - -#include -#include - -#include -#include - -/** - * @brief Binary Semaphore implementation using the task notification value. - * The notification value should therefore not be used - * for other purposes. - * @details - * Additional information: https://www.freertos.org/RTOS-task-notifications.html - * and general semaphore documentation. - */ -class BinarySemaphoreUsingTask: public SemaphoreIF, - public HasReturnvaluesIF { -public: - static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; - - //! @brief Default ctor - BinarySemaphoreUsingTask(); - //! @brief Default dtor - virtual~ BinarySemaphoreUsingTask(); - - ReturnValue_t acquire(uint32_t timeoutMs = - SemaphoreIF::BLOCKING) override; - ReturnValue_t release() override; - uint8_t getSemaphoreCounter() const override; - static uint8_t getSemaphoreCounter(TaskHandle_t taskHandle); - static uint8_t getSemaphoreCounterFromISR(TaskHandle_t taskHandle, - BaseType_t* higherPriorityTaskWoken); - - /** - * Same as acquire() with timeout in FreeRTOS ticks. - * @param timeoutTicks - * @return - @c RETURN_OK on success - * - @c RETURN_FAILED on failure - */ - ReturnValue_t acquireWithTickTimeout(TickType_t timeoutTicks = - SemaphoreIF::BLOCKING); - - /** - * Get handle to the task related to the semaphore. - * @return - */ - TaskHandle_t getTaskHandle(); - - /** - * Wrapper function to give back semaphore from handle - * @param semaphore - * @return - @c RETURN_OK on success - * - @c RETURN_FAILED on failure - */ - static ReturnValue_t release(TaskHandle_t taskToNotify); - - /** - * Wrapper function to give back semaphore from handle when called from an ISR - * @param semaphore - * @param higherPriorityTaskWoken This will be set to pdPASS if a task with - * a higher priority was unblocked. A context switch should be requested - * from an ISR if this is the case (see TaskManagement functions) - * @return - @c RETURN_OK on success - * - @c RETURN_FAILED on failure - */ - static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify, - BaseType_t * higherPriorityTaskWoken); - -protected: - TaskHandle_t handle; -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ +#define FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ + +#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../tasks/SemaphoreIF.h" + +#include +#include + +/** + * @brief Binary Semaphore implementation using the task notification value. + * The notification value should therefore not be used + * for other purposes. + * @details + * Additional information: https://www.freertos.org/RTOS-task-notifications.html + * and general semaphore documentation. + */ +class BinarySemaphoreUsingTask: public SemaphoreIF, + public HasReturnvaluesIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; + + //! @brief Default ctor + BinarySemaphoreUsingTask(); + //! @brief Default dtor + virtual~ BinarySemaphoreUsingTask(); + + ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, + uint32_t timeoutMs = portMAX_DELAY) override; + ReturnValue_t release() override; + uint8_t getSemaphoreCounter() const override; + static uint8_t getSemaphoreCounter(TaskHandle_t taskHandle); + static uint8_t getSemaphoreCounterFromISR(TaskHandle_t taskHandle, + BaseType_t* higherPriorityTaskWoken); + + /** + * Same as acquire() with timeout in FreeRTOS ticks. + * @param timeoutTicks + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + ReturnValue_t acquireWithTickTimeout( + TimeoutType timeoutType = TimeoutType::BLOCKING, + TickType_t timeoutTicks = portMAX_DELAY); + + /** + * Get handle to the task related to the semaphore. + * @return + */ + TaskHandle_t getTaskHandle(); + + /** + * Wrapper function to give back semaphore from handle + * @param semaphore + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + static ReturnValue_t release(TaskHandle_t taskToNotify); + + /** + * Wrapper function to give back semaphore from handle when called from an ISR + * @param semaphore + * @param higherPriorityTaskWoken This will be set to pdPASS if a task with + * a higher priority was unblocked. A context switch should be requested + * from an ISR if this is the case (see TaskManagement functions) + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify, + BaseType_t * higherPriorityTaskWoken); + +protected: + TaskHandle_t handle; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ */ diff --git a/osal/FreeRTOS/BinarySemaphore.cpp b/osal/FreeRTOS/BinarySemaphore.cpp index e6d2f92f..f1c78473 100644 --- a/osal/FreeRTOS/BinarySemaphore.cpp +++ b/osal/FreeRTOS/BinarySemaphore.cpp @@ -1,11 +1,11 @@ -#include -#include -#include +#include "../../osal/FreeRTOS/BinarySemaphore.h" +#include "../../osal/FreeRTOS/TaskManagement.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" BinarySemaphore::BinarySemaphore() { handle = xSemaphoreCreateBinary(); - if(handle == nullptr) { - sif::error << "Semaphore: Binary semaph creation failure" << std::endl; + if(handle == nullptr) { + sif::error << "Semaphore: Binary semaph creation failure" << std::endl; } // Initiated semaphore must be given before it can be taken. xSemaphoreGive(handle); @@ -35,18 +35,23 @@ BinarySemaphore& BinarySemaphore::operator =( return *this; } -ReturnValue_t BinarySemaphore::acquire(uint32_t timeoutMs) { - TickType_t timeout = SemaphoreIF::POLLING; - if(timeoutMs == SemaphoreIF::BLOCKING) { - timeout = SemaphoreIF::BLOCKING; +ReturnValue_t BinarySemaphore::acquire(TimeoutType timeoutType, + uint32_t timeoutMs) { + TickType_t timeout = 0; + if(timeoutType == TimeoutType::POLLING) { + timeout = 0; } - else if(timeoutMs > SemaphoreIF::POLLING){ + else if(timeoutType == TimeoutType::WAITING){ timeout = pdMS_TO_TICKS(timeoutMs); } - return acquireWithTickTimeout(timeout); + else { + timeout = portMAX_DELAY; + } + return acquireWithTickTimeout(timeoutType, timeout); } -ReturnValue_t BinarySemaphore::acquireWithTickTimeout(TickType_t timeoutTicks) { +ReturnValue_t BinarySemaphore::acquireWithTickTimeout(TimeoutType timeoutType, + TickType_t timeoutTicks) { if(handle == nullptr) { return SemaphoreIF::SEMAPHORE_INVALID; } @@ -84,7 +89,7 @@ uint8_t BinarySemaphore::getSemaphoreCounter() const { SemaphoreHandle_t BinarySemaphore::getSemaphore() { return handle; } - + // Be careful with the stack size here. This is called from an ISR! ReturnValue_t BinarySemaphore::releaseFromISR( @@ -100,4 +105,4 @@ ReturnValue_t BinarySemaphore::releaseFromISR( else { return SemaphoreIF::SEMAPHORE_NOT_OWNED; } -} +} diff --git a/osal/FreeRTOS/BinarySemaphore.h b/osal/FreeRTOS/BinarySemaphore.h index 2a372cd2..5a32088a 100644 --- a/osal/FreeRTOS/BinarySemaphore.h +++ b/osal/FreeRTOS/BinarySemaphore.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ #define FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ -#include -#include +#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../tasks/SemaphoreIF.h" #include #include @@ -52,8 +52,8 @@ public: * @return -@c RETURN_OK on success * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout */ - ReturnValue_t acquire(uint32_t timeoutMs = - SemaphoreIF::BLOCKING) override; + ReturnValue_t acquire(TimeoutType timeoutType = + TimeoutType::BLOCKING, uint32_t timeoutMs = portMAX_DELAY) override; /** * Same as lockBinarySemaphore() with timeout in FreeRTOS ticks. @@ -61,8 +61,8 @@ public: * @return -@c RETURN_OK on success * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout */ - ReturnValue_t acquireWithTickTimeout(TickType_t timeoutTicks = - SemaphoreIF::BLOCKING); + ReturnValue_t acquireWithTickTimeout(TimeoutType timeoutType = + TimeoutType::BLOCKING, TickType_t timeoutTicks = portMAX_DELAY); /** * Release the binary semaphore. diff --git a/osal/FreeRTOS/CountingSemaphUsingTask.cpp b/osal/FreeRTOS/CountingSemaphUsingTask.cpp index f33c7a0d..e66671ac 100644 --- a/osal/FreeRTOS/CountingSemaphUsingTask.cpp +++ b/osal/FreeRTOS/CountingSemaphUsingTask.cpp @@ -1,110 +1,114 @@ -#include -#include -#include - -CountingSemaphoreUsingTask::CountingSemaphoreUsingTask(const uint8_t maxCount, - uint8_t initCount): maxCount(maxCount) { - if(initCount > maxCount) { - sif::error << "CountingSemaphoreUsingTask: Max count bigger than " - "intial cout. Setting initial count to max count." << std::endl; - initCount = maxCount; - } - - handle = TaskManagement::getCurrentTaskHandle(); - if(handle == nullptr) { - sif::error << "CountingSemaphoreUsingTask: Could not retrieve task " - "handle. Please ensure the constructor was called inside a " - "task." << std::endl; - } - - uint32_t oldNotificationValue; - xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, - &oldNotificationValue); - if(oldNotificationValue != 0) { - sif::warning << "CountinSemaphoreUsingTask: Semaphore initiated but " - "current notification value is not 0. Please ensure the " - "notification value is not used for other purposes!" << std::endl; - } - for(int i = 0; i < initCount; i++) { - xTaskNotifyGive(handle); - } -} - -CountingSemaphoreUsingTask::~CountingSemaphoreUsingTask() { - // Clear notification value on destruction. - // If this is not desired, don't call the destructor - // (or implement a boolean which disables the reset) - xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr); -} - -ReturnValue_t CountingSemaphoreUsingTask::acquire(uint32_t timeoutMs) { - TickType_t timeout = SemaphoreIF::POLLING; - if(timeoutMs == SemaphoreIF::BLOCKING) { - timeout = SemaphoreIF::BLOCKING; - } - else if(timeoutMs > SemaphoreIF::POLLING){ - timeout = pdMS_TO_TICKS(timeoutMs); - } - return acquireWithTickTimeout(timeout); - -} - -ReturnValue_t CountingSemaphoreUsingTask::acquireWithTickTimeout( - TickType_t timeoutTicks) { - // Decrement notfication value without resetting it. - BaseType_t oldCount = ulTaskNotifyTake(pdFALSE, timeoutTicks); - if (getSemaphoreCounter() == oldCount - 1) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - return SemaphoreIF::SEMAPHORE_TIMEOUT; - } -} - -ReturnValue_t CountingSemaphoreUsingTask::release() { - if(getSemaphoreCounter() == maxCount) { - return SemaphoreIF::SEMAPHORE_NOT_OWNED; - } - return release(handle); -} - -ReturnValue_t CountingSemaphoreUsingTask::release( - TaskHandle_t taskToNotify) { - BaseType_t returncode = xTaskNotifyGive(taskToNotify); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - // This should never happen. - return HasReturnvaluesIF::RETURN_FAILED; - } -} - - -uint8_t CountingSemaphoreUsingTask::getSemaphoreCounter() const { - uint32_t notificationValue = 0; - xTaskNotifyAndQuery(handle, 0, eNoAction, ¬ificationValue); - return notificationValue; -} - -TaskHandle_t CountingSemaphoreUsingTask::getTaskHandle() { - return handle; -} - -ReturnValue_t CountingSemaphoreUsingTask::releaseFromISR( - TaskHandle_t taskToNotify, BaseType_t* higherPriorityTaskWoken) { - vTaskNotifyGiveFromISR(taskToNotify, higherPriorityTaskWoken); - return HasReturnvaluesIF::RETURN_OK; -} - -uint8_t CountingSemaphoreUsingTask::getSemaphoreCounterFromISR( - TaskHandle_t task, BaseType_t* higherPriorityTaskWoken) { - uint32_t notificationValue; - xTaskNotifyAndQueryFromISR(task, 0, eNoAction, ¬ificationValue, - higherPriorityTaskWoken); - return notificationValue; -} - -uint8_t CountingSemaphoreUsingTask::getMaxCount() const { - return maxCount; -} +#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h" +#include "../../osal/FreeRTOS/TaskManagement.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +CountingSemaphoreUsingTask::CountingSemaphoreUsingTask(const uint8_t maxCount, + uint8_t initCount): maxCount(maxCount) { + if(initCount > maxCount) { + sif::error << "CountingSemaphoreUsingTask: Max count bigger than " + "intial cout. Setting initial count to max count." << std::endl; + initCount = maxCount; + } + + handle = TaskManagement::getCurrentTaskHandle(); + if(handle == nullptr) { + sif::error << "CountingSemaphoreUsingTask: Could not retrieve task " + "handle. Please ensure the constructor was called inside a " + "task." << std::endl; + } + + uint32_t oldNotificationValue; + xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, + &oldNotificationValue); + if(oldNotificationValue != 0) { + sif::warning << "CountinSemaphoreUsingTask: Semaphore initiated but " + "current notification value is not 0. Please ensure the " + "notification value is not used for other purposes!" << std::endl; + } + for(int i = 0; i < initCount; i++) { + xTaskNotifyGive(handle); + } +} + +CountingSemaphoreUsingTask::~CountingSemaphoreUsingTask() { + // Clear notification value on destruction. + // If this is not desired, don't call the destructor + // (or implement a boolean which disables the reset) + xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr); +} + +ReturnValue_t CountingSemaphoreUsingTask::acquire(TimeoutType timeoutType, + uint32_t timeoutMs) { + TickType_t timeout = 0; + if(timeoutType == TimeoutType::POLLING) { + timeout = 0; + } + else if(timeoutType == TimeoutType::WAITING){ + timeout = pdMS_TO_TICKS(timeoutMs); + } + else { + timeout = portMAX_DELAY; + } + return acquireWithTickTimeout(timeoutType, timeout); + +} + +ReturnValue_t CountingSemaphoreUsingTask::acquireWithTickTimeout( + TimeoutType timeoutType, TickType_t timeoutTicks) { + // Decrement notfication value without resetting it. + BaseType_t oldCount = ulTaskNotifyTake(pdFALSE, timeoutTicks); + if (getSemaphoreCounter() == oldCount - 1) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SemaphoreIF::SEMAPHORE_TIMEOUT; + } +} + +ReturnValue_t CountingSemaphoreUsingTask::release() { + if(getSemaphoreCounter() == maxCount) { + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } + return release(handle); +} + +ReturnValue_t CountingSemaphoreUsingTask::release( + TaskHandle_t taskToNotify) { + BaseType_t returncode = xTaskNotifyGive(taskToNotify); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + // This should never happen. + return HasReturnvaluesIF::RETURN_FAILED; + } +} + + +uint8_t CountingSemaphoreUsingTask::getSemaphoreCounter() const { + uint32_t notificationValue = 0; + xTaskNotifyAndQuery(handle, 0, eNoAction, ¬ificationValue); + return notificationValue; +} + +TaskHandle_t CountingSemaphoreUsingTask::getTaskHandle() { + return handle; +} + +ReturnValue_t CountingSemaphoreUsingTask::releaseFromISR( + TaskHandle_t taskToNotify, BaseType_t* higherPriorityTaskWoken) { + vTaskNotifyGiveFromISR(taskToNotify, higherPriorityTaskWoken); + return HasReturnvaluesIF::RETURN_OK; +} + +uint8_t CountingSemaphoreUsingTask::getSemaphoreCounterFromISR( + TaskHandle_t task, BaseType_t* higherPriorityTaskWoken) { + uint32_t notificationValue; + xTaskNotifyAndQueryFromISR(task, 0, eNoAction, ¬ificationValue, + higherPriorityTaskWoken); + return notificationValue; +} + +uint8_t CountingSemaphoreUsingTask::getMaxCount() const { + return maxCount; +} diff --git a/osal/FreeRTOS/CountingSemaphUsingTask.h b/osal/FreeRTOS/CountingSemaphUsingTask.h index f1d82c1d..e3733382 100644 --- a/osal/FreeRTOS/CountingSemaphUsingTask.h +++ b/osal/FreeRTOS/CountingSemaphUsingTask.h @@ -1,100 +1,102 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ -#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ - -#include -#include - -extern "C" { -#include -#include -} - -/** - * @brief Couting Semaphore implementation which uses the notification value - * of the task. The notification value should therefore not be used - * for other purposes. - * @details - * Additional information: https://www.freertos.org/RTOS-task-notifications.html - * and general semaphore documentation. - */ -class CountingSemaphoreUsingTask: public SemaphoreIF { -public: - CountingSemaphoreUsingTask(const uint8_t maxCount, uint8_t initCount); - virtual ~CountingSemaphoreUsingTask(); - - /** - * Acquire the counting semaphore. - * If no semaphores are available, the task will be blocked - * for a maximum of #timeoutMs or until one is given back, - * for example by an ISR or another task. - * @param timeoutMs - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout - */ - ReturnValue_t acquire(uint32_t timeoutMs = SemaphoreIF::BLOCKING) override; - - /** - * Release a semaphore, increasing the number of available counting - * semaphores up to the #maxCount value. - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are - * already available. - */ - ReturnValue_t release() override; - - uint8_t getSemaphoreCounter() const override; - /** - * Get the semaphore counter from an ISR. - * @param task - * @param higherPriorityTaskWoken This will be set to pdPASS if a task with - * a higher priority was unblocked. A context switch should be requested - * from an ISR if this is the case (see TaskManagement functions) - * @return - */ - static uint8_t getSemaphoreCounterFromISR(TaskHandle_t task, - BaseType_t* higherPriorityTaskWoken); - - /** - * Acquire with a timeout value in ticks - * @param timeoutTicks - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout - */ - ReturnValue_t acquireWithTickTimeout( - TickType_t timeoutTicks = SemaphoreIF::BLOCKING); - - /** - * Get handle to the task related to the semaphore. - * @return - */ - TaskHandle_t getTaskHandle(); - - /** - * Release semaphore of task by supplying task handle - * @param taskToNotify - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are - * already available. - */ - static ReturnValue_t release(TaskHandle_t taskToNotify); - /** - * Release seamphore of a task from an ISR. - * @param taskToNotify - * @param higherPriorityTaskWoken This will be set to pdPASS if a task with - * a higher priority was unblocked. A context switch should be requested - * from an ISR if this is the case (see TaskManagement functions) - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are - * already available. - */ - static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify, - BaseType_t* higherPriorityTaskWoken); - - uint8_t getMaxCount() const; - -private: - TaskHandle_t handle; - const uint8_t maxCount; -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ +#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ + +#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h" +#include "../../tasks/SemaphoreIF.h" + +extern "C" { +#include +#include +} + +/** + * @brief Couting Semaphore implementation which uses the notification value + * of the task. The notification value should therefore not be used + * for other purposes. + * @details + * Additional information: https://www.freertos.org/RTOS-task-notifications.html + * and general semaphore documentation. + */ +class CountingSemaphoreUsingTask: public SemaphoreIF { +public: + CountingSemaphoreUsingTask(const uint8_t maxCount, uint8_t initCount); + virtual ~CountingSemaphoreUsingTask(); + + /** + * Acquire the counting semaphore. + * If no semaphores are available, the task will be blocked + * for a maximum of #timeoutMs or until one is given back, + * for example by an ISR or another task. + * @param timeoutMs + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout + */ + ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, + uint32_t timeoutMs = portMAX_DELAY) override; + + /** + * Release a semaphore, increasing the number of available counting + * semaphores up to the #maxCount value. + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are + * already available. + */ + ReturnValue_t release() override; + + uint8_t getSemaphoreCounter() const override; + /** + * Get the semaphore counter from an ISR. + * @param task + * @param higherPriorityTaskWoken This will be set to pdPASS if a task with + * a higher priority was unblocked. A context switch should be requested + * from an ISR if this is the case (see TaskManagement functions) + * @return + */ + static uint8_t getSemaphoreCounterFromISR(TaskHandle_t task, + BaseType_t* higherPriorityTaskWoken); + + /** + * Acquire with a timeout value in ticks + * @param timeoutTicks + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout + */ + ReturnValue_t acquireWithTickTimeout( + TimeoutType timeoutType = TimeoutType::BLOCKING, + TickType_t timeoutTicks = portMAX_DELAY); + + /** + * Get handle to the task related to the semaphore. + * @return + */ + TaskHandle_t getTaskHandle(); + + /** + * Release semaphore of task by supplying task handle + * @param taskToNotify + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are + * already available. + */ + static ReturnValue_t release(TaskHandle_t taskToNotify); + /** + * Release seamphore of a task from an ISR. + * @param taskToNotify + * @param higherPriorityTaskWoken This will be set to pdPASS if a task with + * a higher priority was unblocked. A context switch should be requested + * from an ISR if this is the case (see TaskManagement functions) + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are + * already available. + */ + static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify, + BaseType_t* higherPriorityTaskWoken); + + uint8_t getMaxCount() const; + +private: + TaskHandle_t handle; + const uint8_t maxCount; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ */ diff --git a/osal/FreeRTOS/CountingSemaphore.cpp b/osal/FreeRTOS/CountingSemaphore.cpp index 957f6a31..0b218e54 100644 --- a/osal/FreeRTOS/CountingSemaphore.cpp +++ b/osal/FreeRTOS/CountingSemaphore.cpp @@ -1,43 +1,43 @@ -#include -#include -#include - -#include - -// Make sure #define configUSE_COUNTING_SEMAPHORES 1 is set in -// free FreeRTOSConfig.h file. -CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount): - maxCount(maxCount), initCount(initCount) { - if(initCount > maxCount) { - sif::error << "CountingSemaphoreUsingTask: Max count bigger than " - "intial cout. Setting initial count to max count." << std::endl; - initCount = maxCount; - } - - handle = xSemaphoreCreateCounting(maxCount, initCount); - if(handle == nullptr) { - sif::error << "CountingSemaphore: Creation failure" << std::endl; - } -} - -CountingSemaphore::CountingSemaphore(CountingSemaphore&& other): - maxCount(other.maxCount), initCount(other.initCount) { - handle = xSemaphoreCreateCounting(other.maxCount, other.initCount); - if(handle == nullptr) { - sif::error << "CountingSemaphore: Creation failure" << std::endl; - } -} - -CountingSemaphore& CountingSemaphore::operator =( - CountingSemaphore&& other) { - handle = xSemaphoreCreateCounting(other.maxCount, other.initCount); - if(handle == nullptr) { - sif::error << "CountingSemaphore: Creation failure" << std::endl; - } - return * this; -} - - -uint8_t CountingSemaphore::getMaxCount() const { - return maxCount; -} +#include "../../osal/FreeRTOS/CountingSemaphore.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../osal/FreeRTOS/TaskManagement.h" + +#include + +// Make sure #define configUSE_COUNTING_SEMAPHORES 1 is set in +// free FreeRTOSConfig.h file. +CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount): + maxCount(maxCount), initCount(initCount) { + if(initCount > maxCount) { + sif::error << "CountingSemaphoreUsingTask: Max count bigger than " + "intial cout. Setting initial count to max count." << std::endl; + initCount = maxCount; + } + + handle = xSemaphoreCreateCounting(maxCount, initCount); + if(handle == nullptr) { + sif::error << "CountingSemaphore: Creation failure" << std::endl; + } +} + +CountingSemaphore::CountingSemaphore(CountingSemaphore&& other): + maxCount(other.maxCount), initCount(other.initCount) { + handle = xSemaphoreCreateCounting(other.maxCount, other.initCount); + if(handle == nullptr) { + sif::error << "CountingSemaphore: Creation failure" << std::endl; + } +} + +CountingSemaphore& CountingSemaphore::operator =( + CountingSemaphore&& other) { + handle = xSemaphoreCreateCounting(other.maxCount, other.initCount); + if(handle == nullptr) { + sif::error << "CountingSemaphore: Creation failure" << std::endl; + } + return * this; +} + + +uint8_t CountingSemaphore::getMaxCount() const { + return maxCount; +} diff --git a/osal/FreeRTOS/CountingSemaphore.h b/osal/FreeRTOS/CountingSemaphore.h index dca3ab0e..9432ed81 100644 --- a/osal/FreeRTOS/CountingSemaphore.h +++ b/osal/FreeRTOS/CountingSemaphore.h @@ -1,34 +1,34 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ -#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ -#include - -/** - * @brief Counting semaphores, which can be acquire more than once. - * @details - * See: https://www.freertos.org/CreateCounting.html - * API of counting semaphores is almost identical to binary semaphores, - * so we just inherit from binary semaphore and provide the respective - * constructors. - */ -class CountingSemaphore: public BinarySemaphore { -public: - CountingSemaphore(const uint8_t maxCount, uint8_t initCount); - //! @brief Copy ctor, disabled - CountingSemaphore(const CountingSemaphore&) = delete; - //! @brief Copy assignment, disabled - CountingSemaphore& operator=(const CountingSemaphore&) = delete; - //! @brief Move ctor - CountingSemaphore (CountingSemaphore &&); - //! @brief Move assignment - CountingSemaphore & operator=(CountingSemaphore &&); - - /* Same API as binary semaphore otherwise. acquire() can be called - * until there are not semaphores left and release() can be called - * until maxCount is reached. */ - uint8_t getMaxCount() const; -private: - const uint8_t maxCount; - uint8_t initCount = 0; -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ +#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ +#include "../../osal/FreeRTOS/BinarySemaphore.h" + +/** + * @brief Counting semaphores, which can be acquire more than once. + * @details + * See: https://www.freertos.org/CreateCounting.html + * API of counting semaphores is almost identical to binary semaphores, + * so we just inherit from binary semaphore and provide the respective + * constructors. + */ +class CountingSemaphore: public BinarySemaphore { +public: + CountingSemaphore(const uint8_t maxCount, uint8_t initCount); + //! @brief Copy ctor, disabled + CountingSemaphore(const CountingSemaphore&) = delete; + //! @brief Copy assignment, disabled + CountingSemaphore& operator=(const CountingSemaphore&) = delete; + //! @brief Move ctor + CountingSemaphore (CountingSemaphore &&); + //! @brief Move assignment + CountingSemaphore & operator=(CountingSemaphore &&); + + /* Same API as binary semaphore otherwise. acquire() can be called + * until there are not semaphores left and release() can be called + * until maxCount is reached. */ + uint8_t getMaxCount() const; +private: + const uint8_t maxCount; + uint8_t initCount = 0; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */ diff --git a/osal/FreeRTOS/SemaphoreFactory.cpp b/osal/FreeRTOS/SemaphoreFactory.cpp index 78427f6c..8575cf4a 100644 --- a/osal/FreeRTOS/SemaphoreFactory.cpp +++ b/osal/FreeRTOS/SemaphoreFactory.cpp @@ -1,61 +1,59 @@ -#include -#include -#include -#include -#include -#include - -SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; -const uint32_t SemaphoreIF::POLLING = 0; -const uint32_t SemaphoreIF::BLOCKING = portMAX_DELAY; - -static const uint32_t USE_REGULAR_SEMAPHORES = 0; -static const uint32_t USE_TASK_NOTIFICATIONS = 1; - -SemaphoreFactory::SemaphoreFactory() { -} - -SemaphoreFactory::~SemaphoreFactory() { - delete factoryInstance; -} - -SemaphoreFactory* SemaphoreFactory::instance() { - if (factoryInstance == nullptr){ - factoryInstance = new SemaphoreFactory(); - } - return SemaphoreFactory::factoryInstance; -} - -SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t argument) { - if(argument == USE_REGULAR_SEMAPHORES) { - return new BinarySemaphore(); - } - else if(argument == USE_TASK_NOTIFICATIONS) { - return new BinarySemaphoreUsingTask(); - } - else { - sif::warning << "SemaphoreFactory: Invalid argument, return regular" - "binary semaphore" << std::endl; - return new BinarySemaphore(); - } -} - -SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t maxCount, - uint8_t initCount, uint32_t argument) { - if(argument == USE_REGULAR_SEMAPHORES) { - return new CountingSemaphore(maxCount, initCount); - } - else if(argument == USE_TASK_NOTIFICATIONS) { - return new CountingSemaphoreUsingTask(maxCount, initCount); - } - else { - sif::warning << "SemaphoreFactory: Invalid argument, return regular" - "binary semaphore" << std::endl; - return new CountingSemaphore(maxCount, initCount); - } - -} - -void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { - delete semaphore; -} +#include "../../osal/FreeRTOS/BinarySemaphore.h" +#include "../../osal/FreeRTOS/BinSemaphUsingTask.h" +#include "../../osal/FreeRTOS/CountingSemaphore.h" +#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h" +#include "../../tasks/SemaphoreFactory.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; + +static const uint32_t USE_REGULAR_SEMAPHORES = 0; +static const uint32_t USE_TASK_NOTIFICATIONS = 1; + +SemaphoreFactory::SemaphoreFactory() { +} + +SemaphoreFactory::~SemaphoreFactory() { + delete factoryInstance; +} + +SemaphoreFactory* SemaphoreFactory::instance() { + if (factoryInstance == nullptr){ + factoryInstance = new SemaphoreFactory(); + } + return SemaphoreFactory::factoryInstance; +} + +SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t argument) { + if(argument == USE_REGULAR_SEMAPHORES) { + return new BinarySemaphore(); + } + else if(argument == USE_TASK_NOTIFICATIONS) { + return new BinarySemaphoreUsingTask(); + } + else { + sif::warning << "SemaphoreFactory: Invalid argument, return regular" + "binary semaphore" << std::endl; + return new BinarySemaphore(); + } +} + +SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t maxCount, + uint8_t initCount, uint32_t argument) { + if(argument == USE_REGULAR_SEMAPHORES) { + return new CountingSemaphore(maxCount, initCount); + } + else if(argument == USE_TASK_NOTIFICATIONS) { + return new CountingSemaphoreUsingTask(maxCount, initCount); + } + else { + sif::warning << "SemaphoreFactory: Invalid argument, return regular" + "binary semaphore" << std::endl; + return new CountingSemaphore(maxCount, initCount); + } + +} + +void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { + delete semaphore; +} diff --git a/tasks/SemaphoreIF.h b/tasks/SemaphoreIF.h index 4fc92ebd..30d4ed88 100644 --- a/tasks/SemaphoreIF.h +++ b/tasks/SemaphoreIF.h @@ -1,72 +1,68 @@ -#ifndef FRAMEWORK_TASKS_SEMAPHOREIF_H_ -#define FRAMEWORK_TASKS_SEMAPHOREIF_H_ -#include -#include -#include - -/** - * @brief Generic interface for semaphores, which can be used to achieve - * task synchronization. This is a generic interface which can be - * used for both binary semaphores and counting semaphores. - * @details - * A semaphore is a synchronization primitive. - * See: https://en.wikipedia.org/wiki/Semaphore_(programming) - * A semaphore can be used to achieve task synchonization and track the - * availability of resources by using either the binary or the counting - * semaphore types. - * - * If mutual exlcusion of a resource is desired, a mutex should be used, - * which is a special form of a semaphore and has an own interface. - */ -class SemaphoreIF { -public: - virtual~ SemaphoreIF() {}; - /** - * @brief Timeout value used for polling lock attempt. - * @details - * If the lock is not successfull, MUTEX_TIMEOUT will be returned - * immediately. Value needs to be defined in implementation. - */ - static const uint32_t POLLING; - /** - * @brief Timeout value used for permanent blocking lock attempt. - * @details - * The task will be blocked (indefinitely) until the mutex is unlocked. - * Value needs to be defined in implementation. - */ - static const uint32_t BLOCKING; - - static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; - //! Semaphore timeout - static constexpr ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(1); - //! The current semaphore can not be given, because it is not owned - static constexpr ReturnValue_t SEMAPHORE_NOT_OWNED = MAKE_RETURN_CODE(2); - static constexpr ReturnValue_t SEMAPHORE_INVALID = MAKE_RETURN_CODE(3); - - /** - * Generic call to acquire a semaphore. - * If there are no more semaphores to be taken (for a counting semaphore, - * a semaphore may be taken more than once), the taks will block - * for a maximum of timeoutMs while trying to acquire the semaphore. - * This can be used to achieve task synchrnization. - * @param timeoutMs - * @return - c RETURN_OK for successfull acquisition - */ - virtual ReturnValue_t acquire(uint32_t timeoutMs) = 0; - - /** - * Corrensponding call to release a semaphore. - * @return -@c RETURN_OK for successfull release - */ - virtual ReturnValue_t release() = 0; - - /** - * If the semaphore is a counting semaphore then the semaphores current - * count value is returned. If the semaphore is a binary semaphore then 1 - * is returned if the semaphore is available, and 0 is returned if the - * semaphore is not available. - */ - virtual uint8_t getSemaphoreCounter() const = 0; -}; - -#endif /* FRAMEWORK_TASKS_SEMAPHOREIF_H_ */ +#ifndef FRAMEWORK_TASKS_SEMAPHOREIF_H_ +#define FRAMEWORK_TASKS_SEMAPHOREIF_H_ +#include "../returnvalues/FwClassIds.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include + +/** + * @brief Generic interface for semaphores, which can be used to achieve + * task synchronization. This is a generic interface which can be + * used for both binary semaphores and counting semaphores. + * @details + * A semaphore is a synchronization primitive. + * See: https://en.wikipedia.org/wiki/Semaphore_(programming) + * A semaphore can be used to achieve task synchonization and track the + * availability of resources by using either the binary or the counting + * semaphore types. + * + * If mutual exlcusion of a resource is desired, a mutex should be used, + * which is a special form of a semaphore and has an own interface. + */ +class SemaphoreIF { +public: + /** + * Different types of timeout for the mutex lock. + */ + enum TimeoutType { + POLLING, //!< If mutex is not available, return immediately + WAITING, //!< Wait a specified time for the mutex to become available + BLOCKING //!< Block indefinitely until the mutex becomes available. + }; + + virtual~ SemaphoreIF() {}; + + static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; + //! Semaphore timeout + static constexpr ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(1); + //! The current semaphore can not be given, because it is not owned + static constexpr ReturnValue_t SEMAPHORE_NOT_OWNED = MAKE_RETURN_CODE(2); + static constexpr ReturnValue_t SEMAPHORE_INVALID = MAKE_RETURN_CODE(3); + + /** + * Generic call to acquire a semaphore. + * If there are no more semaphores to be taken (for a counting semaphore, + * a semaphore may be taken more than once), the taks will block + * for a maximum of timeoutMs while trying to acquire the semaphore. + * This can be used to achieve task synchrnization. + * @param timeoutMs + * @return - c RETURN_OK for successfull acquisition + */ + virtual ReturnValue_t acquire(TimeoutType timeoutType = + TimeoutType::BLOCKING, uint32_t timeoutMs = 0) = 0; + + /** + * Corrensponding call to release a semaphore. + * @return -@c RETURN_OK for successfull release + */ + virtual ReturnValue_t release() = 0; + + /** + * If the semaphore is a counting semaphore then the semaphores current + * count value is returned. If the semaphore is a binary semaphore then 1 + * is returned if the semaphore is available, and 0 is returned if the + * semaphore is not available. + */ + virtual uint8_t getSemaphoreCounter() const = 0; +}; + +#endif /* FRAMEWORK_TASKS_SEMAPHOREIF_H_ */ From 073f168b9507800d11ddcee8f63deb6025c513e7 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 27 Aug 2020 16:27:54 +0200 Subject: [PATCH 269/653] task management function taken over from master --- osal/FreeRTOS/TaskManagement.cpp | 23 ++++++++++++----------- osal/FreeRTOS/TaskManagement.h | 23 ++++++++++++----------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/osal/FreeRTOS/TaskManagement.cpp b/osal/FreeRTOS/TaskManagement.cpp index 7871ab2e..16682d36 100644 --- a/osal/FreeRTOS/TaskManagement.cpp +++ b/osal/FreeRTOS/TaskManagement.cpp @@ -1,23 +1,24 @@ -#include - -void TaskManagement::requestContextSwitchFromTask() { +#include "../../osal/FreeRTOS/TaskManagement.h" + +void TaskManagement::vRequestContextSwitchFromTask() { vTaskDelay(0); } - + void TaskManagement::requestContextSwitch( - CallContext callContext = CallContext::TASK) { + CallContext callContext = CallContext::TASK) { if(callContext == CallContext::ISR) { // This function depends on the partmacro.h definition for the specific device - requestContextSwitchFromISR(); + vRequestContextSwitchFromISR(); } else { - requestContextSwitchFromTask(); + vRequestContextSwitchFromTask(); } } - + TaskHandle_t TaskManagement::getCurrentTaskHandle() { return xTaskGetCurrentTaskHandle(); } -configSTACK_DEPTH_TYPE TaskManagement::getTaskStackHighWatermark() { - return uxTaskGetStackHighWaterMark(TaskManagement::getCurrentTaskHandle()); -} +size_t TaskManagement::getTaskStackHighWatermark( + TaskHandle_t task) { + return uxTaskGetStackHighWaterMark(task) * sizeof(StackType_t); +} diff --git a/osal/FreeRTOS/TaskManagement.h b/osal/FreeRTOS/TaskManagement.h index 39c24377..43003d76 100644 --- a/osal/FreeRTOS/TaskManagement.h +++ b/osal/FreeRTOS/TaskManagement.h @@ -1,25 +1,25 @@ #ifndef FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ #define FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ -#include +#include "../../returnvalues/HasReturnvaluesIF.h" extern "C" { #include #include } #include - + /** * Architecture dependant portmacro.h function call. * Should be implemented in bsp. */ -extern "C" void requestContextSwitchFromISR(); +extern void vRequestContextSwitchFromISR(); /*! * Used by functions to tell if they are being called from - * within an ISR or from a regular task. This is required because FreeRTOS + * within an ISR or from a regular task. This is required because FreeRTOS * has different functions for handling semaphores and messages from within - * an ISR and task. + * an ISR and task. */ enum class CallContext { TASK = 0x00,//!< task_context @@ -29,19 +29,19 @@ enum class CallContext { class TaskManagement { public: - /** + /** * @brief In this function, a function dependant on the portmacro.h header * function calls to request a context switch can be specified. * This can be used if sending to the queue from an ISR caused a task - * to unblock and a context switch is required. + * to unblock and a context switch is required. */ static void requestContextSwitch(CallContext callContext); /** * If task preemption in FreeRTOS is disabled, a context switch * can be requested manually by calling this function. - */ - static void requestContextSwitchFromTask(void); + */ + static void vRequestContextSwitchFromTask(void); /** * @return The current task handle @@ -56,8 +56,9 @@ public: * E.g. on a 32 bit machine, a value of 200 means 800 bytes. * @return Smallest value of stack remaining since the task was started in * words. - */ - static configSTACK_DEPTH_TYPE getTaskStackHighWatermark(); + */ + static size_t getTaskStackHighWatermark( + TaskHandle_t task = nullptr); }; #endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */ From 73db79a3fefb1d7153a9a6f9cbaceb55b725d494 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 27 Aug 2020 17:06:10 +0200 Subject: [PATCH 270/653] updated linux implementation --- osal/linux/BinarySemaphore.cpp | 13 ++-- osal/linux/BinarySemaphore.h | 8 +-- osal/linux/CountingSemaphore.cpp | 108 +++++++++++++++---------------- osal/linux/CountingSemaphore.h | 74 ++++++++++----------- osal/linux/SemaphoreFactory.cpp | 69 ++++++++++---------- 5 files changed, 135 insertions(+), 137 deletions(-) diff --git a/osal/linux/BinarySemaphore.cpp b/osal/linux/BinarySemaphore.cpp index e2ad9b58..5216ff37 100644 --- a/osal/linux/BinarySemaphore.cpp +++ b/osal/linux/BinarySemaphore.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "../../osal/linux/BinarySemaphore.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" extern "C" { #include @@ -25,15 +25,16 @@ BinarySemaphore& BinarySemaphore::operator =( return * this; } -ReturnValue_t BinarySemaphore::acquire(uint32_t timeoutMs) { +ReturnValue_t BinarySemaphore::acquire(TimeoutType timeoutType, + uint32_t timeoutMs) { int result = 0; - if(timeoutMs == SemaphoreIF::POLLING) { + if(timeoutType == TimeoutType::POLLING) { result = sem_trywait(&handle); } - else if(timeoutMs == SemaphoreIF::BLOCKING) { + else if(timeoutType == TimeoutType::BLOCKING) { result = sem_wait(&handle); } - else if(timeoutMs > SemaphoreIF::POLLING){ + else if(timeoutType == TimeoutType::WAITING){ timespec timeOut; clock_gettime(CLOCK_REALTIME, &timeOut); uint64_t nseconds = timeOut.tv_sec * 1000000000 + timeOut.tv_nsec; diff --git a/osal/linux/BinarySemaphore.h b/osal/linux/BinarySemaphore.h index 9d4ed1cd..4181de85 100644 --- a/osal/linux/BinarySemaphore.h +++ b/osal/linux/BinarySemaphore.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_ #define FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_ -#include -#include +#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../tasks/SemaphoreIF.h" extern "C" { #include @@ -49,8 +49,8 @@ public: * @return -@c RETURN_OK on success * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout */ - ReturnValue_t acquire(uint32_t timeoutMs = - SemaphoreIF::BLOCKING) override; + ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, + uint32_t timeoutMs = 0) override; /** * Release the binary semaphore. diff --git a/osal/linux/CountingSemaphore.cpp b/osal/linux/CountingSemaphore.cpp index dfc4d801..ef32539b 100644 --- a/osal/linux/CountingSemaphore.cpp +++ b/osal/linux/CountingSemaphore.cpp @@ -1,54 +1,54 @@ -#include -#include - -CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount): - maxCount(maxCount), initCount(initCount) { - if(initCount > maxCount) { - sif::error << "CountingSemaphoreUsingTask: Max count bigger than " - "intial cout. Setting initial count to max count." << std::endl; - initCount = maxCount; - } - - initSemaphore(initCount); -} - -CountingSemaphore::CountingSemaphore(CountingSemaphore&& other): - maxCount(other.maxCount), initCount(other.initCount) { - initSemaphore(initCount); -} - -CountingSemaphore& CountingSemaphore::operator =( - CountingSemaphore&& other) { - initSemaphore(other.initCount); - return * this; -} - -ReturnValue_t CountingSemaphore::release() { - ReturnValue_t result = checkCount(&handle, maxCount); - if(result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - return CountingSemaphore::release(&this->handle); -} - -ReturnValue_t CountingSemaphore::release(sem_t* handle) { - int result = sem_post(handle); - if(result == 0) { - return HasReturnvaluesIF::RETURN_OK; - } - - switch(errno) { - case(EINVAL): - // Semaphore invalid - return SemaphoreIF::SEMAPHORE_INVALID; - case(EOVERFLOW): - // SEM_MAX_VALUE overflow. This should never happen - default: - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -uint8_t CountingSemaphore::getMaxCount() const { - return maxCount; -} - +#include "../../osal/linux/CountingSemaphore.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount): + maxCount(maxCount), initCount(initCount) { + if(initCount > maxCount) { + sif::error << "CountingSemaphoreUsingTask: Max count bigger than " + "intial cout. Setting initial count to max count." << std::endl; + initCount = maxCount; + } + + initSemaphore(initCount); +} + +CountingSemaphore::CountingSemaphore(CountingSemaphore&& other): + maxCount(other.maxCount), initCount(other.initCount) { + initSemaphore(initCount); +} + +CountingSemaphore& CountingSemaphore::operator =( + CountingSemaphore&& other) { + initSemaphore(other.initCount); + return * this; +} + +ReturnValue_t CountingSemaphore::release() { + ReturnValue_t result = checkCount(&handle, maxCount); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return CountingSemaphore::release(&this->handle); +} + +ReturnValue_t CountingSemaphore::release(sem_t* handle) { + int result = sem_post(handle); + if(result == 0) { + return HasReturnvaluesIF::RETURN_OK; + } + + switch(errno) { + case(EINVAL): + // Semaphore invalid + return SemaphoreIF::SEMAPHORE_INVALID; + case(EOVERFLOW): + // SEM_MAX_VALUE overflow. This should never happen + default: + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +uint8_t CountingSemaphore::getMaxCount() const { + return maxCount; +} + diff --git a/osal/linux/CountingSemaphore.h b/osal/linux/CountingSemaphore.h index ba606595..afe21a61 100644 --- a/osal/linux/CountingSemaphore.h +++ b/osal/linux/CountingSemaphore.h @@ -1,37 +1,37 @@ -#ifndef FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_ -#define FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_ -#include - -/** - * @brief Counting semaphores, which can be acquired more than once. - * @details - * See: https://www.freertos.org/CreateCounting.html - * API of counting semaphores is almost identical to binary semaphores, - * so we just inherit from binary semaphore and provide the respective - * constructors. - */ -class CountingSemaphore: public BinarySemaphore { -public: - CountingSemaphore(const uint8_t maxCount, uint8_t initCount); - //! @brief Copy ctor, disabled - CountingSemaphore(const CountingSemaphore&) = delete; - //! @brief Copy assignment, disabled - CountingSemaphore& operator=(const CountingSemaphore&) = delete; - //! @brief Move ctor - CountingSemaphore (CountingSemaphore &&); - //! @brief Move assignment - CountingSemaphore & operator=(CountingSemaphore &&); - - ReturnValue_t release() override; - static ReturnValue_t release(sem_t* sem); - /* Same API as binary semaphore otherwise. acquire() can be called - * until there are not semaphores left and release() can be called - * until maxCount is reached. */ - - uint8_t getMaxCount() const; -private: - const uint8_t maxCount; - uint8_t initCount = 0; -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */ +#ifndef FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_ +#define FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_ +#include "../../osal/linux/BinarySemaphore.h" + +/** + * @brief Counting semaphores, which can be acquired more than once. + * @details + * See: https://www.freertos.org/CreateCounting.html + * API of counting semaphores is almost identical to binary semaphores, + * so we just inherit from binary semaphore and provide the respective + * constructors. + */ +class CountingSemaphore: public BinarySemaphore { +public: + CountingSemaphore(const uint8_t maxCount, uint8_t initCount); + //! @brief Copy ctor, disabled + CountingSemaphore(const CountingSemaphore&) = delete; + //! @brief Copy assignment, disabled + CountingSemaphore& operator=(const CountingSemaphore&) = delete; + //! @brief Move ctor + CountingSemaphore (CountingSemaphore &&); + //! @brief Move assignment + CountingSemaphore & operator=(CountingSemaphore &&); + + ReturnValue_t release() override; + static ReturnValue_t release(sem_t* sem); + /* Same API as binary semaphore otherwise. acquire() can be called + * until there are not semaphores left and release() can be called + * until maxCount is reached. */ + + uint8_t getMaxCount() const; +private: + const uint8_t maxCount; + uint8_t initCount = 0; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */ diff --git a/osal/linux/SemaphoreFactory.cpp b/osal/linux/SemaphoreFactory.cpp index 4fbd60d9..805865ca 100644 --- a/osal/linux/SemaphoreFactory.cpp +++ b/osal/linux/SemaphoreFactory.cpp @@ -1,36 +1,33 @@ -#include -#include -#include -#include - -const uint32_t SemaphoreIF::POLLING = 0; -const uint32_t SemaphoreIF::BLOCKING = 0xffffffff; - -SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; - -SemaphoreFactory::SemaphoreFactory() { -} - -SemaphoreFactory::~SemaphoreFactory() { - delete factoryInstance; -} - -SemaphoreFactory* SemaphoreFactory::instance() { - if (factoryInstance == nullptr){ - factoryInstance = new SemaphoreFactory(); - } - return SemaphoreFactory::factoryInstance; -} - -SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t arguments) { - return new BinarySemaphore(); -} - -SemaphoreIF* SemaphoreFactory::createCountingSemaphore(const uint8_t maxCount, - uint8_t initCount, uint32_t arguments) { - return new CountingSemaphore(maxCount, initCount); -} - -void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { - delete semaphore; -} +#include "../../tasks/SemaphoreFactory.h" +#include "../../osal/linux/BinarySemaphore.h" +#include "../../osal/linux/CountingSemaphore.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; + +SemaphoreFactory::SemaphoreFactory() { +} + +SemaphoreFactory::~SemaphoreFactory() { + delete factoryInstance; +} + +SemaphoreFactory* SemaphoreFactory::instance() { + if (factoryInstance == nullptr){ + factoryInstance = new SemaphoreFactory(); + } + return SemaphoreFactory::factoryInstance; +} + +SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t arguments) { + return new BinarySemaphore(); +} + +SemaphoreIF* SemaphoreFactory::createCountingSemaphore(const uint8_t maxCount, + uint8_t initCount, uint32_t arguments) { + return new CountingSemaphore(maxCount, initCount); +} + +void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { + delete semaphore; +} From 3be253efd62cae876f3df5fc9689380d3309cf5d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 27 Aug 2020 17:07:42 +0200 Subject: [PATCH 271/653] include fix --- tasks/SemaphoreFactory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/SemaphoreFactory.h b/tasks/SemaphoreFactory.h index 7f8edaf1..bffa59c8 100644 --- a/tasks/SemaphoreFactory.h +++ b/tasks/SemaphoreFactory.h @@ -1,6 +1,6 @@ #ifndef FRAMEWORK_TASKS_SEMAPHOREFACTORY_H_ #define FRAMEWORK_TASKS_SEMAPHOREFACTORY_H_ -#include +#include "../tasks/SemaphoreIF.h" /** * Creates Semaphore. From 0fedad6da09816c8a06615f3903a8e34545001bc Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 27 Aug 2020 17:14:49 +0200 Subject: [PATCH 272/653] semaphore factory update --- osal/linux/SemaphoreFactory.cpp | 4 +- tasks/SemaphoreFactory.h | 99 +++++++++++++++++---------------- 2 files changed, 52 insertions(+), 51 deletions(-) diff --git a/osal/linux/SemaphoreFactory.cpp b/osal/linux/SemaphoreFactory.cpp index 805865ca..bcb5d16f 100644 --- a/osal/linux/SemaphoreFactory.cpp +++ b/osal/linux/SemaphoreFactory.cpp @@ -1,6 +1,6 @@ #include "../../tasks/SemaphoreFactory.h" -#include "../../osal/linux/BinarySemaphore.h" -#include "../../osal/linux/CountingSemaphore.h" +#include "BinarySemaphore.h" +#include "CountingSemaphore.h" #include "../../serviceinterface/ServiceInterfaceStream.h" SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; diff --git a/tasks/SemaphoreFactory.h b/tasks/SemaphoreFactory.h index bffa59c8..2c41a135 100644 --- a/tasks/SemaphoreFactory.h +++ b/tasks/SemaphoreFactory.h @@ -1,49 +1,50 @@ -#ifndef FRAMEWORK_TASKS_SEMAPHOREFACTORY_H_ -#define FRAMEWORK_TASKS_SEMAPHOREFACTORY_H_ -#include "../tasks/SemaphoreIF.h" - -/** - * Creates Semaphore. - * This class is a "singleton" interface, i.e. it provides an - * interface, but also is the base class for a singleton. - */ -class SemaphoreFactory { -public: - virtual ~SemaphoreFactory(); - /** - * Returns the single instance of SemaphoreFactory. - * The implementation of #instance is found in its subclasses. - * Thus, we choose link-time variability of the instance. - */ - static SemaphoreFactory* instance(); - - /** - * Create a binary semaphore. - * Creator function for a binary semaphore which may only be acquired once - * @param argument Can be used to pass implementation specific information. - * @return Pointer to newly created semaphore class instance. - */ - SemaphoreIF* createBinarySemaphore(uint32_t arguments = 0); - /** - * Create a counting semaphore. - * Creator functons for a counting semaphore which may be acquired multiple - * times. - * @param count Semaphore can be taken count times. - * @param initCount Initial count value. - * @param argument Can be used to pass implementation specific information. - * @return - */ - SemaphoreIF* createCountingSemaphore(const uint8_t maxCount, - uint8_t initCount, uint32_t arguments = 0); - - void deleteSemaphore(SemaphoreIF* semaphore); - -private: - /** - * External instantiation is not allowed. - */ - SemaphoreFactory(); - static SemaphoreFactory* factoryInstance; -}; - -#endif /* FRAMEWORK_TASKS_SEMAPHOREFACTORY_H_ */ +#ifndef FSFW_TASKS_SEMAPHOREFACTORY_H_ +#define FSFW_TASKS_SEMAPHOREFACTORY_H_ + +#include "../tasks/SemaphoreIF.h" + +/** + * Creates Semaphore. + * This class is a "singleton" interface, i.e. it provides an + * interface, but also is the base class for a singleton. + */ +class SemaphoreFactory { +public: + virtual ~SemaphoreFactory(); + /** + * Returns the single instance of SemaphoreFactory. + * The implementation of #instance is found in its subclasses. + * Thus, we choose link-time variability of the instance. + */ + static SemaphoreFactory* instance(); + + /** + * Create a binary semaphore. + * Creator function for a binary semaphore which may only be acquired once + * @param argument Can be used to pass implementation specific information. + * @return Pointer to newly created semaphore class instance. + */ + SemaphoreIF* createBinarySemaphore(uint32_t arguments = 0); + /** + * Create a counting semaphore. + * Creator functons for a counting semaphore which may be acquired multiple + * times. + * @param count Semaphore can be taken count times. + * @param initCount Initial count value. + * @param argument Can be used to pass implementation specific information. + * @return + */ + SemaphoreIF* createCountingSemaphore(const uint8_t maxCount, + uint8_t initCount, uint32_t arguments = 0); + + void deleteSemaphore(SemaphoreIF* semaphore); + +private: + /** + * External instantiation is not allowed. + */ + SemaphoreFactory(); + static SemaphoreFactory* factoryInstance; +}; + +#endif /* FSFW_TASKS_SEMAPHOREFACTORY_H_ */ From dfe3658a851d4576738dcd1c973ce0b20672753a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 27 Aug 2020 19:52:25 +0200 Subject: [PATCH 273/653] removed hk stuff --- devicehandlers/ChildHandlerBase.cpp | 8 +++----- devicehandlers/ChildHandlerBase.h | 5 ++--- devicehandlers/DeviceHandlerBase.cpp | 14 -------------- devicehandlers/DeviceHandlerBase.h | 9 +-------- 4 files changed, 6 insertions(+), 30 deletions(-) diff --git a/devicehandlers/ChildHandlerBase.cpp b/devicehandlers/ChildHandlerBase.cpp index acc1b5a0..f18c3812 100644 --- a/devicehandlers/ChildHandlerBase.cpp +++ b/devicehandlers/ChildHandlerBase.cpp @@ -4,15 +4,13 @@ ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF * cookie, - object_id_t hkDestination, uint32_t thermalStatePoolId, - uint32_t thermalRequestPoolId, - object_id_t parent, - FailureIsolationBase* customFdir, size_t cmdQueueSize) : + uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, + object_id_t parent, FailureIsolationBase* customFdir, + size_t cmdQueueSize) : DeviceHandlerBase(setObjectId, deviceCommunication, cookie, (customFdir == nullptr? &childHandlerFdir : customFdir), cmdQueueSize), parentId(parent), childHandlerFdir(setObjectId) { - this->setHkDestination(hkDestination); this->setThermalStateRequestPoolIds(thermalStatePoolId, thermalRequestPoolId); diff --git a/devicehandlers/ChildHandlerBase.h b/devicehandlers/ChildHandlerBase.h index 625955f0..70c27952 100644 --- a/devicehandlers/ChildHandlerBase.h +++ b/devicehandlers/ChildHandlerBase.h @@ -7,9 +7,8 @@ class ChildHandlerBase: public DeviceHandlerBase { public: ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, - CookieIF * cookie, object_id_t hkDestination, - uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, - object_id_t parent = objects::NO_OBJECT, + CookieIF * cookie, uint32_t thermalStatePoolId, + uint32_t thermalRequestPoolId, object_id_t parent = objects::NO_OBJECT, FailureIsolationBase* customFdir = nullptr, size_t cmdQueueSize = 20); virtual ~ChildHandlerBase(); diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index ff6a5dbe..017ea8d2 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -17,7 +17,6 @@ object_id_t DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT; object_id_t DeviceHandlerBase::rawDataReceiverId = objects::NO_OBJECT; object_id_t DeviceHandlerBase::defaultFdirParentId = objects::NO_OBJECT; -object_id_t DeviceHandlerBase::defaultHkDestination = objects::NO_OBJECT; DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF * comCookie, @@ -49,10 +48,6 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, } } -void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) { - this->hkDestination = hkDestination; -} - void DeviceHandlerBase::setThermalStateRequestPoolIds( uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId) { this->deviceThermalRequestPoolId = thermalStatePoolId; @@ -188,15 +183,6 @@ ReturnValue_t DeviceHandlerBase::initialize() { return result; } -// if(hkDestination == objects::NO_OBJECT) { -// hkDestination = defaultHkDestination; -// } -// -// result = hkManager.initialize(commandQueue, hkDestination); -// if (result != HasReturnvaluesIF::RETURN_OK) { -// return result; -// } - fillCommandAndReplyMap(); //Set temperature target state to NON_OP. diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index d41a50e5..5666f35e 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -85,8 +85,7 @@ class DeviceHandlerBase: public DeviceHandlerIF, public HasModesIF, public HasHealthIF, public HasActionsIF, - public ReceivesParameterMessagesIF - /* public HasLocalDataPoolIF */ { + public ReceivesParameterMessagesIF { friend void (Factory::setStaticFrameworkObjectIds)(); public: /** @@ -107,7 +106,6 @@ public: CookieIF * comCookie, FailureIsolationBase* fdirInstance = nullptr, size_t cmdQueueSize = 20); - void setHkDestination(object_id_t hkDestination); void setThermalStateRequestPoolIds(uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId); @@ -1036,11 +1034,6 @@ private: /** the object used to set power switches */ PowerSwitchIF *powerSwitcher = nullptr; - /** Cached for initialize() */ - static object_id_t defaultHkDestination; - /** HK destination can also be set individually */ - object_id_t hkDestination = objects::NO_OBJECT; - /** * @brief Used for timing out mode transitions. * Set when setMode() is called. From 8f2d5a5528c7247a0f1cd60a6dc29ffd85eaeb45 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 27 Aug 2020 19:58:35 +0200 Subject: [PATCH 274/653] DH fdir improvements --- devicehandlers/DeviceHandlerFailureIsolation.cpp | 6 +++--- devicehandlers/DeviceHandlerFailureIsolation.h | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/devicehandlers/DeviceHandlerFailureIsolation.cpp b/devicehandlers/DeviceHandlerFailureIsolation.cpp index 1f098d55..8831f9ae 100644 --- a/devicehandlers/DeviceHandlerFailureIsolation.cpp +++ b/devicehandlers/DeviceHandlerFailureIsolation.cpp @@ -5,7 +5,8 @@ #include "../serviceinterface/ServiceInterfaceStream.h" #include "../thermal/ThermalComponentIF.h" -object_id_t DeviceHandlerFailureIsolation::powerConfirmationId = 0; +object_id_t DeviceHandlerFailureIsolation::powerConfirmationId = + objects::NO_OBJECT; DeviceHandlerFailureIsolation::DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent) : @@ -70,7 +71,7 @@ ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event) break; //****Power***** case PowerSwitchIF::SWITCH_WENT_OFF: - if(hasPowerConfirmation) { + if(powerConfirmation != MessageQueueIF::NO_QUEUE) { result = sendConfirmationRequest(event, powerConfirmation); if (result == RETURN_OK) { setFdirState(DEVICE_MIGHT_BE_OFF); @@ -171,7 +172,6 @@ ReturnValue_t DeviceHandlerFailureIsolation::initialize() { powerConfirmationId); if (power != nullptr) { powerConfirmation = power->getEventReceptionQueue(); - hasPowerConfirmation = true; } return RETURN_OK; diff --git a/devicehandlers/DeviceHandlerFailureIsolation.h b/devicehandlers/DeviceHandlerFailureIsolation.h index 56649ee9..6ed53efd 100644 --- a/devicehandlers/DeviceHandlerFailureIsolation.h +++ b/devicehandlers/DeviceHandlerFailureIsolation.h @@ -3,11 +3,11 @@ #include "../fdir/FaultCounter.h" #include "../fdir/FailureIsolationBase.h" + namespace Factory{ void setStaticFrameworkObjectIds(); } - class DeviceHandlerFailureIsolation: public FailureIsolationBase { friend void (Factory::setStaticFrameworkObjectIds)(); friend class Heater; @@ -28,8 +28,7 @@ protected: NONE, RECOVERY_ONGOING, DEVICE_MIGHT_BE_OFF, AWAIT_SHUTDOWN }; FDIRState fdirState; - bool hasPowerConfirmation = false; - MessageQueueId_t powerConfirmation; + MessageQueueId_t powerConfirmation = MessageQueueIF::NO_QUEUE; static object_id_t powerConfirmationId; // TODO: Are those hardcoded value? How can they be changed. static const uint32_t MAX_REBOOT = 1; From c4c607776c38d9913be6bf2b4ada0d767d345c53 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 27 Aug 2020 20:07:03 +0200 Subject: [PATCH 275/653] important fix, 0 init removed --- .../DeviceHandlerFailureIsolation.cpp | 15 ++++++++---- .../DeviceHandlerFailureIsolation.h | 24 +++++++++++-------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/devicehandlers/DeviceHandlerFailureIsolation.cpp b/devicehandlers/DeviceHandlerFailureIsolation.cpp index 8831f9ae..9fbe71d8 100644 --- a/devicehandlers/DeviceHandlerFailureIsolation.cpp +++ b/devicehandlers/DeviceHandlerFailureIsolation.cpp @@ -1,5 +1,7 @@ -#include "DeviceHandlerBase.h" #include "DeviceHandlerFailureIsolation.h" + +#include "../devicehandlers/DeviceHandlerIF.h" +#include "../modes/HasModesIF.h" #include "../health/HealthTableIF.h" #include "../power/Fuse.h" #include "../serviceinterface/ServiceInterfaceStream.h" @@ -11,12 +13,15 @@ object_id_t DeviceHandlerFailureIsolation::powerConfirmationId = DeviceHandlerFailureIsolation::DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent) : FailureIsolationBase(owner, parent), - strangeReplyCount(MAX_STRANGE_REPLIES, STRANGE_REPLIES_TIME_MS, + strangeReplyCount(DEFAULT_MAX_STRANGE_REPLIES, + DEFAULT_STRANGE_REPLIES_TIME_MS, parameterDomainBase++), - missedReplyCount( MAX_MISSED_REPLY_COUNT, MISSED_REPLY_TIME_MS, + missedReplyCount( DEFAULT_MAX_MISSED_REPLY_COUNT, + DEFAULT_MISSED_REPLY_TIME_MS, parameterDomainBase++), - recoveryCounter(MAX_REBOOT, REBOOT_TIME_MS, parameterDomainBase++), - fdirState(NONE), powerConfirmation(0) { + recoveryCounter(DEFAULT_MAX_REBOOT, DEFAULT_REBOOT_TIME_MS, + parameterDomainBase++), + fdirState(NONE) { } DeviceHandlerFailureIsolation::~DeviceHandlerFailureIsolation() { diff --git a/devicehandlers/DeviceHandlerFailureIsolation.h b/devicehandlers/DeviceHandlerFailureIsolation.h index 6ed53efd..8a3fd9dd 100644 --- a/devicehandlers/DeviceHandlerFailureIsolation.h +++ b/devicehandlers/DeviceHandlerFailureIsolation.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFAILUREISOLATION_H_ -#define FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFAILUREISOLATION_H_ +#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERFAILUREISOLATION_H_ +#define FSFW_DEVICEHANDLERS_DEVICEHANDLERFAILUREISOLATION_H_ #include "../fdir/FaultCounter.h" #include "../fdir/FailureIsolationBase.h" @@ -20,23 +20,27 @@ public: virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues, uint16_t startAtIndex); + protected: FaultCounter strangeReplyCount; FaultCounter missedReplyCount; FaultCounter recoveryCounter; + enum FDIRState { NONE, RECOVERY_ONGOING, DEVICE_MIGHT_BE_OFF, AWAIT_SHUTDOWN }; FDIRState fdirState; + MessageQueueId_t powerConfirmation = MessageQueueIF::NO_QUEUE; static object_id_t powerConfirmationId; - // TODO: Are those hardcoded value? How can they be changed. - 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; + + static const uint32_t DEFAULT_MAX_REBOOT = 1; + static const uint32_t DEFAULT_REBOOT_TIME_MS = 180000; + static const uint32_t DEFAULT_MAX_STRANGE_REPLIES = 10; + static const uint32_t DEFAULT_STRANGE_REPLIES_TIME_MS = 10000; + static const uint32_t DEFAULT_MAX_MISSED_REPLY_COUNT = 5; + static const uint32_t DEFAULT_MISSED_REPLY_TIME_MS = 10000; + virtual ReturnValue_t eventReceived(EventMessage* event); virtual void eventConfirmed(EventMessage* event); void wasParentsFault(EventMessage* event); @@ -50,4 +54,4 @@ protected: bool isFdirInActionOrAreWeFaulty(EventMessage* event); }; -#endif /* FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFAILUREISOLATION_H_ */ +#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERFAILUREISOLATION_H_ */ From 54112acf625b3ca918313b3186a127521686008f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 27 Aug 2020 20:11:36 +0200 Subject: [PATCH 276/653] chb update --- devicehandlers/ChildHandlerBase.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/devicehandlers/ChildHandlerBase.h b/devicehandlers/ChildHandlerBase.h index 70c27952..3e9652a3 100644 --- a/devicehandlers/ChildHandlerBase.h +++ b/devicehandlers/ChildHandlerBase.h @@ -1,15 +1,17 @@ -#ifndef PAYLOADHANDLERBASE_H_ -#define PAYLOADHANDLERBASE_H_ +#ifndef FSFW_DEVICES_CHILDHANDLERBASE_H_ +#define FSFW_DEVICES_CHILDHANDLERBASE_H_ -#include "../devicehandlers/ChildHandlerFDIR.h" -#include "../devicehandlers/DeviceHandlerBase.h" +#include "ChildHandlerFDIR.h" +#include "DeviceHandlerBase.h" class ChildHandlerBase: public DeviceHandlerBase { public: ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF * cookie, uint32_t thermalStatePoolId, - uint32_t thermalRequestPoolId, object_id_t parent = objects::NO_OBJECT, - FailureIsolationBase* customFdir = nullptr, size_t cmdQueueSize = 20); + uint32_t thermalRequestPoolId, + object_id_t parent = objects::NO_OBJECT, + FailureIsolationBase* customFdir = nullptr, + size_t cmdQueueSize = 20); virtual ~ChildHandlerBase(); virtual ReturnValue_t initialize(); @@ -20,4 +22,5 @@ protected: }; -#endif /* PAYLOADHANDLERBASE_H_ */ +#endif /* FSFW_DEVICES_CHILDHANDLERBASE_H_ */ + From eb503ae030fdc5a8c7925f58cad85427d77251cf Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 27 Aug 2020 20:19:27 +0200 Subject: [PATCH 277/653] include guard fix --- container/DynamicFIFO.h | 6 +++--- container/FIFOBase.h | 6 +++--- container/FIFOBase.tpp | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/container/DynamicFIFO.h b/container/DynamicFIFO.h index 5cdae81a..7fa0c32c 100644 --- a/container/DynamicFIFO.h +++ b/container/DynamicFIFO.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ -#define FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ +#ifndef FSFW_CONTAINER_DYNAMICFIFO_H_ +#define FSFW_CONTAINER_DYNAMICFIFO_H_ #include "FIFOBase.h" #include @@ -39,4 +39,4 @@ private: std::vector fifoVector; }; -#endif /* FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ */ +#endif /* FSFW_CONTAINER_DYNAMICFIFO_H_ */ diff --git a/container/FIFOBase.h b/container/FIFOBase.h index acb38b82..bbabd67c 100644 --- a/container/FIFOBase.h +++ b/container/FIFOBase.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_CONTAINER_FIFOBASE_H_ -#define FRAMEWORK_CONTAINER_FIFOBASE_H_ +#ifndef FSFW_CONTAINER_FIFOBASE_H_ +#define FSFW_CONTAINER_FIFOBASE_H_ #include "../returnvalues/HasReturnvaluesIF.h" #include @@ -62,4 +62,4 @@ protected: #include "FIFOBase.tpp" -#endif /* FRAMEWORK_CONTAINER_FIFOBASE_H_ */ +#endif /* FSFW_CONTAINER_FIFOBASE_H_ */ diff --git a/container/FIFOBase.tpp b/container/FIFOBase.tpp index c73e9d59..e1287dcf 100644 --- a/container/FIFOBase.tpp +++ b/container/FIFOBase.tpp @@ -1,7 +1,7 @@ -#ifndef FRAMEWORK_CONTAINER_FIFOBASE_TPP_ -#define FRAMEWORK_CONTAINER_FIFOBASE_TPP_ +#ifndef FSFW_CONTAINER_FIFOBASE_TPP_ +#define FSFW_CONTAINER_FIFOBASE_TPP_ -#ifndef FRAMEWORK_CONTAINER_FIFOBASE_H_ +#ifndef FSFW_CONTAINER_FIFOBASE_H_ #error Include FIFOBase.h before FIFOBase.tpp! #endif From aec557a8c06a233b3139134a8fa5db0befb4e757 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 28 Aug 2020 17:14:20 +0200 Subject: [PATCH 278/653] updated unix udp bridge --- globalfunctions/timevalOperations.cpp | 191 +++++++++++++------------- globalfunctions/timevalOperations.h | 1 + osal/linux/TcUnixUdpPollingTask.cpp | 4 +- osal/linux/TcUnixUdpPollingTask.h | 6 +- osal/linux/TmTcUnixUdpBridge.cpp | 8 +- osal/linux/TmTcUnixUdpBridge.h | 4 +- 6 files changed, 111 insertions(+), 103 deletions(-) diff --git a/globalfunctions/timevalOperations.cpp b/globalfunctions/timevalOperations.cpp index 6efe75ba..ae49ef21 100644 --- a/globalfunctions/timevalOperations.cpp +++ b/globalfunctions/timevalOperations.cpp @@ -1,92 +1,99 @@ -#include "timevalOperations.h" - -timeval& operator+=(timeval& lhs, const timeval& rhs) { - int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; - sum += rhs.tv_sec * 1000000. + rhs.tv_usec; - lhs.tv_sec = sum / 1000000; - lhs.tv_usec = sum - lhs.tv_sec * 1000000; - return lhs; -} - -timeval operator+(timeval lhs, const timeval& rhs) { - lhs += rhs; - return lhs; -} - -timeval& operator-=(timeval& lhs, const timeval& rhs) { - int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; - sum -= rhs.tv_sec * 1000000. + rhs.tv_usec; - lhs.tv_sec = sum / 1000000; - lhs.tv_usec = sum - lhs.tv_sec * 1000000; - return lhs; -} - -timeval operator-(timeval lhs, const timeval& rhs) { - lhs -= rhs; - return lhs; -} - -double operator/(const timeval& lhs, const timeval& rhs) { - double lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; - double rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; - return lhs64 / rhs64; -} - -timeval& operator/=(timeval& lhs, double scalar) { - int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec; - product /= scalar; - lhs.tv_sec = product / 1000000; - lhs.tv_usec = product - lhs.tv_sec * 1000000; - return lhs; -} - -timeval operator/(timeval lhs, double scalar) { - lhs /= scalar; - return lhs; -} - -timeval& operator*=(timeval& lhs, double scalar) { - int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec; - product *= scalar; - lhs.tv_sec = product / 1000000; - lhs.tv_usec = product - lhs.tv_sec * 1000000; - return lhs; -} - -timeval operator*(timeval lhs, double scalar) { - lhs *= scalar; - return lhs; -} - -timeval operator*(double scalar, timeval rhs) { - rhs *= scalar; - return rhs; -} - -bool operator==(const timeval& lhs, const timeval& rhs) { - int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; - int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; - return lhs64 == rhs64; -} -bool operator!=(const timeval& lhs, const timeval& rhs) { - return !operator==(lhs, rhs); -} -bool operator<(const timeval& lhs, const timeval& rhs) { - int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; - int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; - return lhs64 < rhs64; -} -bool operator>(const timeval& lhs, const timeval& rhs) { - return operator<(rhs, lhs); -} -bool operator<=(const timeval& lhs, const timeval& rhs) { - return !operator>(lhs, rhs); -} -bool operator>=(const timeval& lhs, const timeval& rhs) { - return !operator<(lhs, rhs); -} - -double timevalOperations::toDouble(const timeval timeval) { - double result = timeval.tv_sec * 1000000. + timeval.tv_usec; - return result / 1000000.; -} +#include "timevalOperations.h" + +timeval& operator+=(timeval& lhs, const timeval& rhs) { + int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; + sum += rhs.tv_sec * 1000000. + rhs.tv_usec; + lhs.tv_sec = sum / 1000000; + lhs.tv_usec = sum - lhs.tv_sec * 1000000; + return lhs; +} + +timeval operator+(timeval lhs, const timeval& rhs) { + lhs += rhs; + return lhs; +} + +timeval& operator-=(timeval& lhs, const timeval& rhs) { + int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; + sum -= rhs.tv_sec * 1000000. + rhs.tv_usec; + lhs.tv_sec = sum / 1000000; + lhs.tv_usec = sum - lhs.tv_sec * 1000000; + return lhs; +} + +timeval operator-(timeval lhs, const timeval& rhs) { + lhs -= rhs; + return lhs; +} + +double operator/(const timeval& lhs, const timeval& rhs) { + double lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; + double rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; + return lhs64 / rhs64; +} + +timeval& operator/=(timeval& lhs, double scalar) { + int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec; + product /= scalar; + lhs.tv_sec = product / 1000000; + lhs.tv_usec = product - lhs.tv_sec * 1000000; + return lhs; +} + +timeval operator/(timeval lhs, double scalar) { + lhs /= scalar; + return lhs; +} + +timeval& operator*=(timeval& lhs, double scalar) { + int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec; + product *= scalar; + lhs.tv_sec = product / 1000000; + lhs.tv_usec = product - lhs.tv_sec * 1000000; + return lhs; +} + +timeval operator*(timeval lhs, double scalar) { + lhs *= scalar; + return lhs; +} + +timeval operator*(double scalar, timeval rhs) { + rhs *= scalar; + return rhs; +} + +bool operator==(const timeval& lhs, const timeval& rhs) { + int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; + int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; + return lhs64 == rhs64; +} +bool operator!=(const timeval& lhs, const timeval& rhs) { + return !operator==(lhs, rhs); +} +bool operator<(const timeval& lhs, const timeval& rhs) { + int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; + int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; + return lhs64 < rhs64; +} +bool operator>(const timeval& lhs, const timeval& rhs) { + return operator<(rhs, lhs); +} +bool operator<=(const timeval& lhs, const timeval& rhs) { + return !operator>(lhs, rhs); +} +bool operator>=(const timeval& lhs, const timeval& rhs) { + return !operator<(lhs, rhs); +} + +double timevalOperations::toDouble(const timeval timeval) { + double result = timeval.tv_sec * 1000000. + timeval.tv_usec; + return result / 1000000.; +} + +timeval timevalOperations::toTimeval(const double seconds) { + timeval tval; + tval.tv_sec = seconds; + tval.tv_usec = seconds *(double) 1e6 - (tval.tv_sec *1e6); + return tval; +} diff --git a/globalfunctions/timevalOperations.h b/globalfunctions/timevalOperations.h index a553e60a..3977d5d9 100644 --- a/globalfunctions/timevalOperations.h +++ b/globalfunctions/timevalOperations.h @@ -41,6 +41,7 @@ namespace timevalOperations { * @return seconds */ double toDouble(const timeval timeval); +timeval toTimeval(const double seconds); } #endif /* TIMEVALOPERATIONS_H_ */ diff --git a/osal/linux/TcUnixUdpPollingTask.cpp b/osal/linux/TcUnixUdpPollingTask.cpp index 8cf7b285..95910b02 100644 --- a/osal/linux/TcUnixUdpPollingTask.cpp +++ b/osal/linux/TcUnixUdpPollingTask.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "TcUnixUdpPollingTask.h" +#include "../../globalfunctions/arrayprinter.h" TcUnixUdpPollingTask::TcUnixUdpPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge, size_t frameSize, diff --git a/osal/linux/TcUnixUdpPollingTask.h b/osal/linux/TcUnixUdpPollingTask.h index d8de1458..cc032561 100644 --- a/osal/linux/TcUnixUdpPollingTask.h +++ b/osal/linux/TcUnixUdpPollingTask.h @@ -1,9 +1,9 @@ #ifndef FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ #define FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ -#include -#include -#include +#include "../../objectmanager/SystemObject.h" +#include "../../osal/linux/TmTcUnixUdpBridge.h" +#include "../../tasks/ExecutableObjectIF.h" #include #include diff --git a/osal/linux/TmTcUnixUdpBridge.cpp b/osal/linux/TmTcUnixUdpBridge.cpp index 92fbbdfa..46b26254 100644 --- a/osal/linux/TmTcUnixUdpBridge.cpp +++ b/osal/linux/TmTcUnixUdpBridge.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "TmTcUnixUdpBridge.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../ipc/MutexHelper.h" #include #include @@ -85,7 +85,7 @@ ReturnValue_t TmTcUnixUdpBridge::sendTm(const uint8_t *data, size_t dataLen) { } void TmTcUnixUdpBridge::checkAndSetClientAddress(sockaddr_in newAddress) { - MutexHelper lock(mutex, 10); + MutexHelper lock(mutex, MutexIF::TimeoutType::WAITING, 10); // char ipAddress [15]; // sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET, diff --git a/osal/linux/TmTcUnixUdpBridge.h b/osal/linux/TmTcUnixUdpBridge.h index dbddc6c3..5245c44c 100644 --- a/osal/linux/TmTcUnixUdpBridge.h +++ b/osal/linux/TmTcUnixUdpBridge.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ #define FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ -#include -#include +#include "../../tmtcservices/AcceptsTelecommandsIF.h" +#include "../../tmtcservices/TmTcBridge.h" #include #include #include From b54d63edcb6077572f7cd61f0b94c96990460b07 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 28 Aug 2020 18:10:02 +0200 Subject: [PATCH 279/653] event manager improvements --- events/EventManager.cpp | 59 +++++++++++++++++++++++------------------ events/EventManager.h | 10 +++++-- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/events/EventManager.cpp b/events/EventManager.cpp index e58f251a..e71951e3 100644 --- a/events/EventManager.cpp +++ b/events/EventManager.cpp @@ -8,13 +8,16 @@ const uint16_t EventManager::POOL_SIZES[N_POOLS] = { sizeof(EventMatchTree::Node), sizeof(EventIdRangeMatcher), sizeof(ReporterRangeMatcher) }; -//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. +// 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. +// SHOULDDO: Shouldn't this be in the config folder and passed via ctor? const uint16_t EventManager::N_ELEMENTS[N_POOLS] = { 240, 120, 120 }; EventManager::EventManager(object_id_t setObjectId) : - SystemObject(setObjectId), eventReportQueue(NULL), mutex(NULL), factoryBackend( - 0, POOL_SIZES, N_ELEMENTS, false, true) { + SystemObject(setObjectId), + factoryBackend(0, POOL_SIZES, N_ELEMENTS, false, true) { mutex = MutexFactory::instance()->createMutex(); eventReportQueue = QueueFactory::instance()->createMessageQueue( MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE); @@ -108,41 +111,45 @@ ReturnValue_t EventManager::unsubscribeFromEventRange(MessageQueueId_t listener, #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()); -// sif::info << "EVENT: "; -// if (string != 0) { -// sif::info << string; -// } else { -// sif::info << "0x" << std::hex << message->getReporter() << std::dec; -// } -// sif::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: +#ifdef DEBUG_INFO_EVENT string = translateObject(message->getReporter()); - sif::error << "EVENT: "; + sif::info << "EVENT: "; if (string != 0) { - sif::error << string; + sif::info << string; } else { - sif::error << "0x" << std::hex << message->getReporter() << std::dec; + sif::info << "0x" << std::hex << message->getReporter() << std::dec; } - sif::error << " reported " << translateEvents(message->getEvent()) << " (" + sif::info << " reported " << translateEvents(message->getEvent()) << " (" << std::dec << message->getEventId() << std::hex << ") P1: 0x" << message->getParameter1() << " P2: 0x" << message->getParameter2() << std::dec << std::endl; +#endif + break; + default: + string = translateObject(message->getReporter()); + sif::debug << "EventManager: "; + if (string != 0) { + sif::debug << string; + } + else { + sif::debug << "0x" << std::hex << message->getReporter() << std::dec; + } + sif::debug << " reported " << translateEvents(message->getEvent()) + << " (" << std::dec << message->getEventId() << ") " + << std::endl; + + sif::debug << std::hex << "P1 Hex: 0x" << message->getParameter1() + << ", P1 Dec: " << std::dec << message->getParameter1() + << std::endl; + sif::debug << std::hex << "P2 Hex: 0x" << message->getParameter2() + << ", P2 Dec: " << std::dec << message->getParameter2() + << std::endl; break; } - } #endif diff --git a/events/EventManager.h b/events/EventManager.h index 7badc3bf..2602aeb2 100644 --- a/events/EventManager.h +++ b/events/EventManager.h @@ -10,6 +10,12 @@ #include "../ipc/MutexIF.h" #include +#ifdef DEBUG +// forward declaration, should be implemented by mission +extern const char* translateObject(object_id_t object); +extern const char* translateEvents(Event event); +#endif + class EventManager: public EventManagerIF, public ExecutableObjectIF, public SystemObject { @@ -36,11 +42,11 @@ public: ReturnValue_t performOperation(uint8_t opCode); protected: - MessageQueueIF* eventReportQueue; + MessageQueueIF* eventReportQueue = nullptr; std::map listenerList; - MutexIF* mutex; + MutexIF* mutex = nullptr; static const uint8_t N_POOLS = 3; LocalPool factoryBackend; From 7a5c70e75366399082ac9d40a6f95c1c7245cf95 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 28 Aug 2020 18:46:47 +0200 Subject: [PATCH 280/653] typo fixes --- parameters/HasParametersIF.h | 27 +++++-- parameters/ParameterHelper.cpp | 16 ++-- parameters/ParameterHelper.h | 23 ++++-- parameters/ParameterMessage.cpp | 2 +- parameters/ParameterMessage.h | 8 +- parameters/ParameterWrapper.cpp | 31 ++++---- parameters/ParameterWrapper.h | 95 +++++++++++++++--------- parameters/ReceivesParameterMessagesIF.h | 6 +- 8 files changed, 126 insertions(+), 82 deletions(-) diff --git a/parameters/HasParametersIF.h b/parameters/HasParametersIF.h index 71212b57..005403fa 100644 --- a/parameters/HasParametersIF.h +++ b/parameters/HasParametersIF.h @@ -1,12 +1,27 @@ -#ifndef HASPARAMETERSIF_H_ -#define HASPARAMETERSIF_H_ +#ifndef FSFW_PARAMETERS_HASPARAMETERSIF_H_ +#define FSFW_PARAMETERS_HASPARAMETERSIF_H_ -#include "ParameterWrapper.h" +#include "../parameters/ParameterWrapper.h" #include "../returnvalues/HasReturnvaluesIF.h" #include +/** Each parameter is identified with a unique parameter ID */ typedef uint32_t ParameterId_t; +/** + * @brief This interface is used by components which have modifiable + * parameters, e.g. atittude controllers + * @details + * Each parameter has a unique parameter ID. The first byte of the parameter + * ID is the domain ID which can be used to identify unqiue spacecraft domains + * (e.g. control and sensor domain in the AOCS controller). + * + * The second and third byte represent the matrix ID, which can represent + * a 8-bit row and column number and the last byte... + * + * Yeah, it it matrix ID oder parameter ID now and is index a 16 bit number + * of a 8 bit number now? + */ class HasParametersIF { public: static const uint8_t INTERFACE_ID = CLASS_ID::HAS_PARAMETERS_IF; @@ -32,13 +47,11 @@ public: return (domainId << 24) + (parameterId << 8) + index; } - virtual ~HasParametersIF() { - } + virtual ~HasParametersIF() {} /** * Always set parameter before checking newValues! * - * * @param domainId * @param parameterId * @param parameterWrapper @@ -51,4 +64,4 @@ public: const ParameterWrapper *newValues, uint16_t startAtIndex) = 0; }; -#endif /* HASPARAMETERSIF_H_ */ +#endif /* FSFW_PARAMETERS_HASPARAMETERSIF_H_ */ diff --git a/parameters/ParameterHelper.cpp b/parameters/ParameterHelper.cpp index 8543515f..659b00de 100644 --- a/parameters/ParameterHelper.cpp +++ b/parameters/ParameterHelper.cpp @@ -1,11 +1,9 @@ -#include "../objectmanager/ObjectManagerIF.h" #include "ParameterHelper.h" #include "ParameterMessage.h" +#include "../objectmanager/ObjectManagerIF.h" ParameterHelper::ParameterHelper(ReceivesParameterMessagesIF* owner) : - owner(owner), storage(NULL) { - -} + owner(owner) {} ParameterHelper::~ParameterHelper() { } @@ -28,7 +26,6 @@ ReturnValue_t ParameterHelper::handleParameterMessage(CommandMessage *message) { } break; case ParameterMessage::CMD_PARAMETER_LOAD: { - uint8_t domain = HasParametersIF::getDomain( ParameterMessage::getParameterId(message)); uint16_t parameterId = HasParametersIF::getMatrixId( @@ -36,12 +33,14 @@ ReturnValue_t ParameterHelper::handleParameterMessage(CommandMessage *message) { uint8_t index = HasParametersIF::getIndex( ParameterMessage::getParameterId(message)); - const uint8_t *storedStream; - size_t storedStreamSize; + const uint8_t *storedStream = nullptr; + size_t storedStreamSize = 0; result = storage->getData( ParameterMessage::getStoreId(message), &storedStream, &storedStreamSize); if (result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "ParameterHelper::handleParameterMessage: Getting" + " store data failed for load command." << std::endl; break; } @@ -125,7 +124,8 @@ ReturnValue_t ParameterHelper::initialize() { } } -void ParameterHelper::rejectCommand(MessageQueueId_t to, ReturnValue_t reason, Command_t initialCommand) { +void ParameterHelper::rejectCommand(MessageQueueId_t to, ReturnValue_t reason, + Command_t initialCommand) { CommandMessage reply; reply.setReplyRejected(reason, initialCommand); MessageQueueSenderIF::sendMessage(to, &reply, ownerQueueId); diff --git a/parameters/ParameterHelper.h b/parameters/ParameterHelper.h index d887bf1d..595b4bc5 100644 --- a/parameters/ParameterHelper.h +++ b/parameters/ParameterHelper.h @@ -1,9 +1,16 @@ -#ifndef PARAMETERHELPER_H_ -#define PARAMETERHELPER_H_ +#ifndef FSFW_PARAMETERS_PARAMETERHELPER_H_ +#define FSFW_PARAMETERS_PARAMETERHELPER_H_ #include "ParameterMessage.h" #include "ReceivesParameterMessagesIF.h" +#include "../ipc/MessageQueueIF.h" +/** + * @brief Helper class to handle parameter messages. + * @details + * This class simplfies handling of parameter messages, which are sent + * to a class which implements ReceivesParameterMessagesIF. + */ class ParameterHelper { public: ParameterHelper(ReceivesParameterMessagesIF *owner); @@ -15,13 +22,15 @@ public: private: ReceivesParameterMessagesIF *owner; - MessageQueueId_t ownerQueueId; + MessageQueueId_t ownerQueueId = MessageQueueIF::NO_QUEUE; - StorageManagerIF *storage; + StorageManagerIF *storage = nullptr; - ReturnValue_t sendParameter(MessageQueueId_t to, uint32_t id, const ParameterWrapper *description); + ReturnValue_t sendParameter(MessageQueueId_t to, uint32_t id, + const ParameterWrapper *description); - void rejectCommand(MessageQueueId_t to, ReturnValue_t reason, Command_t initialCommand); + void rejectCommand(MessageQueueId_t to, ReturnValue_t reason, + Command_t initialCommand); }; -#endif /* PARAMETERHELPER_H_ */ +#endif /* FSFW_PARAMETERS_PARAMETERHELPER_H_ */ diff --git a/parameters/ParameterMessage.cpp b/parameters/ParameterMessage.cpp index 7e0ed114..e9f3191f 100644 --- a/parameters/ParameterMessage.cpp +++ b/parameters/ParameterMessage.cpp @@ -1,4 +1,4 @@ -#include "ParameterMessage.h" +#include "../parameters/ParameterMessage.h" #include "../objectmanager/ObjectManagerIF.h" ParameterId_t ParameterMessage::getParameterId(const CommandMessage* message) { diff --git a/parameters/ParameterMessage.h b/parameters/ParameterMessage.h index f59af513..31d7fe0b 100644 --- a/parameters/ParameterMessage.h +++ b/parameters/ParameterMessage.h @@ -1,8 +1,8 @@ -#ifndef PARAMETERMESSAGE_H_ -#define PARAMETERMESSAGE_H_ +#ifndef FSFW_PARAMETERS_PARAMETERMESSAGE_H_ +#define FSFW_PARAMETERS_PARAMETERMESSAGE_H_ -#include "../ipc/CommandMessage.h" #include "HasParametersIF.h" +#include "../ipc/CommandMessage.h" #include "../storagemanager/StorageManagerIF.h" class ParameterMessage { @@ -26,4 +26,4 @@ public: }; -#endif /* PARAMETERMESSAGE_H_ */ +#endif /* FSFW_PARAMETERS_PARAMETERMESSAGE_H_ */ diff --git a/parameters/ParameterWrapper.cpp b/parameters/ParameterWrapper.cpp index 56f56426..d020da33 100644 --- a/parameters/ParameterWrapper.cpp +++ b/parameters/ParameterWrapper.cpp @@ -1,20 +1,19 @@ #include "ParameterWrapper.h" ParameterWrapper::ParameterWrapper() : - pointsToStream(false), type(Type::UNKNOWN_TYPE), rows(0), columns(0), data( - NULL), readonlyData(NULL) { + pointsToStream(false), type(Type::UNKNOWN_TYPE) { } ParameterWrapper::ParameterWrapper(Type type, uint8_t rows, uint8_t columns, void *data) : - pointsToStream(false), type(type), rows(rows), columns(columns), data( - data), readonlyData(data) { + pointsToStream(false), type(type), rows(rows), columns(columns), + data(data), readonlyData(data) { } ParameterWrapper::ParameterWrapper(Type type, uint8_t rows, uint8_t columns, const void *data) : - pointsToStream(false), type(type), rows(rows), columns(columns), data( - NULL), readonlyData(data) { + pointsToStream(false), type(type), rows(rows), columns(columns), + data(nullptr), readonlyData(data) { } ParameterWrapper::~ParameterWrapper() { @@ -141,6 +140,7 @@ ReturnValue_t ParameterWrapper::deSerializeData(uint8_t startingRow, } + ReturnValue_t ParameterWrapper::deSerialize(const uint8_t **buffer, size_t *size, Endianness streamEndianness) { return deSerialize(buffer, size, streamEndianness, 0); @@ -184,16 +184,16 @@ ReturnValue_t ParameterWrapper::set(const uint8_t *stream, size_t streamSize, return SerializeIF::STREAM_TOO_SHORT; } - data = NULL; + data = nullptr; readonlyData = stream; pointsToStream = true; stream += dataSize; - if (remainingStream != NULL) { + if (remainingStream != nullptr) { *remainingStream = stream; } streamSize -= dataSize; - if (remainingSize != NULL) { + if (remainingSize != nullptr) { *remainingSize = streamSize; } @@ -265,15 +265,14 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from, result = UNKNOW_DATATYPE; break; } - } else { + } + else { //need a type to do arithmetic - uint8_t *toDataWithType = (uint8_t*) data; + uint8_t* typedData = static_cast(data); for (uint8_t fromRow = 0; fromRow < from->rows; fromRow++) { - memcpy( - toDataWithType - + (((startingRow + fromRow) * columns) - + startingColumn) * typeSize, - from->readonlyData, typeSize * from->columns); + uint8_t offset = (((startingRow + fromRow) * columns) + startingColumn) * typeSize; + std::memcpy(typedData + offset, from->readonlyData, + typeSize * from->columns); } } diff --git a/parameters/ParameterWrapper.h b/parameters/ParameterWrapper.h index b18fe2b9..f07205d4 100644 --- a/parameters/ParameterWrapper.h +++ b/parameters/ParameterWrapper.h @@ -1,12 +1,16 @@ -#ifndef PARAMETERWRAPPER_H_ -#define PARAMETERWRAPPER_H_ +#ifndef FSFW_PARAMETERS_PARAMETERWRAPPER_H_ +#define FSFW_PARAMETERS_PARAMETERWRAPPER_H_ #include "../returnvalues/HasReturnvaluesIF.h" #include "../serialize/SerializeAdapter.h" #include "../serialize/SerializeIF.h" -#include #include "../globalfunctions/Type.h" +#include +/** + * @brief + * @details + */ class ParameterWrapper: public SerializeIF { friend class DataPoolParameterWrapper; public: @@ -36,32 +40,21 @@ public: virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness, uint16_t startWritingAtIndex = 0); + /** + * Get a specific parameter value by supplying the row and the column. + * @tparam T Type of target data + * @param value [out] Pointer to storage location + * @param row + * @param column + * @return + * -@c RETURN_OK if element was retrieved successfully + * -@c NOT_SET data has not been set yet + * -@c DATATYPE_MISSMATCH Invalid supplied type + * -@c OUT_OF_BOUNDS Invalid row and/or column. + */ template - ReturnValue_t getElement(T *value, uint8_t row = 0, uint8_t column = 0) const { - if (readonlyData == NULL){ - return NOT_SET; - } - - if (PodTypeConversion::type != type) { - return DATATYPE_MISSMATCH; - } - - if ((row >= rows) || (column >= columns)) { - return OUT_OF_BOUNDS; - } - - if (pointsToStream) { - const uint8_t *streamWithtype = (const uint8_t *) readonlyData; - streamWithtype += (row * columns + column) * type.getSize(); - int32_t size = type.getSize(); - return SerializeAdapter::deSerialize(value, &streamWithtype, - &size, true); - } else { - const T *dataWithType = (const T *) readonlyData; - *value = dataWithType[row * columns + column]; - return HasReturnvaluesIF::RETURN_OK; - } - } + ReturnValue_t getElement(T *value, uint8_t row = 0, + uint8_t column = 0) const; template void set(T *data, uint8_t rows, uint8_t columns) { @@ -111,21 +104,22 @@ public: void setMatrix(const T& member) { this->set(member[0], sizeof(member)/sizeof(member[0]), sizeof(member[0])/sizeof(member[0][0])); } + ReturnValue_t set(const uint8_t *stream, size_t streamSize, - const uint8_t **remainingStream = NULL, size_t *remainingSize = - NULL); + const uint8_t **remainingStream = nullptr, + size_t *remainingSize = nullptr); ReturnValue_t copyFrom(const ParameterWrapper *from, uint16_t startWritingAtIndex); private: - bool pointsToStream; + bool pointsToStream = false; Type type; - uint8_t rows; - uint8_t columns; - void *data; - const void *readonlyData; + uint8_t rows = 0; + uint8_t columns = 0; + void *data = nullptr; + const void *readonlyData = nullptr; template ReturnValue_t serializeData(uint8_t** buffer, size_t* size, @@ -136,4 +130,33 @@ private: const void *from, uint8_t fromRows, uint8_t fromColumns); }; -#endif /* PARAMETERWRAPPER_H_ */ +template +inline ReturnValue_t ParameterWrapper::getElement(T *value, uint8_t row, + uint8_t column) const { + if (readonlyData == nullptr){ + return NOT_SET; + } + + if (PodTypeConversion::type != type) { + return DATATYPE_MISSMATCH; + } + + if ((row >= rows) or (column >= columns)) { + return OUT_OF_BOUNDS; + } + + if (pointsToStream) { + const uint8_t *streamWithType = static_cast(readonlyData); + streamWithType += (row * columns + column) * type.getSize(); + int32_t size = type.getSize(); + return SerializeAdapter::deSerialize(value, &streamWithType, + &size, true); + } + else { + const T *dataWithType = static_cast(readonlyData); + *value = dataWithType[row * columns + column]; + return HasReturnvaluesIF::RETURN_OK; + } +} + +#endif /* FSFW_PARAMETERS_PARAMETERWRAPPER_H_ */ diff --git a/parameters/ReceivesParameterMessagesIF.h b/parameters/ReceivesParameterMessagesIF.h index 1fcbd4b3..e8c7fa69 100644 --- a/parameters/ReceivesParameterMessagesIF.h +++ b/parameters/ReceivesParameterMessagesIF.h @@ -1,5 +1,5 @@ -#ifndef RECEIVESPARAMETERMESSAGESIF_H_ -#define RECEIVESPARAMETERMESSAGESIF_H_ +#ifndef FSFW_PARAMETERS_RECEIVESPARAMETERMESSAGESIF_H_ +#define FSFW_PARAMETERS_RECEIVESPARAMETERMESSAGESIF_H_ #include "HasParametersIF.h" @@ -16,4 +16,4 @@ public: }; -#endif /* RECEIVESPARAMETERMESSAGESIF_H_ */ +#endif /* FSFW_PARAMETERS_RECEIVESPARAMETERMESSAGESIF_H_ */ From c0ed474373aef91fc12e2dc9b26bc9b8f4b8a4e4 Mon Sep 17 00:00:00 2001 From: gaisser Date: Tue, 1 Sep 2020 11:34:28 +0200 Subject: [PATCH 281/653] Update 'serialize/SerializeIF.h' --- serialize/SerializeIF.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/serialize/SerializeIF.h b/serialize/SerializeIF.h index 2bb17154..7f9ea9df 100644 --- a/serialize/SerializeIF.h +++ b/serialize/SerializeIF.h @@ -5,13 +5,13 @@ #include /** - * \defgroup serialize Serialization + * @defgroup serialize Serialization * Contains serialization services. */ /** * Translation of objects into data streams and from data streams. - * \ingroup serialize + * @ingroup serialize */ class SerializeIF { public: @@ -51,7 +51,7 @@ public: size_t maxSize, Endianness streamEndianness) const = 0; /** - * Gets the size of a object if it would be serialized in a buffer.s + * Gets the size of a object if it would be serialized in a buffer * @return Size of serialized object */ virtual size_t getSerializedSize() const = 0; From a4d9c761a78831a963c06c5969410daedd48e4dd Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 1 Sep 2020 11:49:43 +0200 Subject: [PATCH 282/653] renormalize CHB --- contrib/sgp4/sgp4unit.cpp | 4180 +++++++++++++-------------- contrib/sgp4/sgp4unit.h | 234 +- devicehandlers/ChildHandlerBase.cpp | 90 +- devicehandlers/ChildHandlerBase.h | 48 +- osal/FreeRTOS/TaskManagement.cpp | 48 +- osal/FreeRTOS/TaskManagement.h | 128 +- serialize/SerialBufferAdapter.cpp | 258 +- serialize/SerialBufferAdapter.h | 156 +- 8 files changed, 2571 insertions(+), 2571 deletions(-) diff --git a/contrib/sgp4/sgp4unit.cpp b/contrib/sgp4/sgp4unit.cpp index 24d63aa9..b707a7a2 100644 --- a/contrib/sgp4/sgp4unit.cpp +++ b/contrib/sgp4/sgp4unit.cpp @@ -1,2090 +1,2090 @@ -/* ---------------------------------------------------------------- -* -* sgp4unit.cpp -* -* this file contains the sgp4 procedures for analytical propagation -* of a satellite. the code was originally released in the 1980 and 1986 -* spacetrack papers. a detailed discussion of the theory and history -* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, -* and kelso. -* -* companion code for -* fundamentals of astrodynamics and applications -* 2007 -* by david vallado -* -* (w) 719-573-2600, email dvallado@agi.com -* -* current : -* 16 nov 07 david vallado -* misc fixes for better compliance -* changes : -* 20 apr 07 david vallado -* misc fixes for constants -* 11 aug 06 david vallado -* chg lyddane choice back to strn3, constants, misc doc -* 15 dec 05 david vallado -* misc fixes -* 26 jul 05 david vallado -* fixes for paper -* note that each fix is preceded by a -* comment with "sgp4fix" and an explanation of -* what was changed -* 10 aug 04 david vallado -* 2nd printing baseline working -* 14 may 01 david vallado -* 2nd edition baseline -* 80 norad -* original baseline -* ---------------------------------------------------------------- */ - -#include "sgp4unit.h" - -const char help = 'n'; -FILE *dbgfile; - -#define pi 3.14159265358979323846 - - -/* ----------- local functions - only ever used internally by sgp4 ---------- */ -static void dpper - ( - double e3, double ee2, double peo, double pgho, double pho, - double pinco, double plo, double se2, double se3, double sgh2, - double sgh3, double sgh4, double sh2, double sh3, double si2, - double si3, double sl2, double sl3, double sl4, double t, - double xgh2, double xgh3, double xgh4, double xh2, double xh3, - double xi2, double xi3, double xl2, double xl3, double xl4, - double zmol, double zmos, double inclo, - char init, - double& ep, double& inclp, double& nodep, double& argpp, double& mp - ); - -static void dscom - ( - double epoch, double ep, double argpp, double tc, double inclp, - double nodep, double np, - double& snodm, double& cnodm, double& sinim, double& cosim, double& sinomm, - double& cosomm,double& day, double& e3, double& ee2, double& em, - double& emsq, double& gam, double& peo, double& pgho, double& pho, - double& pinco, double& plo, double& rtemsq, double& se2, double& se3, - double& sgh2, double& sgh3, double& sgh4, double& sh2, double& sh3, - double& si2, double& si3, double& sl2, double& sl3, double& sl4, - double& s1, double& s2, double& s3, double& s4, double& s5, - double& s6, double& s7, double& ss1, double& ss2, double& ss3, - double& ss4, double& ss5, double& ss6, double& ss7, double& sz1, - double& sz2, double& sz3, double& sz11, double& sz12, double& sz13, - double& sz21, double& sz22, double& sz23, double& sz31, double& sz32, - double& sz33, double& xgh2, double& xgh3, double& xgh4, double& xh2, - double& xh3, double& xi2, double& xi3, double& xl2, double& xl3, - double& xl4, double& nm, double& z1, double& z2, double& z3, - double& z11, double& z12, double& z13, double& z21, double& z22, - double& z23, double& z31, double& z32, double& z33, double& zmol, - double& zmos - ); - -static void dsinit - ( - gravconsttype whichconst, - double cosim, double emsq, double argpo, double s1, double s2, - double s3, double s4, double s5, double sinim, double ss1, - double ss2, double ss3, double ss4, double ss5, double sz1, - double sz3, double sz11, double sz13, double sz21, double sz23, - double sz31, double sz33, double t, double tc, double gsto, - double mo, double mdot, double no, double nodeo, double nodedot, - double xpidot, double z1, double z3, double z11, double z13, - double z21, double z23, double z31, double z33, double ecco, - double eccsq, double& em, double& argpm, double& inclm, double& mm, - double& nm, double& nodem, - int& irez, - double& atime, double& d2201, double& d2211, double& d3210, double& d3222, - double& d4410, double& d4422, double& d5220, double& d5232, double& d5421, - double& d5433, double& dedt, double& didt, double& dmdt, double& dndt, - double& dnodt, double& domdt, double& del1, double& del2, double& del3, - double& xfact, double& xlamo, double& xli, double& xni - ); - -static void dspace - ( - int irez, - double d2201, double d2211, double d3210, double d3222, double d4410, - double d4422, double d5220, double d5232, double d5421, double d5433, - double dedt, double del1, double del2, double del3, double didt, - double dmdt, double dnodt, double domdt, double argpo, double argpdot, - double t, double tc, double gsto, double xfact, double xlamo, - double no, - double& atime, double& em, double& argpm, double& inclm, double& xli, - double& mm, double& xni, double& nodem, double& dndt, double& nm - ); - -static void initl - ( - int satn, gravconsttype whichconst, - double ecco, double epoch, double inclo, double& no, - char& method, - double& ainv, double& ao, double& con41, double& con42, double& cosio, - double& cosio2,double& eccsq, double& omeosq, double& posq, - double& rp, double& rteosq,double& sinio , double& gsto - ); - -/* ----------------------------------------------------------------------------- -* -* procedure dpper -* -* this procedure provides deep space long period periodic contributions -* to the mean elements. by design, these periodics are zero at epoch. -* this used to be dscom which included initialization, but it's really a -* recurring function. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* e3 - -* ee2 - -* peo - -* pgho - -* pho - -* pinco - -* plo - -* se2 , se3 , sgh2, sgh3, sgh4, sh2, sh3, si2, si3, sl2, sl3, sl4 - -* t - -* xh2, xh3, xi2, xi3, xl2, xl3, xl4 - -* zmol - -* zmos - -* ep - eccentricity 0.0 - 1.0 -* inclo - inclination - needed for lyddane modification -* nodep - right ascension of ascending node -* argpp - argument of perigee -* mp - mean anomaly -* -* outputs : -* ep - eccentricity 0.0 - 1.0 -* inclp - inclination -* nodep - right ascension of ascending node -* argpp - argument of perigee -* mp - mean anomaly -* -* locals : -* alfdp - -* betdp - -* cosip , sinip , cosop , sinop , -* dalf - -* dbet - -* dls - -* f2, f3 - -* pe - -* pgh - -* ph - -* pinc - -* pl - -* sel , ses , sghl , sghs , shl , shs , sil , sinzf , sis , -* sll , sls -* xls - -* xnoh - -* zf - -* zm - -* -* coupling : -* none. -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void dpper - ( - double e3, double ee2, double peo, double pgho, double pho, - double pinco, double plo, double se2, double se3, double sgh2, - double sgh3, double sgh4, double sh2, double sh3, double si2, - double si3, double sl2, double sl3, double sl4, double t, - double xgh2, double xgh3, double xgh4, double xh2, double xh3, - double xi2, double xi3, double xl2, double xl3, double xl4, - double zmol, double zmos, double inclo, - char init, - double& ep, double& inclp, double& nodep, double& argpp, double& mp - ) -{ - /* --------------------- local variables ------------------------ */ - const double twopi = 2.0 * pi; - double alfdp, betdp, cosip, cosop, dalf, dbet, dls, - f2, f3, pe, pgh, ph, pinc, pl , - sel, ses, sghl, sghs, shll, shs, sil, - sinip, sinop, sinzf, sis, sll, sls, xls, - xnoh, zf, zm, zel, zes, znl, zns; - - /* ---------------------- constants ----------------------------- */ - zns = 1.19459e-5; - zes = 0.01675; - znl = 1.5835218e-4; - zel = 0.05490; - - /* --------------- calculate time varying periodics ----------- */ - zm = zmos + zns * t; - // be sure that the initial call has time set to zero - if (init == 'y') - zm = zmos; - zf = zm + 2.0 * zes * sin(zm); - sinzf = sin(zf); - f2 = 0.5 * sinzf * sinzf - 0.25; - f3 = -0.5 * sinzf * cos(zf); - ses = se2* f2 + se3 * f3; - sis = si2 * f2 + si3 * f3; - sls = sl2 * f2 + sl3 * f3 + sl4 * sinzf; - sghs = sgh2 * f2 + sgh3 * f3 + sgh4 * sinzf; - shs = sh2 * f2 + sh3 * f3; - zm = zmol + znl * t; - if (init == 'y') - zm = zmol; - zf = zm + 2.0 * zel * sin(zm); - sinzf = sin(zf); - f2 = 0.5 * sinzf * sinzf - 0.25; - f3 = -0.5 * sinzf * cos(zf); - sel = ee2 * f2 + e3 * f3; - sil = xi2 * f2 + xi3 * f3; - sll = xl2 * f2 + xl3 * f3 + xl4 * sinzf; - sghl = xgh2 * f2 + xgh3 * f3 + xgh4 * sinzf; - shll = xh2 * f2 + xh3 * f3; - pe = ses + sel; - pinc = sis + sil; - pl = sls + sll; - pgh = sghs + sghl; - ph = shs + shll; - - if (init == 'n') - { - pe = pe - peo; - pinc = pinc - pinco; - pl = pl - plo; - pgh = pgh - pgho; - ph = ph - pho; - inclp = inclp + pinc; - ep = ep + pe; - sinip = sin(inclp); - cosip = cos(inclp); - - /* ----------------- apply periodics directly ------------ */ - // sgp4fix for lyddane choice - // strn3 used original inclination - this is technically feasible - // gsfc used perturbed inclination - also technically feasible - // probably best to readjust the 0.2 limit value and limit discontinuity - // 0.2 rad = 11.45916 deg - // use next line for original strn3 approach and original inclination - // if (inclo >= 0.2) - // use next line for gsfc version and perturbed inclination - if (inclp >= 0.2) - { - ph = ph / sinip; - pgh = pgh - cosip * ph; - argpp = argpp + pgh; - nodep = nodep + ph; - mp = mp + pl; - } - else - { - /* ---- apply periodics with lyddane modification ---- */ - sinop = sin(nodep); - cosop = cos(nodep); - alfdp = sinip * sinop; - betdp = sinip * cosop; - dalf = ph * cosop + pinc * cosip * sinop; - dbet = -ph * sinop + pinc * cosip * cosop; - alfdp = alfdp + dalf; - betdp = betdp + dbet; - nodep = fmod(nodep, twopi); - // sgp4fix for afspc written intrinsic functions - // nodep used without a trigonometric function ahead - if (nodep < 0.0) - nodep = nodep + twopi; - xls = mp + argpp + cosip * nodep; - dls = pl + pgh - pinc * nodep * sinip; - xls = xls + dls; - xnoh = nodep; - nodep = atan2(alfdp, betdp); - // sgp4fix for afspc written intrinsic functions - // nodep used without a trigonometric function ahead - if (nodep < 0.0) - nodep = nodep + twopi; - if (fabs(xnoh - nodep) > pi){ - if (nodep < xnoh) - nodep = nodep + twopi; - else - nodep = nodep - twopi; - } - mp = mp + pl; - argpp = xls - mp - cosip * nodep; - } - } // if init == 'n' - -//#include "debug1.cpp" -} // end dpper - -/*----------------------------------------------------------------------------- -* -* procedure dscom -* -* this procedure provides deep space common items used by both the secular -* and periodics subroutines. input is provided as shown. this routine -* used to be called dpper, but the functions inside weren't well organized. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* epoch - -* ep - eccentricity -* argpp - argument of perigee -* tc - -* inclp - inclination -* nodep - right ascension of ascending node -* np - mean motion -* -* outputs : -* sinim , cosim , sinomm , cosomm , snodm , cnodm -* day - -* e3 - -* ee2 - -* em - eccentricity -* emsq - eccentricity squared -* gam - -* peo - -* pgho - -* pho - -* pinco - -* plo - -* rtemsq - -* se2, se3 - -* sgh2, sgh3, sgh4 - -* sh2, sh3, si2, si3, sl2, sl3, sl4 - -* s1, s2, s3, s4, s5, s6, s7 - -* ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3 - -* sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33 - -* xgh2, xgh3, xgh4, xh2, xh3, xi2, xi3, xl2, xl3, xl4 - -* nm - mean motion -* z1, z2, z3, z11, z12, z13, z21, z22, z23, z31, z32, z33 - -* zmol - -* zmos - -* -* locals : -* a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 - -* betasq - -* cc - -* ctem, stem - -* x1, x2, x3, x4, x5, x6, x7, x8 - -* xnodce - -* xnoi - -* zcosg , zsing , zcosgl , zsingl , zcosh , zsinh , zcoshl , zsinhl , -* zcosi , zsini , zcosil , zsinil , -* zx - -* zy - -* -* coupling : -* none. -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void dscom - ( - double epoch, double ep, double argpp, double tc, double inclp, - double nodep, double np, - double& snodm, double& cnodm, double& sinim, double& cosim, double& sinomm, - double& cosomm,double& day, double& e3, double& ee2, double& em, - double& emsq, double& gam, double& peo, double& pgho, double& pho, - double& pinco, double& plo, double& rtemsq, double& se2, double& se3, - double& sgh2, double& sgh3, double& sgh4, double& sh2, double& sh3, - double& si2, double& si3, double& sl2, double& sl3, double& sl4, - double& s1, double& s2, double& s3, double& s4, double& s5, - double& s6, double& s7, double& ss1, double& ss2, double& ss3, - double& ss4, double& ss5, double& ss6, double& ss7, double& sz1, - double& sz2, double& sz3, double& sz11, double& sz12, double& sz13, - double& sz21, double& sz22, double& sz23, double& sz31, double& sz32, - double& sz33, double& xgh2, double& xgh3, double& xgh4, double& xh2, - double& xh3, double& xi2, double& xi3, double& xl2, double& xl3, - double& xl4, double& nm, double& z1, double& z2, double& z3, - double& z11, double& z12, double& z13, double& z21, double& z22, - double& z23, double& z31, double& z32, double& z33, double& zmol, - double& zmos - ) -{ - /* -------------------------- constants ------------------------- */ - const double zes = 0.01675; - const double zel = 0.05490; - const double c1ss = 2.9864797e-6; - const double c1l = 4.7968065e-7; - const double zsinis = 0.39785416; - const double zcosis = 0.91744867; - const double zcosgs = 0.1945905; - const double zsings = -0.98088458; - const double twopi = 2.0 * pi; - - /* --------------------- local variables ------------------------ */ - int lsflg; - double a1 , a2 , a3 , a4 , a5 , a6 , a7 , - a8 , a9 , a10 , betasq, cc , ctem , stem , - x1 , x2 , x3 , x4 , x5 , x6 , x7 , - x8 , xnodce, xnoi , zcosg , zcosgl, zcosh , zcoshl, - zcosi , zcosil, zsing , zsingl, zsinh , zsinhl, zsini , - zsinil, zx , zy; - - nm = np; - em = ep; - snodm = sin(nodep); - cnodm = cos(nodep); - sinomm = sin(argpp); - cosomm = cos(argpp); - sinim = sin(inclp); - cosim = cos(inclp); - emsq = em * em; - betasq = 1.0 - emsq; - rtemsq = sqrt(betasq); - - /* ----------------- initialize lunar solar terms --------------- */ - peo = 0.0; - pinco = 0.0; - plo = 0.0; - pgho = 0.0; - pho = 0.0; - day = epoch + 18261.5 + tc / 1440.0; - xnodce = fmod(4.5236020 - 9.2422029e-4 * day, twopi); - stem = sin(xnodce); - ctem = cos(xnodce); - zcosil = 0.91375164 - 0.03568096 * ctem; - zsinil = sqrt(1.0 - zcosil * zcosil); - zsinhl = 0.089683511 * stem / zsinil; - zcoshl = sqrt(1.0 - zsinhl * zsinhl); - gam = 5.8351514 + 0.0019443680 * day; - zx = 0.39785416 * stem / zsinil; - zy = zcoshl * ctem + 0.91744867 * zsinhl * stem; - zx = atan2(zx, zy); - zx = gam + zx - xnodce; - zcosgl = cos(zx); - zsingl = sin(zx); - - /* ------------------------- do solar terms --------------------- */ - zcosg = zcosgs; - zsing = zsings; - zcosi = zcosis; - zsini = zsinis; - zcosh = cnodm; - zsinh = snodm; - cc = c1ss; - xnoi = 1.0 / nm; - - for (lsflg = 1; lsflg <= 2; lsflg++) - { - a1 = zcosg * zcosh + zsing * zcosi * zsinh; - a3 = -zsing * zcosh + zcosg * zcosi * zsinh; - a7 = -zcosg * zsinh + zsing * zcosi * zcosh; - a8 = zsing * zsini; - a9 = zsing * zsinh + zcosg * zcosi * zcosh; - a10 = zcosg * zsini; - a2 = cosim * a7 + sinim * a8; - a4 = cosim * a9 + sinim * a10; - a5 = -sinim * a7 + cosim * a8; - a6 = -sinim * a9 + cosim * a10; - - x1 = a1 * cosomm + a2 * sinomm; - x2 = a3 * cosomm + a4 * sinomm; - x3 = -a1 * sinomm + a2 * cosomm; - x4 = -a3 * sinomm + a4 * cosomm; - x5 = a5 * sinomm; - x6 = a6 * sinomm; - x7 = a5 * cosomm; - x8 = a6 * cosomm; - - z31 = 12.0 * x1 * x1 - 3.0 * x3 * x3; - z32 = 24.0 * x1 * x2 - 6.0 * x3 * x4; - z33 = 12.0 * x2 * x2 - 3.0 * x4 * x4; - z1 = 3.0 * (a1 * a1 + a2 * a2) + z31 * emsq; - z2 = 6.0 * (a1 * a3 + a2 * a4) + z32 * emsq; - z3 = 3.0 * (a3 * a3 + a4 * a4) + z33 * emsq; - z11 = -6.0 * a1 * a5 + emsq * (-24.0 * x1 * x7-6.0 * x3 * x5); - z12 = -6.0 * (a1 * a6 + a3 * a5) + emsq * - (-24.0 * (x2 * x7 + x1 * x8) - 6.0 * (x3 * x6 + x4 * x5)); - z13 = -6.0 * a3 * a6 + emsq * (-24.0 * x2 * x8 - 6.0 * x4 * x6); - z21 = 6.0 * a2 * a5 + emsq * (24.0 * x1 * x5 - 6.0 * x3 * x7); - z22 = 6.0 * (a4 * a5 + a2 * a6) + emsq * - (24.0 * (x2 * x5 + x1 * x6) - 6.0 * (x4 * x7 + x3 * x8)); - z23 = 6.0 * a4 * a6 + emsq * (24.0 * x2 * x6 - 6.0 * x4 * x8); - z1 = z1 + z1 + betasq * z31; - z2 = z2 + z2 + betasq * z32; - z3 = z3 + z3 + betasq * z33; - s3 = cc * xnoi; - s2 = -0.5 * s3 / rtemsq; - s4 = s3 * rtemsq; - s1 = -15.0 * em * s4; - s5 = x1 * x3 + x2 * x4; - s6 = x2 * x3 + x1 * x4; - s7 = x2 * x4 - x1 * x3; - - /* ----------------------- do lunar terms ------------------- */ - if (lsflg == 1) - { - ss1 = s1; - ss2 = s2; - ss3 = s3; - ss4 = s4; - ss5 = s5; - ss6 = s6; - ss7 = s7; - sz1 = z1; - sz2 = z2; - sz3 = z3; - sz11 = z11; - sz12 = z12; - sz13 = z13; - sz21 = z21; - sz22 = z22; - sz23 = z23; - sz31 = z31; - sz32 = z32; - sz33 = z33; - zcosg = zcosgl; - zsing = zsingl; - zcosi = zcosil; - zsini = zsinil; - zcosh = zcoshl * cnodm + zsinhl * snodm; - zsinh = snodm * zcoshl - cnodm * zsinhl; - cc = c1l; - } - } - - zmol = fmod(4.7199672 + 0.22997150 * day - gam, twopi); - zmos = fmod(6.2565837 + 0.017201977 * day, twopi); - - /* ------------------------ do solar terms ---------------------- */ - se2 = 2.0 * ss1 * ss6; - se3 = 2.0 * ss1 * ss7; - si2 = 2.0 * ss2 * sz12; - si3 = 2.0 * ss2 * (sz13 - sz11); - sl2 = -2.0 * ss3 * sz2; - sl3 = -2.0 * ss3 * (sz3 - sz1); - sl4 = -2.0 * ss3 * (-21.0 - 9.0 * emsq) * zes; - sgh2 = 2.0 * ss4 * sz32; - sgh3 = 2.0 * ss4 * (sz33 - sz31); - sgh4 = -18.0 * ss4 * zes; - sh2 = -2.0 * ss2 * sz22; - sh3 = -2.0 * ss2 * (sz23 - sz21); - - /* ------------------------ do lunar terms ---------------------- */ - ee2 = 2.0 * s1 * s6; - e3 = 2.0 * s1 * s7; - xi2 = 2.0 * s2 * z12; - xi3 = 2.0 * s2 * (z13 - z11); - xl2 = -2.0 * s3 * z2; - xl3 = -2.0 * s3 * (z3 - z1); - xl4 = -2.0 * s3 * (-21.0 - 9.0 * emsq) * zel; - xgh2 = 2.0 * s4 * z32; - xgh3 = 2.0 * s4 * (z33 - z31); - xgh4 = -18.0 * s4 * zel; - xh2 = -2.0 * s2 * z22; - xh3 = -2.0 * s2 * (z23 - z21); - -//#include "debug2.cpp" -} // end dscom - -/*----------------------------------------------------------------------------- -* -* procedure dsinit -* -* this procedure provides deep space contributions to mean motion dot due -* to geopotential resonance with half day and one day orbits. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* cosim, sinim- -* emsq - eccentricity squared -* argpo - argument of perigee -* s1, s2, s3, s4, s5 - -* ss1, ss2, ss3, ss4, ss5 - -* sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33 - -* t - time -* tc - -* gsto - greenwich sidereal time rad -* mo - mean anomaly -* mdot - mean anomaly dot (rate) -* no - mean motion -* nodeo - right ascension of ascending node -* nodedot - right ascension of ascending node dot (rate) -* xpidot - -* z1, z3, z11, z13, z21, z23, z31, z33 - -* eccm - eccentricity -* argpm - argument of perigee -* inclm - inclination -* mm - mean anomaly -* xn - mean motion -* nodem - right ascension of ascending node -* -* outputs : -* em - eccentricity -* argpm - argument of perigee -* inclm - inclination -* mm - mean anomaly -* nm - mean motion -* nodem - right ascension of ascending node -* irez - flag for resonance 0-none, 1-one day, 2-half day -* atime - -* d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 - -* dedt - -* didt - -* dmdt - -* dndt - -* dnodt - -* domdt - -* del1, del2, del3 - -* ses , sghl , sghs , sgs , shl , shs , sis , sls -* theta - -* xfact - -* xlamo - -* xli - -* xni -* -* locals : -* ainv2 - -* aonv - -* cosisq - -* eoc - -* f220, f221, f311, f321, f322, f330, f441, f442, f522, f523, f542, f543 - -* g200, g201, g211, g300, g310, g322, g410, g422, g520, g521, g532, g533 - -* sini2 - -* temp - -* temp1 - -* theta - -* xno2 - -* -* coupling : -* getgravconst -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void dsinit - ( - gravconsttype whichconst, - double cosim, double emsq, double argpo, double s1, double s2, - double s3, double s4, double s5, double sinim, double ss1, - double ss2, double ss3, double ss4, double ss5, double sz1, - double sz3, double sz11, double sz13, double sz21, double sz23, - double sz31, double sz33, double t, double tc, double gsto, - double mo, double mdot, double no, double nodeo, double nodedot, - double xpidot, double z1, double z3, double z11, double z13, - double z21, double z23, double z31, double z33, double ecco, - double eccsq, double& em, double& argpm, double& inclm, double& mm, - double& nm, double& nodem, - int& irez, - double& atime, double& d2201, double& d2211, double& d3210, double& d3222, - double& d4410, double& d4422, double& d5220, double& d5232, double& d5421, - double& d5433, double& dedt, double& didt, double& dmdt, double& dndt, - double& dnodt, double& domdt, double& del1, double& del2, double& del3, - double& xfact, double& xlamo, double& xli, double& xni - ) -{ - /* --------------------- local variables ------------------------ */ - const double twopi = 2.0 * pi; - - double ainv2 , aonv=0.0, cosisq, eoc, f220 , f221 , f311 , - f321 , f322 , f330 , f441 , f442 , f522 , f523 , - f542 , f543 , g200 , g201 , g211 , g300 , g310 , - g322 , g410 , g422 , g520 , g521 , g532 , g533 , - ses , sgs , sghl , sghs , shs , shll , sis , - sini2 , sls , temp , temp1 , theta , xno2 , q22 , - q31 , q33 , root22, root44, root54, rptim , root32, - root52, x2o3 , xke , znl , emo , zns , emsqo, - tumin, mu, radiusearthkm, j2, j3, j4, j3oj2; - - q22 = 1.7891679e-6; - q31 = 2.1460748e-6; - q33 = 2.2123015e-7; - root22 = 1.7891679e-6; - root44 = 7.3636953e-9; - root54 = 2.1765803e-9; - rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec - root32 = 3.7393792e-7; - root52 = 1.1428639e-7; - x2o3 = 2.0 / 3.0; - znl = 1.5835218e-4; - zns = 1.19459e-5; - - // sgp4fix identify constants and allow alternate values - getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); - - /* -------------------- deep space initialization ------------ */ - irez = 0; - if ((nm < 0.0052359877) && (nm > 0.0034906585)) - irez = 1; - if ((nm >= 8.26e-3) && (nm <= 9.24e-3) && (em >= 0.5)) - irez = 2; - - /* ------------------------ do solar terms ------------------- */ - ses = ss1 * zns * ss5; - sis = ss2 * zns * (sz11 + sz13); - sls = -zns * ss3 * (sz1 + sz3 - 14.0 - 6.0 * emsq); - sghs = ss4 * zns * (sz31 + sz33 - 6.0); - shs = -zns * ss2 * (sz21 + sz23); - // sgp4fix for 180 deg incl - if ((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2)) - shs = 0.0; - if (sinim != 0.0) - shs = shs / sinim; - sgs = sghs - cosim * shs; - - /* ------------------------- do lunar terms ------------------ */ - dedt = ses + s1 * znl * s5; - didt = sis + s2 * znl * (z11 + z13); - dmdt = sls - znl * s3 * (z1 + z3 - 14.0 - 6.0 * emsq); - sghl = s4 * znl * (z31 + z33 - 6.0); - shll = -znl * s2 * (z21 + z23); - // sgp4fix for 180 deg incl - if ((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2)) - shll = 0.0; - domdt = sgs + sghl; - dnodt = shs; - if (sinim != 0.0) - { - domdt = domdt - cosim / sinim * shll; - dnodt = dnodt + shll / sinim; - } - - /* ----------- calculate deep space resonance effects -------- */ - dndt = 0.0; - theta = fmod(gsto + tc * rptim, twopi); - em = em + dedt * t; - inclm = inclm + didt * t; - argpm = argpm + domdt * t; - nodem = nodem + dnodt * t; - mm = mm + dmdt * t; - // sgp4fix for negative inclinations - // the following if statement should be commented out - //if (inclm < 0.0) - // { - // inclm = -inclm; - // argpm = argpm - pi; - // nodem = nodem + pi; - // } - - /* -------------- initialize the resonance terms ------------- */ - if (irez != 0) - { - aonv = pow(nm / xke, x2o3); - - /* ---------- geopotential resonance for 12 hour orbits ------ */ - if (irez == 2) - { - cosisq = cosim * cosim; - emo = em; - em = ecco; - emsqo = emsq; - emsq = eccsq; - eoc = em * emsq; - g201 = -0.306 - (em - 0.64) * 0.440; - - if (em <= 0.65) - { - g211 = 3.616 - 13.2470 * em + 16.2900 * emsq; - g310 = -19.302 + 117.3900 * em - 228.4190 * emsq + 156.5910 * eoc; - g322 = -18.9068 + 109.7927 * em - 214.6334 * emsq + 146.5816 * eoc; - g410 = -41.122 + 242.6940 * em - 471.0940 * emsq + 313.9530 * eoc; - g422 = -146.407 + 841.8800 * em - 1629.014 * emsq + 1083.4350 * eoc; - g520 = -532.114 + 3017.977 * em - 5740.032 * emsq + 3708.2760 * eoc; - } - else - { - g211 = -72.099 + 331.819 * em - 508.738 * emsq + 266.724 * eoc; - g310 = -346.844 + 1582.851 * em - 2415.925 * emsq + 1246.113 * eoc; - g322 = -342.585 + 1554.908 * em - 2366.899 * emsq + 1215.972 * eoc; - g410 = -1052.797 + 4758.686 * em - 7193.992 * emsq + 3651.957 * eoc; - g422 = -3581.690 + 16178.110 * em - 24462.770 * emsq + 12422.520 * eoc; - if (em > 0.715) - g520 =-5149.66 + 29936.92 * em - 54087.36 * emsq + 31324.56 * eoc; - else - g520 = 1464.74 - 4664.75 * em + 3763.64 * emsq; - } - if (em < 0.7) - { - g533 = -919.22770 + 4988.6100 * em - 9064.7700 * emsq + 5542.21 * eoc; - g521 = -822.71072 + 4568.6173 * em - 8491.4146 * emsq + 5337.524 * eoc; - g532 = -853.66600 + 4690.2500 * em - 8624.7700 * emsq + 5341.4 * eoc; - } - else - { - g533 =-37995.780 + 161616.52 * em - 229838.20 * emsq + 109377.94 * eoc; - g521 =-51752.104 + 218913.95 * em - 309468.16 * emsq + 146349.42 * eoc; - g532 =-40023.880 + 170470.89 * em - 242699.48 * emsq + 115605.82 * eoc; - } - - sini2= sinim * sinim; - f220 = 0.75 * (1.0 + 2.0 * cosim+cosisq); - f221 = 1.5 * sini2; - f321 = 1.875 * sinim * (1.0 - 2.0 * cosim - 3.0 * cosisq); - f322 = -1.875 * sinim * (1.0 + 2.0 * cosim - 3.0 * cosisq); - f441 = 35.0 * sini2 * f220; - f442 = 39.3750 * sini2 * sini2; - f522 = 9.84375 * sinim * (sini2 * (1.0 - 2.0 * cosim- 5.0 * cosisq) + - 0.33333333 * (-2.0 + 4.0 * cosim + 6.0 * cosisq) ); - f523 = sinim * (4.92187512 * sini2 * (-2.0 - 4.0 * cosim + - 10.0 * cosisq) + 6.56250012 * (1.0+2.0 * cosim - 3.0 * cosisq)); - f542 = 29.53125 * sinim * (2.0 - 8.0 * cosim+cosisq * - (-12.0 + 8.0 * cosim + 10.0 * cosisq)); - f543 = 29.53125 * sinim * (-2.0 - 8.0 * cosim+cosisq * - (12.0 + 8.0 * cosim - 10.0 * cosisq)); - xno2 = nm * nm; - ainv2 = aonv * aonv; - temp1 = 3.0 * xno2 * ainv2; - temp = temp1 * root22; - d2201 = temp * f220 * g201; - d2211 = temp * f221 * g211; - temp1 = temp1 * aonv; - temp = temp1 * root32; - d3210 = temp * f321 * g310; - d3222 = temp * f322 * g322; - temp1 = temp1 * aonv; - temp = 2.0 * temp1 * root44; - d4410 = temp * f441 * g410; - d4422 = temp * f442 * g422; - temp1 = temp1 * aonv; - temp = temp1 * root52; - d5220 = temp * f522 * g520; - d5232 = temp * f523 * g532; - temp = 2.0 * temp1 * root54; - d5421 = temp * f542 * g521; - d5433 = temp * f543 * g533; - xlamo = fmod(mo + nodeo + nodeo-theta - theta, twopi); - xfact = mdot + dmdt + 2.0 * (nodedot + dnodt - rptim) - no; - em = emo; - emsq = emsqo; - } - - /* ---------------- synchronous resonance terms -------------- */ - if (irez == 1) - { - g200 = 1.0 + emsq * (-2.5 + 0.8125 * emsq); - g310 = 1.0 + 2.0 * emsq; - g300 = 1.0 + emsq * (-6.0 + 6.60937 * emsq); - f220 = 0.75 * (1.0 + cosim) * (1.0 + cosim); - f311 = 0.9375 * sinim * sinim * (1.0 + 3.0 * cosim) - 0.75 * (1.0 + cosim); - f330 = 1.0 + cosim; - f330 = 1.875 * f330 * f330 * f330; - del1 = 3.0 * nm * nm * aonv * aonv; - del2 = 2.0 * del1 * f220 * g200 * q22; - del3 = 3.0 * del1 * f330 * g300 * q33 * aonv; - del1 = del1 * f311 * g310 * q31 * aonv; - xlamo = fmod(mo + nodeo + argpo - theta, twopi); - xfact = mdot + xpidot - rptim + dmdt + domdt + dnodt - no; - } - - /* ------------ for sgp4, initialize the integrator ---------- */ - xli = xlamo; - xni = no; - atime = 0.0; - nm = no + dndt; - } - -//#include "debug3.cpp" -} // end dsinit - -/*----------------------------------------------------------------------------- -* -* procedure dspace -* -* this procedure provides deep space contributions to mean elements for -* perturbing third body. these effects have been averaged over one -* revolution of the sun and moon. for earth resonance effects, the -* effects have been averaged over no revolutions of the satellite. -* (mean motion) -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 - -* dedt - -* del1, del2, del3 - -* didt - -* dmdt - -* dnodt - -* domdt - -* irez - flag for resonance 0-none, 1-one day, 2-half day -* argpo - argument of perigee -* argpdot - argument of perigee dot (rate) -* t - time -* tc - -* gsto - gst -* xfact - -* xlamo - -* no - mean motion -* atime - -* em - eccentricity -* ft - -* argpm - argument of perigee -* inclm - inclination -* xli - -* mm - mean anomaly -* xni - mean motion -* nodem - right ascension of ascending node -* -* outputs : -* atime - -* em - eccentricity -* argpm - argument of perigee -* inclm - inclination -* xli - -* mm - mean anomaly -* xni - -* nodem - right ascension of ascending node -* dndt - -* nm - mean motion -* -* locals : -* delt - -* ft - -* theta - -* x2li - -* x2omi - -* xl - -* xldot - -* xnddt - -* xndt - -* xomi - -* -* coupling : -* none - -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void dspace - ( - int irez, - double d2201, double d2211, double d3210, double d3222, double d4410, - double d4422, double d5220, double d5232, double d5421, double d5433, - double dedt, double del1, double del2, double del3, double didt, - double dmdt, double dnodt, double domdt, double argpo, double argpdot, - double t, double tc, double gsto, double xfact, double xlamo, - double no, - double& atime, double& em, double& argpm, double& inclm, double& xli, - double& mm, double& xni, double& nodem, double& dndt, double& nm - ) -{ - const double twopi = 2.0 * pi; - int iretn , iret; - double delt, ft, theta, x2li, x2omi, xl, xldot , xnddt, xndt, xomi, g22, g32, - g44, g52, g54, fasx2, fasx4, fasx6, rptim , step2, stepn , stepp; - - ft = 0.0; - fasx2 = 0.13130908; - fasx4 = 2.8843198; - fasx6 = 0.37448087; - g22 = 5.7686396; - g32 = 0.95240898; - g44 = 1.8014998; - g52 = 1.0508330; - g54 = 4.4108898; - rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec - stepp = 720.0; - stepn = -720.0; - step2 = 259200.0; - - /* ----------- calculate deep space resonance effects ----------- */ - dndt = 0.0; - theta = fmod(gsto + tc * rptim, twopi); - em = em + dedt * t; - - inclm = inclm + didt * t; - argpm = argpm + domdt * t; - nodem = nodem + dnodt * t; - mm = mm + dmdt * t; - - // sgp4fix for negative inclinations - // the following if statement should be commented out - // if (inclm < 0.0) - // { - // inclm = -inclm; - // argpm = argpm - pi; - // nodem = nodem + pi; - // } - - /* - update resonances : numerical (euler-maclaurin) integration - */ - /* ------------------------- epoch restart ---------------------- */ - // sgp4fix for propagator problems - // the following integration works for negative time steps and periods - // the specific changes are unknown because the original code was so convoluted - - ft = 0.0; - atime = 0.0; - if (irez != 0) - { - if ((atime == 0.0) || ((t >= 0.0) && (atime < 0.0)) || - ((t < 0.0) && (atime >= 0.0))) - { - if (t >= 0.0) - delt = stepp; - else - delt = stepn; - atime = 0.0; - xni = no; - xli = xlamo; - } - iretn = 381; // added for do loop - iret = 0; // added for loop - while (iretn == 381) - { - if ((fabs(t) < fabs(atime)) || (iret == 351)) - { - if (t >= 0.0) - delt = stepn; - else - delt = stepp; - iret = 351; - iretn = 381; - } - else - { - if (t > 0.0) // error if prev if has atime:=0.0 and t:=0.0 (ge) - delt = stepp; - else - delt = stepn; - if (fabs(t - atime) >= stepp) - { - iret = 0; - iretn = 381; - } - else - { - ft = t - atime; - iretn = 0; - } - } - - /* ------------------- dot terms calculated ------------- */ - /* ----------- near - synchronous resonance terms ------- */ - if (irez != 2) - { - xndt = del1 * sin(xli - fasx2) + del2 * sin(2.0 * (xli - fasx4)) + - del3 * sin(3.0 * (xli - fasx6)); - xldot = xni + xfact; - xnddt = del1 * cos(xli - fasx2) + - 2.0 * del2 * cos(2.0 * (xli - fasx4)) + - 3.0 * del3 * cos(3.0 * (xli - fasx6)); - xnddt = xnddt * xldot; - } - else - { - /* --------- near - half-day resonance terms -------- */ - xomi = argpo + argpdot * atime; - x2omi = xomi + xomi; - x2li = xli + xli; - xndt = d2201 * sin(x2omi + xli - g22) + d2211 * sin(xli - g22) + - d3210 * sin(xomi + xli - g32) + d3222 * sin(-xomi + xli - g32)+ - d4410 * sin(x2omi + x2li - g44)+ d4422 * sin(x2li - g44) + - d5220 * sin(xomi + xli - g52) + d5232 * sin(-xomi + xli - g52)+ - d5421 * sin(xomi + x2li - g54) + d5433 * sin(-xomi + x2li - g54); - xldot = xni + xfact; - xnddt = d2201 * cos(x2omi + xli - g22) + d2211 * cos(xli - g22) + - d3210 * cos(xomi + xli - g32) + d3222 * cos(-xomi + xli - g32) + - d5220 * cos(xomi + xli - g52) + d5232 * cos(-xomi + xli - g52) + - 2.0 * (d4410 * cos(x2omi + x2li - g44) + - d4422 * cos(x2li - g44) + d5421 * cos(xomi + x2li - g54) + - d5433 * cos(-xomi + x2li - g54)); - xnddt = xnddt * xldot; - } - - /* ----------------------- integrator ------------------- */ - if (iretn == 381) - { - xli = xli + xldot * delt + xndt * step2; - xni = xni + xndt * delt + xnddt * step2; - atime = atime + delt; - } - } // while iretn = 381 - - nm = xni + xndt * ft + xnddt * ft * ft * 0.5; - xl = xli + xldot * ft + xndt * ft * ft * 0.5; - if (irez != 1) - { - mm = xl - 2.0 * nodem + 2.0 * theta; - dndt = nm - no; - } - else - { - mm = xl - nodem - argpm + theta; - dndt = nm - no; - } - nm = no + dndt; - } - -//#include "debug4.cpp" -} // end dsspace - -/*----------------------------------------------------------------------------- -* -* procedure initl -* -* this procedure initializes the spg4 propagator. all the initialization is -* consolidated here instead of having multiple loops inside other routines. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* ecco - eccentricity 0.0 - 1.0 -* epoch - epoch time in days from jan 0, 1950. 0 hr -* inclo - inclination of satellite -* no - mean motion of satellite -* satn - satellite number -* -* outputs : -* ainv - 1.0 / a -* ao - semi major axis -* con41 - -* con42 - 1.0 - 5.0 cos(i) -* cosio - cosine of inclination -* cosio2 - cosio squared -* eccsq - eccentricity squared -* method - flag for deep space 'd', 'n' -* omeosq - 1.0 - ecco * ecco -* posq - semi-parameter squared -* rp - radius of perigee -* rteosq - square root of (1.0 - ecco*ecco) -* sinio - sine of inclination -* gsto - gst at time of observation rad -* no - mean motion of satellite -* -* locals : -* ak - -* d1 - -* del - -* adel - -* po - -* -* coupling : -* getgravconst -* gstime - find greenwich sidereal time from the julian date -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void initl - ( - int satn, gravconsttype whichconst, - double ecco, double epoch, double inclo, double& no, - char& method, - double& ainv, double& ao, double& con41, double& con42, double& cosio, - double& cosio2,double& eccsq, double& omeosq, double& posq, - double& rp, double& rteosq,double& sinio , double& gsto - ) -{ - /* --------------------- local variables ------------------------ */ - double ak, d1, del, adel, po, x2o3, j2, xke, - tumin, mu, radiusearthkm, j3, j4, j3oj2; - - // sgp4fix use old way of finding gst - int ids70; - double ts70, ds70, tfrac, c1, thgr70, fk5r, c1p2p; - const double twopi = 2.0 * pi; - - /* ----------------------- earth constants ---------------------- */ - // sgp4fix identify constants and allow alternate values - getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); - x2o3 = 2.0 / 3.0; - - /* ------------- calculate auxillary epoch quantities ---------- */ - eccsq = ecco * ecco; - omeosq = 1.0 - eccsq; - rteosq = sqrt(omeosq); - cosio = cos(inclo); - cosio2 = cosio * cosio; - - /* ------------------ un-kozai the mean motion ----------------- */ - ak = pow(xke / no, x2o3); - d1 = 0.75 * j2 * (3.0 * cosio2 - 1.0) / (rteosq * omeosq); - del = d1 / (ak * ak); - adel = ak * (1.0 - del * del - del * - (1.0 / 3.0 + 134.0 * del * del / 81.0)); - del = d1/(adel * adel); - no = no / (1.0 + del); - - ao = pow(xke / no, x2o3); - sinio = sin(inclo); - po = ao * omeosq; - con42 = 1.0 - 5.0 * cosio2; - con41 = -con42-cosio2-cosio2; - ainv = 1.0 / ao; - posq = po * po; - rp = ao * (1.0 - ecco); - method = 'n'; - - // sgp4fix modern approach to finding sidereal timew - // gsto = gstime(epoch + 2433281.5); - - // sgp4fix use old way of finding gst - // count integer number of days from 0 jan 1970 - ts70 = epoch - 7305.0; - ids70 = floor(ts70 + 1.0e-8); - ds70 = ids70; - tfrac = ts70 - ds70; - // find greenwich location at epoch - c1 = 1.72027916940703639e-2; - thgr70= 1.7321343856509374; - fk5r = 5.07551419432269442e-15; - c1p2p = c1 + twopi; - gsto = fmod( thgr70 + c1*ds70 + c1p2p*tfrac + ts70*ts70*fk5r, twopi); - if ( gsto < 0.0 ) - gsto = gsto + twopi; - -//#include "debug5.cpp" -} // end initl - -/*----------------------------------------------------------------------------- -* -* procedure sgp4init -* -* this procedure initializes variables for sgp4. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* satn - satellite number -* bstar - sgp4 type drag coefficient kg/m2er -* ecco - eccentricity -* epoch - epoch time in days from jan 0, 1950. 0 hr -* argpo - argument of perigee (output if ds) -* inclo - inclination -* mo - mean anomaly (output if ds) -* no - mean motion -* nodeo - right ascension of ascending node -* -* outputs : -* satrec - common values for subsequent calls -* return code - non-zero on error. -* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er -* 2 - mean motion less than 0.0 -* 3 - pert elements, ecc < 0.0 or ecc > 1.0 -* 4 - semi-latus rectum < 0.0 -* 5 - epoch elements are sub-orbital -* 6 - satellite has decayed -* -* locals : -* cnodm , snodm , cosim , sinim , cosomm , sinomm -* cc1sq , cc2 , cc3 -* coef , coef1 -* cosio4 - -* day - -* dndt - -* em - eccentricity -* emsq - eccentricity squared -* eeta - -* etasq - -* gam - -* argpm - argument of perigee -* nodem - -* inclm - inclination -* mm - mean anomaly -* nm - mean motion -* perige - perigee -* pinvsq - -* psisq - -* qzms24 - -* rtemsq - -* s1, s2, s3, s4, s5, s6, s7 - -* sfour - -* ss1, ss2, ss3, ss4, ss5, ss6, ss7 - -* sz1, sz2, sz3 -* sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33 - -* tc - -* temp - -* temp1, temp2, temp3 - -* tsi - -* xpidot - -* xhdot1 - -* z1, z2, z3 - -* z11, z12, z13, z21, z22, z23, z31, z32, z33 - -* -* coupling : -* getgravconst- -* initl - -* dscom - -* dpper - -* dsinit - -* sgp4 - -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -int sgp4init - ( - gravconsttype whichconst, const int satn, const double epoch, - const double xbstar, const double xecco, const double xargpo, - const double xinclo, const double xmo, const double xno, - const double xnodeo, elsetrec& satrec - ) -{ - /* --------------------- local variables ------------------------ */ - double ao, ainv, con42, cosio, sinio, cosio2, eccsq, - omeosq, posq, rp, rteosq, - cnodm , snodm , cosim , sinim , cosomm, sinomm, cc1sq , - cc2 , cc3 , coef , coef1 , cosio4, day , dndt , - em , emsq , eeta , etasq , gam , argpm , nodem , - inclm , mm , nm , perige, pinvsq, psisq , qzms24, - rtemsq, s1 , s2 , s3 , s4 , s5 , s6 , - s7 , sfour , ss1 = 0 , ss2 = 0 , ss3 = 0 , ss4 = 0 , ss5 = 0 , - ss6 = 0 , ss7 = 0 , sz1 = 0 , sz2 = 0 , sz3 = 0 , sz11 = 0 , sz12 = 0 , - sz13 = 0 , sz21 = 0 , sz22 = 0 , sz23 = 0 , sz31 = 0 , sz32 = 0 , sz33 = 0 , - tc , temp , temp1 , temp2 , temp3 , tsi , xpidot, - xhdot1, z1 , z2 , z3 , z11 , z12 , z13 , - z21 , z22 , z23 , z31 , z32 , z33, - qzms2t, ss, j2, j3oj2, j4, x2o3, r[3], v[3], - tumin, mu, radiusearthkm, xke, j3; - - /* ------------------------ initialization --------------------- */ - // sgp4fix divisor for divide by zero check on inclination - const double temp4 = 1.0 + cos(pi-1.0e-9); - - /* ----------- set all near earth variables to zero ------------ */ - satrec.isimp = 0; satrec.method = 'n'; satrec.aycof = 0.0; - satrec.con41 = 0.0; satrec.cc1 = 0.0; satrec.cc4 = 0.0; - satrec.cc5 = 0.0; satrec.d2 = 0.0; satrec.d3 = 0.0; - satrec.d4 = 0.0; satrec.delmo = 0.0; satrec.eta = 0.0; - satrec.argpdot = 0.0; satrec.omgcof = 0.0; satrec.sinmao = 0.0; - satrec.t = 0.0; satrec.t2cof = 0.0; satrec.t3cof = 0.0; - satrec.t4cof = 0.0; satrec.t5cof = 0.0; satrec.x1mth2 = 0.0; - satrec.x7thm1 = 0.0; satrec.mdot = 0.0; satrec.nodedot = 0.0; - satrec.xlcof = 0.0; satrec.xmcof = 0.0; satrec.nodecf = 0.0; - - /* ----------- set all deep space variables to zero ------------ */ - satrec.irez = 0; satrec.d2201 = 0.0; satrec.d2211 = 0.0; - satrec.d3210 = 0.0; satrec.d3222 = 0.0; satrec.d4410 = 0.0; - satrec.d4422 = 0.0; satrec.d5220 = 0.0; satrec.d5232 = 0.0; - satrec.d5421 = 0.0; satrec.d5433 = 0.0; satrec.dedt = 0.0; - satrec.del1 = 0.0; satrec.del2 = 0.0; satrec.del3 = 0.0; - satrec.didt = 0.0; satrec.dmdt = 0.0; satrec.dnodt = 0.0; - satrec.domdt = 0.0; satrec.e3 = 0.0; satrec.ee2 = 0.0; - satrec.peo = 0.0; satrec.pgho = 0.0; satrec.pho = 0.0; - satrec.pinco = 0.0; satrec.plo = 0.0; satrec.se2 = 0.0; - satrec.se3 = 0.0; satrec.sgh2 = 0.0; satrec.sgh3 = 0.0; - satrec.sgh4 = 0.0; satrec.sh2 = 0.0; satrec.sh3 = 0.0; - satrec.si2 = 0.0; satrec.si3 = 0.0; satrec.sl2 = 0.0; - satrec.sl3 = 0.0; satrec.sl4 = 0.0; satrec.gsto = 0.0; - satrec.xfact = 0.0; satrec.xgh2 = 0.0; satrec.xgh3 = 0.0; - satrec.xgh4 = 0.0; satrec.xh2 = 0.0; satrec.xh3 = 0.0; - satrec.xi2 = 0.0; satrec.xi3 = 0.0; satrec.xl2 = 0.0; - satrec.xl3 = 0.0; satrec.xl4 = 0.0; satrec.xlamo = 0.0; - satrec.zmol = 0.0; satrec.zmos = 0.0; satrec.atime = 0.0; - satrec.xli = 0.0; satrec.xni = 0.0; - - // sgp4fix - note the following variables are also passed directly via satrec. - // it is possible to streamline the sgp4init call by deleting the "x" - // variables, but the user would need to set the satrec.* values first. we - // include the additional assignments in case twoline2rv is not used. - satrec.bstar = xbstar; - satrec.ecco = xecco; - satrec.argpo = xargpo; - satrec.inclo = xinclo; - satrec.mo = xmo; - satrec.no = xno; - satrec.nodeo = xnodeo; - - /* ------------------------ earth constants ----------------------- */ - // sgp4fix identify constants and allow alternate values - getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); - ss = 78.0 / radiusearthkm + 1.0; - qzms2t = pow(((120.0 - 78.0) / radiusearthkm), 4); - x2o3 = 2.0 / 3.0; - - satrec.init = 'y'; - satrec.t = 0.0; - - initl - ( - satn, whichconst, satrec.ecco, epoch, satrec.inclo, satrec.no, satrec.method, - ainv, ao, satrec.con41, con42, cosio, cosio2, eccsq, omeosq, - posq, rp, rteosq, sinio, satrec.gsto - ); - satrec.error = 0; - - if (rp < 1.0) - { -// printf("# *** satn%d epoch elts sub-orbital ***\n", satn); - satrec.error = 5; - } - - if ((omeosq >= 0.0 ) || ( satrec.no >= 0.0)) - { - satrec.isimp = 0; - if (rp < (220.0 / radiusearthkm + 1.0)) - satrec.isimp = 1; - sfour = ss; - qzms24 = qzms2t; - perige = (rp - 1.0) * radiusearthkm; - - /* - for perigees below 156 km, s and qoms2t are altered - */ - if (perige < 156.0) - { - sfour = perige - 78.0; - if (perige < 98.0) - sfour = 20.0; - qzms24 = pow(((120.0 - sfour) / radiusearthkm), 4.0); - sfour = sfour / radiusearthkm + 1.0; - } - pinvsq = 1.0 / posq; - - tsi = 1.0 / (ao - sfour); - satrec.eta = ao * satrec.ecco * tsi; - etasq = satrec.eta * satrec.eta; - eeta = satrec.ecco * satrec.eta; - psisq = fabs(1.0 - etasq); - coef = qzms24 * pow(tsi, 4.0); - coef1 = coef / pow(psisq, 3.5); - cc2 = coef1 * satrec.no * (ao * (1.0 + 1.5 * etasq + eeta * - (4.0 + etasq)) + 0.375 * j2 * tsi / psisq * satrec.con41 * - (8.0 + 3.0 * etasq * (8.0 + etasq))); - satrec.cc1 = satrec.bstar * cc2; - cc3 = 0.0; - if (satrec.ecco > 1.0e-4) - cc3 = -2.0 * coef * tsi * j3oj2 * satrec.no * sinio / satrec.ecco; - satrec.x1mth2 = 1.0 - cosio2; - satrec.cc4 = 2.0* satrec.no * coef1 * ao * omeosq * - (satrec.eta * (2.0 + 0.5 * etasq) + satrec.ecco * - (0.5 + 2.0 * etasq) - j2 * tsi / (ao * psisq) * - (-3.0 * satrec.con41 * (1.0 - 2.0 * eeta + etasq * - (1.5 - 0.5 * eeta)) + 0.75 * satrec.x1mth2 * - (2.0 * etasq - eeta * (1.0 + etasq)) * cos(2.0 * satrec.argpo))); - satrec.cc5 = 2.0 * coef1 * ao * omeosq * (1.0 + 2.75 * - (etasq + eeta) + eeta * etasq); - cosio4 = cosio2 * cosio2; - temp1 = 1.5 * j2 * pinvsq * satrec.no; - temp2 = 0.5 * temp1 * j2 * pinvsq; - temp3 = -0.46875 * j4 * pinvsq * pinvsq * satrec.no; - satrec.mdot = satrec.no + 0.5 * temp1 * rteosq * satrec.con41 + 0.0625 * - temp2 * rteosq * (13.0 - 78.0 * cosio2 + 137.0 * cosio4); - satrec.argpdot = -0.5 * temp1 * con42 + 0.0625 * temp2 * - (7.0 - 114.0 * cosio2 + 395.0 * cosio4) + - temp3 * (3.0 - 36.0 * cosio2 + 49.0 * cosio4); - xhdot1 = -temp1 * cosio; - satrec.nodedot = xhdot1 + (0.5 * temp2 * (4.0 - 19.0 * cosio2) + - 2.0 * temp3 * (3.0 - 7.0 * cosio2)) * cosio; - xpidot = satrec.argpdot+ satrec.nodedot; - satrec.omgcof = satrec.bstar * cc3 * cos(satrec.argpo); - satrec.xmcof = 0.0; - if (satrec.ecco > 1.0e-4) - satrec.xmcof = -x2o3 * coef * satrec.bstar / eeta; - satrec.nodecf = 3.5 * omeosq * xhdot1 * satrec.cc1; - satrec.t2cof = 1.5 * satrec.cc1; - // sgp4fix for divide by zero with xinco = 180 deg - if (fabs(cosio+1.0) > 1.5e-12) - satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / (1.0 + cosio); - else - satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / temp4; - satrec.aycof = -0.5 * j3oj2 * sinio; - satrec.delmo = pow((1.0 + satrec.eta * cos(satrec.mo)), 3); - satrec.sinmao = sin(satrec.mo); - satrec.x7thm1 = 7.0 * cosio2 - 1.0; - - /* --------------- deep space initialization ------------- */ - if ((2*pi / satrec.no) >= 225.0) - { - satrec.method = 'd'; - satrec.isimp = 1; - tc = 0.0; - inclm = satrec.inclo; - - dscom - ( - epoch, satrec.ecco, satrec.argpo, tc, satrec.inclo, satrec.nodeo, - satrec.no, snodm, cnodm, sinim, cosim,sinomm, cosomm, - day, satrec.e3, satrec.ee2, em, emsq, gam, - satrec.peo, satrec.pgho, satrec.pho, satrec.pinco, - satrec.plo, rtemsq, satrec.se2, satrec.se3, - satrec.sgh2, satrec.sgh3, satrec.sgh4, - satrec.sh2, satrec.sh3, satrec.si2, satrec.si3, - satrec.sl2, satrec.sl3, satrec.sl4, s1, s2, s3, s4, s5, - s6, s7, ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3, - sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33, - satrec.xgh2, satrec.xgh3, satrec.xgh4, satrec.xh2, - satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2, - satrec.xl3, satrec.xl4, nm, z1, z2, z3, z11, - z12, z13, z21, z22, z23, z31, z32, z33, - satrec.zmol, satrec.zmos - ); - dpper - ( - satrec.e3, satrec.ee2, satrec.peo, satrec.pgho, - satrec.pho, satrec.pinco, satrec.plo, satrec.se2, - satrec.se3, satrec.sgh2, satrec.sgh3, satrec.sgh4, - satrec.sh2, satrec.sh3, satrec.si2, satrec.si3, - satrec.sl2, satrec.sl3, satrec.sl4, satrec.t, - satrec.xgh2,satrec.xgh3,satrec.xgh4, satrec.xh2, - satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2, - satrec.xl3, satrec.xl4, satrec.zmol, satrec.zmos, inclm, satrec.init, - satrec.ecco, satrec.inclo, satrec.nodeo, satrec.argpo, satrec.mo - ); - - argpm = 0.0; - nodem = 0.0; - mm = 0.0; - - dsinit - ( - whichconst, - cosim, emsq, satrec.argpo, s1, s2, s3, s4, s5, sinim, ss1, ss2, ss3, ss4, - ss5, sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33, satrec.t, tc, - satrec.gsto, satrec.mo, satrec.mdot, satrec.no, satrec.nodeo, - satrec.nodedot, xpidot, z1, z3, z11, z13, z21, z23, z31, z33, - satrec.ecco, eccsq, em, argpm, inclm, mm, nm, nodem, - satrec.irez, satrec.atime, - satrec.d2201, satrec.d2211, satrec.d3210, satrec.d3222 , - satrec.d4410, satrec.d4422, satrec.d5220, satrec.d5232, - satrec.d5421, satrec.d5433, satrec.dedt, satrec.didt, - satrec.dmdt, dndt, satrec.dnodt, satrec.domdt , - satrec.del1, satrec.del2, satrec.del3, satrec.xfact, - satrec.xlamo, satrec.xli, satrec.xni - ); - } - - /* ----------- set variables if not deep space ----------- */ - if (satrec.isimp != 1) - { - cc1sq = satrec.cc1 * satrec.cc1; - satrec.d2 = 4.0 * ao * tsi * cc1sq; - temp = satrec.d2 * tsi * satrec.cc1 / 3.0; - satrec.d3 = (17.0 * ao + sfour) * temp; - satrec.d4 = 0.5 * temp * ao * tsi * (221.0 * ao + 31.0 * sfour) * - satrec.cc1; - satrec.t3cof = satrec.d2 + 2.0 * cc1sq; - satrec.t4cof = 0.25 * (3.0 * satrec.d3 + satrec.cc1 * - (12.0 * satrec.d2 + 10.0 * cc1sq)); - satrec.t5cof = 0.2 * (3.0 * satrec.d4 + - 12.0 * satrec.cc1 * satrec.d3 + - 6.0 * satrec.d2 * satrec.d2 + - 15.0 * cc1sq * (2.0 * satrec.d2 + cc1sq)); - } - } // if omeosq = 0 ... - - /* finally propogate to zero epoch to initialise all others. */ - if(satrec.error == 0) - sgp4(whichconst, satrec, 0.0, r, v); - - satrec.init = 'n'; - -//#include "debug6.cpp" - return satrec.error; -} // end sgp4init - -/*----------------------------------------------------------------------------- -* -* procedure sgp4 -* -* this procedure is the sgp4 prediction model from space command. this is an -* updated and combined version of sgp4 and sdp4, which were originally -* published separately in spacetrack report #3. this version follows the -* methodology from the aiaa paper (2006) describing the history and -* development of the code. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* satrec - initialised structure from sgp4init() call. -* tsince - time eince epoch (minutes) -* -* outputs : -* r - position vector km -* v - velocity km/sec -* return code - non-zero on error. -* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er -* 2 - mean motion less than 0.0 -* 3 - pert elements, ecc < 0.0 or ecc > 1.0 -* 4 - semi-latus rectum < 0.0 -* 5 - epoch elements are sub-orbital -* 6 - satellite has decayed -* -* locals : -* am - -* axnl, aynl - -* betal - -* cosim , sinim , cosomm , sinomm , cnod , snod , cos2u , -* sin2u , coseo1 , sineo1 , cosi , sini , cosip , sinip , -* cosisq , cossu , sinsu , cosu , sinu -* delm - -* delomg - -* dndt - -* eccm - -* emsq - -* ecose - -* el2 - -* eo1 - -* eccp - -* esine - -* argpm - -* argpp - -* omgadf - -* pl - -* r - -* rtemsq - -* rdotl - -* rl - -* rvdot - -* rvdotl - -* su - -* t2 , t3 , t4 , tc -* tem5, temp , temp1 , temp2 , tempa , tempe , templ -* u , ux , uy , uz , vx , vy , vz -* inclm - inclination -* mm - mean anomaly -* nm - mean motion -* nodem - right asc of ascending node -* xinc - -* xincp - -* xl - -* xlm - -* mp - -* xmdf - -* xmx - -* xmy - -* nodedf - -* xnode - -* nodep - -* np - -* -* coupling : -* getgravconst- -* dpper -* dpspace -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -int sgp4 - ( - gravconsttype whichconst, elsetrec& satrec, double tsince, - double r[3], double v[3] - ) -{ - double am , axnl , aynl , betal , cosim , cnod , - cos2u, coseo1, cosi , cosip , cosisq, cossu , cosu, - delm , delomg, em , emsq , ecose , el2 , eo1 , - ep , esine , argpm, argpp , argpdf, pl, mrt = 0.0, - mvt , rdotl , rl , rvdot , rvdotl, sinim , - sin2u, sineo1, sini , sinip , sinsu , sinu , - snod , su , t2 , t3 , t4 , tem5 , temp, - temp1, temp2 , tempa, tempe , templ , u , ux , - uy , uz , vx , vy , vz , inclm , mm , - nm , nodem, xinc , xincp , xl , xlm , mp , - xmdf , xmx , xmy , nodedf, xnode , nodep, tc , dndt, - twopi, x2o3 , j2 , j3 , tumin, j4 , xke , j3oj2, radiusearthkm, - mu, vkmpersec; - int ktr; - - /* ------------------ set mathematical constants --------------- */ - // sgp4fix divisor for divide by zero check on inclination - const double temp4 = 1.0 + cos(pi-1.0e-9); - twopi = 2.0 * pi; - x2o3 = 2.0 / 3.0; - // sgp4fix identify constants and allow alternate values - getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); - vkmpersec = radiusearthkm * xke/60.0; - - /* --------------------- clear sgp4 error flag ----------------- */ - satrec.t = tsince; - satrec.error = 0; - - /* ------- update for secular gravity and atmospheric drag ----- */ - xmdf = satrec.mo + satrec.mdot * satrec.t; - argpdf = satrec.argpo + satrec.argpdot * satrec.t; - nodedf = satrec.nodeo + satrec.nodedot * satrec.t; - argpm = argpdf; - mm = xmdf; - t2 = satrec.t * satrec.t; - nodem = nodedf + satrec.nodecf * t2; - tempa = 1.0 - satrec.cc1 * satrec.t; - tempe = satrec.bstar * satrec.cc4 * satrec.t; - templ = satrec.t2cof * t2; - - if (satrec.isimp != 1) - { - delomg = satrec.omgcof * satrec.t; - delm = satrec.xmcof * - (pow((1.0 + satrec.eta * cos(xmdf)), 3) - - satrec.delmo); - temp = delomg + delm; - mm = xmdf + temp; - argpm = argpdf - temp; - t3 = t2 * satrec.t; - t4 = t3 * satrec.t; - tempa = tempa - satrec.d2 * t2 - satrec.d3 * t3 - - satrec.d4 * t4; - tempe = tempe + satrec.bstar * satrec.cc5 * (sin(mm) - - satrec.sinmao); - templ = templ + satrec.t3cof * t3 + t4 * (satrec.t4cof + - satrec.t * satrec.t5cof); - } - - nm = satrec.no; - em = satrec.ecco; - inclm = satrec.inclo; - if (satrec.method == 'd') - { - tc = satrec.t; - dspace - ( - satrec.irez, - satrec.d2201, satrec.d2211, satrec.d3210, - satrec.d3222, satrec.d4410, satrec.d4422, - satrec.d5220, satrec.d5232, satrec.d5421, - satrec.d5433, satrec.dedt, satrec.del1, - satrec.del2, satrec.del3, satrec.didt, - satrec.dmdt, satrec.dnodt, satrec.domdt, - satrec.argpo, satrec.argpdot, satrec.t, tc, - satrec.gsto, satrec.xfact, satrec.xlamo, - satrec.no, satrec.atime, - em, argpm, inclm, satrec.xli, mm, satrec.xni, - nodem, dndt, nm - ); - } // if method = d - - if (nm <= 0.0) - { -// printf("# error nm %f\n", nm); - satrec.error = 2; - } - am = pow((xke / nm),x2o3) * tempa * tempa; - nm = xke / pow(am, 1.5); - em = em - tempe; - - // fix tolerance for error recognition - if ((em >= 1.0) || (em < -0.001) || (am < 0.95)) - { -// printf("# error em %f\n", em); - satrec.error = 1; - } - if (em < 0.0) - em = 1.0e-6; - mm = mm + satrec.no * templ; - xlm = mm + argpm + nodem; - emsq = em * em; - temp = 1.0 - emsq; - - nodem = fmod(nodem, twopi); - argpm = fmod(argpm, twopi); - xlm = fmod(xlm, twopi); - mm = fmod(xlm - argpm - nodem, twopi); - - /* ----------------- compute extra mean quantities ------------- */ - sinim = sin(inclm); - cosim = cos(inclm); - - /* -------------------- add lunar-solar periodics -------------- */ - ep = em; - xincp = inclm; - argpp = argpm; - nodep = nodem; - mp = mm; - sinip = sinim; - cosip = cosim; - if (satrec.method == 'd') - { - dpper - ( - satrec.e3, satrec.ee2, satrec.peo, - satrec.pgho, satrec.pho, satrec.pinco, - satrec.plo, satrec.se2, satrec.se3, - satrec.sgh2, satrec.sgh3, satrec.sgh4, - satrec.sh2, satrec.sh3, satrec.si2, - satrec.si3, satrec.sl2, satrec.sl3, - satrec.sl4, satrec.t, satrec.xgh2, - satrec.xgh3, satrec.xgh4, satrec.xh2, - satrec.xh3, satrec.xi2, satrec.xi3, - satrec.xl2, satrec.xl3, satrec.xl4, - satrec.zmol, satrec.zmos, satrec.inclo, - 'n', ep, xincp, nodep, argpp, mp - ); - if (xincp < 0.0) - { - xincp = -xincp; - nodep = nodep + pi; - argpp = argpp - pi; - } - if ((ep < 0.0 ) || ( ep > 1.0)) - { - // printf("# error ep %f\n", ep); - satrec.error = 3; - } - } // if method = d - - /* -------------------- long period periodics ------------------ */ - if (satrec.method == 'd') - { - sinip = sin(xincp); - cosip = cos(xincp); - satrec.aycof = -0.5*j3oj2*sinip; - // sgp4fix for divide by zero for xincp = 180 deg - if (fabs(cosip+1.0) > 1.5e-12) - satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / (1.0 + cosip); - else - satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / temp4; - } - axnl = ep * cos(argpp); - temp = 1.0 / (am * (1.0 - ep * ep)); - aynl = ep* sin(argpp) + temp * satrec.aycof; - xl = mp + argpp + nodep + temp * satrec.xlcof * axnl; - - /* --------------------- solve kepler's equation --------------- */ - u = fmod(xl - nodep, twopi); - eo1 = u; - tem5 = 9999.9; - ktr = 1; - // sgp4fix for kepler iteration - // the following iteration needs better limits on corrections - while (( fabs(tem5) >= 1.0e-12) && (ktr <= 10) ) - { - sineo1 = sin(eo1); - coseo1 = cos(eo1); - tem5 = 1.0 - coseo1 * axnl - sineo1 * aynl; - tem5 = (u - aynl * coseo1 + axnl * sineo1 - eo1) / tem5; - if(fabs(tem5) >= 0.95) - tem5 = tem5 > 0.0 ? 0.95 : -0.95; - eo1 = eo1 + tem5; - ktr = ktr + 1; - } - - /* ------------- short period preliminary quantities ----------- */ - ecose = axnl*coseo1 + aynl*sineo1; - esine = axnl*sineo1 - aynl*coseo1; - el2 = axnl*axnl + aynl*aynl; - pl = am*(1.0-el2); - if (pl < 0.0) - { -// printf("# error pl %f\n", pl); - satrec.error = 4; - } - else - { - rl = am * (1.0 - ecose); - rdotl = sqrt(am) * esine/rl; - rvdotl = sqrt(pl) / rl; - betal = sqrt(1.0 - el2); - temp = esine / (1.0 + betal); - sinu = am / rl * (sineo1 - aynl - axnl * temp); - cosu = am / rl * (coseo1 - axnl + aynl * temp); - su = atan2(sinu, cosu); - sin2u = (cosu + cosu) * sinu; - cos2u = 1.0 - 2.0 * sinu * sinu; - temp = 1.0 / pl; - temp1 = 0.5 * j2 * temp; - temp2 = temp1 * temp; - - /* -------------- update for short period periodics ------------ */ - if (satrec.method == 'd') - { - cosisq = cosip * cosip; - satrec.con41 = 3.0*cosisq - 1.0; - satrec.x1mth2 = 1.0 - cosisq; - satrec.x7thm1 = 7.0*cosisq - 1.0; - } - mrt = rl * (1.0 - 1.5 * temp2 * betal * satrec.con41) + - 0.5 * temp1 * satrec.x1mth2 * cos2u; - su = su - 0.25 * temp2 * satrec.x7thm1 * sin2u; - xnode = nodep + 1.5 * temp2 * cosip * sin2u; - xinc = xincp + 1.5 * temp2 * cosip * sinip * cos2u; - mvt = rdotl - nm * temp1 * satrec.x1mth2 * sin2u / xke; - rvdot = rvdotl + nm * temp1 * (satrec.x1mth2 * cos2u + - 1.5 * satrec.con41) / xke; - - /* --------------------- orientation vectors ------------------- */ - sinsu = sin(su); - cossu = cos(su); - snod = sin(xnode); - cnod = cos(xnode); - sini = sin(xinc); - cosi = cos(xinc); - xmx = -snod * cosi; - xmy = cnod * cosi; - ux = xmx * sinsu + cnod * cossu; - uy = xmy * sinsu + snod * cossu; - uz = sini * sinsu; - vx = xmx * cossu - cnod * sinsu; - vy = xmy * cossu - snod * sinsu; - vz = sini * cossu; - - /* --------- position and velocity (in km and km/sec) ---------- */ - r[0] = (mrt * ux)* radiusearthkm; - r[1] = (mrt * uy)* radiusearthkm; - r[2] = (mrt * uz)* radiusearthkm; - v[0] = (mvt * ux + rvdot * vx) * vkmpersec; - v[1] = (mvt * uy + rvdot * vy) * vkmpersec; - v[2] = (mvt * uz + rvdot * vz) * vkmpersec; - } // if pl > 0 - - // sgp4fix for decaying satellites - if (mrt < 1.0) - { -// printf("# decay condition %11.6f \n",mrt); - satrec.error = 6; - } - - -//#include "debug7.cpp" - return satrec.error; -} // end sgp4 - - -/* ----------------------------------------------------------------------------- -* -* function gstime -* -* this function finds the greenwich sidereal time. -* -* author : david vallado 719-573-2600 1 mar 2001 -* -* inputs description range / units -* jdut1 - julian date in ut1 days from 4713 bc -* -* outputs : -* gstime - greenwich sidereal time 0 to 2pi rad -* -* locals : -* temp - temporary variable for doubles rad -* tut1 - julian centuries from the -* jan 1, 2000 12 h epoch (ut1) -* -* coupling : -* none -* -* references : -* vallado 2004, 191, eq 3-45 -* --------------------------------------------------------------------------- */ - -double gstime - ( - double jdut1 - ) - { - const double twopi = 2.0 * pi; - const double deg2rad = pi / 180.0; - double temp, tut1; - - tut1 = (jdut1 - 2451545.0) / 36525.0; - temp = -6.2e-6* tut1 * tut1 * tut1 + 0.093104 * tut1 * tut1 + - (876600.0*3600 + 8640184.812866) * tut1 + 67310.54841; // sec - temp = fmod(temp * deg2rad / 240.0, twopi); //360/86400 = 1/240, to deg, to rad - - // ------------------------ check quadrants --------------------- - if (temp < 0.0) - temp += twopi; - - return temp; - } // end gstime - -/* ----------------------------------------------------------------------------- -* -* function getgravconst -* -* this function gets constants for the propagator. note that mu is identified to -* facilitiate comparisons with newer models. the common useage is wgs72. -* -* author : david vallado 719-573-2600 21 jul 2006 -* -* inputs : -* whichconst - which set of constants to use wgs72old, wgs72, wgs84 -* -* outputs : -* tumin - minutes in one time unit -* mu - earth gravitational parameter -* radiusearthkm - radius of the earth in km -* xke - reciprocal of tumin -* j2, j3, j4 - un-normalized zonal harmonic values -* j3oj2 - j3 divided by j2 -* -* locals : -* -* coupling : -* none -* -* references : -* norad spacetrack report #3 -* vallado, crawford, hujsak, kelso 2006 - --------------------------------------------------------------------------- */ - -void getgravconst - ( - gravconsttype whichconst, - double& tumin, - double& mu, - double& radiusearthkm, - double& xke, - double& j2, - double& j3, - double& j4, - double& j3oj2 - ) - { - - switch (whichconst) - { - // -- wgs-72 low precision str#3 constants -- - case wgs72old: - mu = 398600.79964; // in km3 / s2 - radiusearthkm = 6378.135; // km - xke = 0.0743669161; - tumin = 1.0 / xke; - j2 = 0.001082616; - j3 = -0.00000253881; - j4 = -0.00000165597; - j3oj2 = j3 / j2; - break; - // ------------ wgs-72 constants ------------ - case wgs72: - mu = 398600.8; // in km3 / s2 - radiusearthkm = 6378.135; // km - xke = 60.0 / sqrt(radiusearthkm*radiusearthkm*radiusearthkm/mu); - tumin = 1.0 / xke; - j2 = 0.001082616; - j3 = -0.00000253881; - j4 = -0.00000165597; - j3oj2 = j3 / j2; - break; - case wgs84: - // ------------ wgs-84 constants ------------ - mu = 398600.5; // in km3 / s2 - radiusearthkm = 6378.137; // km - xke = 60.0 / sqrt(radiusearthkm*radiusearthkm*radiusearthkm/mu); - tumin = 1.0 / xke; - j2 = 0.00108262998905; - j3 = -0.00000253215306; - j4 = -0.00000161098761; - j3oj2 = j3 / j2; - break; - default: - fprintf(stderr,"unknown gravity option (%d)\n",whichconst); - break; - } - - } // end getgravconst - - - - - +/* ---------------------------------------------------------------- +* +* sgp4unit.cpp +* +* this file contains the sgp4 procedures for analytical propagation +* of a satellite. the code was originally released in the 1980 and 1986 +* spacetrack papers. a detailed discussion of the theory and history +* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, +* and kelso. +* +* companion code for +* fundamentals of astrodynamics and applications +* 2007 +* by david vallado +* +* (w) 719-573-2600, email dvallado@agi.com +* +* current : +* 16 nov 07 david vallado +* misc fixes for better compliance +* changes : +* 20 apr 07 david vallado +* misc fixes for constants +* 11 aug 06 david vallado +* chg lyddane choice back to strn3, constants, misc doc +* 15 dec 05 david vallado +* misc fixes +* 26 jul 05 david vallado +* fixes for paper +* note that each fix is preceded by a +* comment with "sgp4fix" and an explanation of +* what was changed +* 10 aug 04 david vallado +* 2nd printing baseline working +* 14 may 01 david vallado +* 2nd edition baseline +* 80 norad +* original baseline +* ---------------------------------------------------------------- */ + +#include "sgp4unit.h" + +const char help = 'n'; +FILE *dbgfile; + +#define pi 3.14159265358979323846 + + +/* ----------- local functions - only ever used internally by sgp4 ---------- */ +static void dpper + ( + double e3, double ee2, double peo, double pgho, double pho, + double pinco, double plo, double se2, double se3, double sgh2, + double sgh3, double sgh4, double sh2, double sh3, double si2, + double si3, double sl2, double sl3, double sl4, double t, + double xgh2, double xgh3, double xgh4, double xh2, double xh3, + double xi2, double xi3, double xl2, double xl3, double xl4, + double zmol, double zmos, double inclo, + char init, + double& ep, double& inclp, double& nodep, double& argpp, double& mp + ); + +static void dscom + ( + double epoch, double ep, double argpp, double tc, double inclp, + double nodep, double np, + double& snodm, double& cnodm, double& sinim, double& cosim, double& sinomm, + double& cosomm,double& day, double& e3, double& ee2, double& em, + double& emsq, double& gam, double& peo, double& pgho, double& pho, + double& pinco, double& plo, double& rtemsq, double& se2, double& se3, + double& sgh2, double& sgh3, double& sgh4, double& sh2, double& sh3, + double& si2, double& si3, double& sl2, double& sl3, double& sl4, + double& s1, double& s2, double& s3, double& s4, double& s5, + double& s6, double& s7, double& ss1, double& ss2, double& ss3, + double& ss4, double& ss5, double& ss6, double& ss7, double& sz1, + double& sz2, double& sz3, double& sz11, double& sz12, double& sz13, + double& sz21, double& sz22, double& sz23, double& sz31, double& sz32, + double& sz33, double& xgh2, double& xgh3, double& xgh4, double& xh2, + double& xh3, double& xi2, double& xi3, double& xl2, double& xl3, + double& xl4, double& nm, double& z1, double& z2, double& z3, + double& z11, double& z12, double& z13, double& z21, double& z22, + double& z23, double& z31, double& z32, double& z33, double& zmol, + double& zmos + ); + +static void dsinit + ( + gravconsttype whichconst, + double cosim, double emsq, double argpo, double s1, double s2, + double s3, double s4, double s5, double sinim, double ss1, + double ss2, double ss3, double ss4, double ss5, double sz1, + double sz3, double sz11, double sz13, double sz21, double sz23, + double sz31, double sz33, double t, double tc, double gsto, + double mo, double mdot, double no, double nodeo, double nodedot, + double xpidot, double z1, double z3, double z11, double z13, + double z21, double z23, double z31, double z33, double ecco, + double eccsq, double& em, double& argpm, double& inclm, double& mm, + double& nm, double& nodem, + int& irez, + double& atime, double& d2201, double& d2211, double& d3210, double& d3222, + double& d4410, double& d4422, double& d5220, double& d5232, double& d5421, + double& d5433, double& dedt, double& didt, double& dmdt, double& dndt, + double& dnodt, double& domdt, double& del1, double& del2, double& del3, + double& xfact, double& xlamo, double& xli, double& xni + ); + +static void dspace + ( + int irez, + double d2201, double d2211, double d3210, double d3222, double d4410, + double d4422, double d5220, double d5232, double d5421, double d5433, + double dedt, double del1, double del2, double del3, double didt, + double dmdt, double dnodt, double domdt, double argpo, double argpdot, + double t, double tc, double gsto, double xfact, double xlamo, + double no, + double& atime, double& em, double& argpm, double& inclm, double& xli, + double& mm, double& xni, double& nodem, double& dndt, double& nm + ); + +static void initl + ( + int satn, gravconsttype whichconst, + double ecco, double epoch, double inclo, double& no, + char& method, + double& ainv, double& ao, double& con41, double& con42, double& cosio, + double& cosio2,double& eccsq, double& omeosq, double& posq, + double& rp, double& rteosq,double& sinio , double& gsto + ); + +/* ----------------------------------------------------------------------------- +* +* procedure dpper +* +* this procedure provides deep space long period periodic contributions +* to the mean elements. by design, these periodics are zero at epoch. +* this used to be dscom which included initialization, but it's really a +* recurring function. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* e3 - +* ee2 - +* peo - +* pgho - +* pho - +* pinco - +* plo - +* se2 , se3 , sgh2, sgh3, sgh4, sh2, sh3, si2, si3, sl2, sl3, sl4 - +* t - +* xh2, xh3, xi2, xi3, xl2, xl3, xl4 - +* zmol - +* zmos - +* ep - eccentricity 0.0 - 1.0 +* inclo - inclination - needed for lyddane modification +* nodep - right ascension of ascending node +* argpp - argument of perigee +* mp - mean anomaly +* +* outputs : +* ep - eccentricity 0.0 - 1.0 +* inclp - inclination +* nodep - right ascension of ascending node +* argpp - argument of perigee +* mp - mean anomaly +* +* locals : +* alfdp - +* betdp - +* cosip , sinip , cosop , sinop , +* dalf - +* dbet - +* dls - +* f2, f3 - +* pe - +* pgh - +* ph - +* pinc - +* pl - +* sel , ses , sghl , sghs , shl , shs , sil , sinzf , sis , +* sll , sls +* xls - +* xnoh - +* zf - +* zm - +* +* coupling : +* none. +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dpper + ( + double e3, double ee2, double peo, double pgho, double pho, + double pinco, double plo, double se2, double se3, double sgh2, + double sgh3, double sgh4, double sh2, double sh3, double si2, + double si3, double sl2, double sl3, double sl4, double t, + double xgh2, double xgh3, double xgh4, double xh2, double xh3, + double xi2, double xi3, double xl2, double xl3, double xl4, + double zmol, double zmos, double inclo, + char init, + double& ep, double& inclp, double& nodep, double& argpp, double& mp + ) +{ + /* --------------------- local variables ------------------------ */ + const double twopi = 2.0 * pi; + double alfdp, betdp, cosip, cosop, dalf, dbet, dls, + f2, f3, pe, pgh, ph, pinc, pl , + sel, ses, sghl, sghs, shll, shs, sil, + sinip, sinop, sinzf, sis, sll, sls, xls, + xnoh, zf, zm, zel, zes, znl, zns; + + /* ---------------------- constants ----------------------------- */ + zns = 1.19459e-5; + zes = 0.01675; + znl = 1.5835218e-4; + zel = 0.05490; + + /* --------------- calculate time varying periodics ----------- */ + zm = zmos + zns * t; + // be sure that the initial call has time set to zero + if (init == 'y') + zm = zmos; + zf = zm + 2.0 * zes * sin(zm); + sinzf = sin(zf); + f2 = 0.5 * sinzf * sinzf - 0.25; + f3 = -0.5 * sinzf * cos(zf); + ses = se2* f2 + se3 * f3; + sis = si2 * f2 + si3 * f3; + sls = sl2 * f2 + sl3 * f3 + sl4 * sinzf; + sghs = sgh2 * f2 + sgh3 * f3 + sgh4 * sinzf; + shs = sh2 * f2 + sh3 * f3; + zm = zmol + znl * t; + if (init == 'y') + zm = zmol; + zf = zm + 2.0 * zel * sin(zm); + sinzf = sin(zf); + f2 = 0.5 * sinzf * sinzf - 0.25; + f3 = -0.5 * sinzf * cos(zf); + sel = ee2 * f2 + e3 * f3; + sil = xi2 * f2 + xi3 * f3; + sll = xl2 * f2 + xl3 * f3 + xl4 * sinzf; + sghl = xgh2 * f2 + xgh3 * f3 + xgh4 * sinzf; + shll = xh2 * f2 + xh3 * f3; + pe = ses + sel; + pinc = sis + sil; + pl = sls + sll; + pgh = sghs + sghl; + ph = shs + shll; + + if (init == 'n') + { + pe = pe - peo; + pinc = pinc - pinco; + pl = pl - plo; + pgh = pgh - pgho; + ph = ph - pho; + inclp = inclp + pinc; + ep = ep + pe; + sinip = sin(inclp); + cosip = cos(inclp); + + /* ----------------- apply periodics directly ------------ */ + // sgp4fix for lyddane choice + // strn3 used original inclination - this is technically feasible + // gsfc used perturbed inclination - also technically feasible + // probably best to readjust the 0.2 limit value and limit discontinuity + // 0.2 rad = 11.45916 deg + // use next line for original strn3 approach and original inclination + // if (inclo >= 0.2) + // use next line for gsfc version and perturbed inclination + if (inclp >= 0.2) + { + ph = ph / sinip; + pgh = pgh - cosip * ph; + argpp = argpp + pgh; + nodep = nodep + ph; + mp = mp + pl; + } + else + { + /* ---- apply periodics with lyddane modification ---- */ + sinop = sin(nodep); + cosop = cos(nodep); + alfdp = sinip * sinop; + betdp = sinip * cosop; + dalf = ph * cosop + pinc * cosip * sinop; + dbet = -ph * sinop + pinc * cosip * cosop; + alfdp = alfdp + dalf; + betdp = betdp + dbet; + nodep = fmod(nodep, twopi); + // sgp4fix for afspc written intrinsic functions + // nodep used without a trigonometric function ahead + if (nodep < 0.0) + nodep = nodep + twopi; + xls = mp + argpp + cosip * nodep; + dls = pl + pgh - pinc * nodep * sinip; + xls = xls + dls; + xnoh = nodep; + nodep = atan2(alfdp, betdp); + // sgp4fix for afspc written intrinsic functions + // nodep used without a trigonometric function ahead + if (nodep < 0.0) + nodep = nodep + twopi; + if (fabs(xnoh - nodep) > pi){ + if (nodep < xnoh) + nodep = nodep + twopi; + else + nodep = nodep - twopi; + } + mp = mp + pl; + argpp = xls - mp - cosip * nodep; + } + } // if init == 'n' + +//#include "debug1.cpp" +} // end dpper + +/*----------------------------------------------------------------------------- +* +* procedure dscom +* +* this procedure provides deep space common items used by both the secular +* and periodics subroutines. input is provided as shown. this routine +* used to be called dpper, but the functions inside weren't well organized. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* epoch - +* ep - eccentricity +* argpp - argument of perigee +* tc - +* inclp - inclination +* nodep - right ascension of ascending node +* np - mean motion +* +* outputs : +* sinim , cosim , sinomm , cosomm , snodm , cnodm +* day - +* e3 - +* ee2 - +* em - eccentricity +* emsq - eccentricity squared +* gam - +* peo - +* pgho - +* pho - +* pinco - +* plo - +* rtemsq - +* se2, se3 - +* sgh2, sgh3, sgh4 - +* sh2, sh3, si2, si3, sl2, sl3, sl4 - +* s1, s2, s3, s4, s5, s6, s7 - +* ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3 - +* sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33 - +* xgh2, xgh3, xgh4, xh2, xh3, xi2, xi3, xl2, xl3, xl4 - +* nm - mean motion +* z1, z2, z3, z11, z12, z13, z21, z22, z23, z31, z32, z33 - +* zmol - +* zmos - +* +* locals : +* a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 - +* betasq - +* cc - +* ctem, stem - +* x1, x2, x3, x4, x5, x6, x7, x8 - +* xnodce - +* xnoi - +* zcosg , zsing , zcosgl , zsingl , zcosh , zsinh , zcoshl , zsinhl , +* zcosi , zsini , zcosil , zsinil , +* zx - +* zy - +* +* coupling : +* none. +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dscom + ( + double epoch, double ep, double argpp, double tc, double inclp, + double nodep, double np, + double& snodm, double& cnodm, double& sinim, double& cosim, double& sinomm, + double& cosomm,double& day, double& e3, double& ee2, double& em, + double& emsq, double& gam, double& peo, double& pgho, double& pho, + double& pinco, double& plo, double& rtemsq, double& se2, double& se3, + double& sgh2, double& sgh3, double& sgh4, double& sh2, double& sh3, + double& si2, double& si3, double& sl2, double& sl3, double& sl4, + double& s1, double& s2, double& s3, double& s4, double& s5, + double& s6, double& s7, double& ss1, double& ss2, double& ss3, + double& ss4, double& ss5, double& ss6, double& ss7, double& sz1, + double& sz2, double& sz3, double& sz11, double& sz12, double& sz13, + double& sz21, double& sz22, double& sz23, double& sz31, double& sz32, + double& sz33, double& xgh2, double& xgh3, double& xgh4, double& xh2, + double& xh3, double& xi2, double& xi3, double& xl2, double& xl3, + double& xl4, double& nm, double& z1, double& z2, double& z3, + double& z11, double& z12, double& z13, double& z21, double& z22, + double& z23, double& z31, double& z32, double& z33, double& zmol, + double& zmos + ) +{ + /* -------------------------- constants ------------------------- */ + const double zes = 0.01675; + const double zel = 0.05490; + const double c1ss = 2.9864797e-6; + const double c1l = 4.7968065e-7; + const double zsinis = 0.39785416; + const double zcosis = 0.91744867; + const double zcosgs = 0.1945905; + const double zsings = -0.98088458; + const double twopi = 2.0 * pi; + + /* --------------------- local variables ------------------------ */ + int lsflg; + double a1 , a2 , a3 , a4 , a5 , a6 , a7 , + a8 , a9 , a10 , betasq, cc , ctem , stem , + x1 , x2 , x3 , x4 , x5 , x6 , x7 , + x8 , xnodce, xnoi , zcosg , zcosgl, zcosh , zcoshl, + zcosi , zcosil, zsing , zsingl, zsinh , zsinhl, zsini , + zsinil, zx , zy; + + nm = np; + em = ep; + snodm = sin(nodep); + cnodm = cos(nodep); + sinomm = sin(argpp); + cosomm = cos(argpp); + sinim = sin(inclp); + cosim = cos(inclp); + emsq = em * em; + betasq = 1.0 - emsq; + rtemsq = sqrt(betasq); + + /* ----------------- initialize lunar solar terms --------------- */ + peo = 0.0; + pinco = 0.0; + plo = 0.0; + pgho = 0.0; + pho = 0.0; + day = epoch + 18261.5 + tc / 1440.0; + xnodce = fmod(4.5236020 - 9.2422029e-4 * day, twopi); + stem = sin(xnodce); + ctem = cos(xnodce); + zcosil = 0.91375164 - 0.03568096 * ctem; + zsinil = sqrt(1.0 - zcosil * zcosil); + zsinhl = 0.089683511 * stem / zsinil; + zcoshl = sqrt(1.0 - zsinhl * zsinhl); + gam = 5.8351514 + 0.0019443680 * day; + zx = 0.39785416 * stem / zsinil; + zy = zcoshl * ctem + 0.91744867 * zsinhl * stem; + zx = atan2(zx, zy); + zx = gam + zx - xnodce; + zcosgl = cos(zx); + zsingl = sin(zx); + + /* ------------------------- do solar terms --------------------- */ + zcosg = zcosgs; + zsing = zsings; + zcosi = zcosis; + zsini = zsinis; + zcosh = cnodm; + zsinh = snodm; + cc = c1ss; + xnoi = 1.0 / nm; + + for (lsflg = 1; lsflg <= 2; lsflg++) + { + a1 = zcosg * zcosh + zsing * zcosi * zsinh; + a3 = -zsing * zcosh + zcosg * zcosi * zsinh; + a7 = -zcosg * zsinh + zsing * zcosi * zcosh; + a8 = zsing * zsini; + a9 = zsing * zsinh + zcosg * zcosi * zcosh; + a10 = zcosg * zsini; + a2 = cosim * a7 + sinim * a8; + a4 = cosim * a9 + sinim * a10; + a5 = -sinim * a7 + cosim * a8; + a6 = -sinim * a9 + cosim * a10; + + x1 = a1 * cosomm + a2 * sinomm; + x2 = a3 * cosomm + a4 * sinomm; + x3 = -a1 * sinomm + a2 * cosomm; + x4 = -a3 * sinomm + a4 * cosomm; + x5 = a5 * sinomm; + x6 = a6 * sinomm; + x7 = a5 * cosomm; + x8 = a6 * cosomm; + + z31 = 12.0 * x1 * x1 - 3.0 * x3 * x3; + z32 = 24.0 * x1 * x2 - 6.0 * x3 * x4; + z33 = 12.0 * x2 * x2 - 3.0 * x4 * x4; + z1 = 3.0 * (a1 * a1 + a2 * a2) + z31 * emsq; + z2 = 6.0 * (a1 * a3 + a2 * a4) + z32 * emsq; + z3 = 3.0 * (a3 * a3 + a4 * a4) + z33 * emsq; + z11 = -6.0 * a1 * a5 + emsq * (-24.0 * x1 * x7-6.0 * x3 * x5); + z12 = -6.0 * (a1 * a6 + a3 * a5) + emsq * + (-24.0 * (x2 * x7 + x1 * x8) - 6.0 * (x3 * x6 + x4 * x5)); + z13 = -6.0 * a3 * a6 + emsq * (-24.0 * x2 * x8 - 6.0 * x4 * x6); + z21 = 6.0 * a2 * a5 + emsq * (24.0 * x1 * x5 - 6.0 * x3 * x7); + z22 = 6.0 * (a4 * a5 + a2 * a6) + emsq * + (24.0 * (x2 * x5 + x1 * x6) - 6.0 * (x4 * x7 + x3 * x8)); + z23 = 6.0 * a4 * a6 + emsq * (24.0 * x2 * x6 - 6.0 * x4 * x8); + z1 = z1 + z1 + betasq * z31; + z2 = z2 + z2 + betasq * z32; + z3 = z3 + z3 + betasq * z33; + s3 = cc * xnoi; + s2 = -0.5 * s3 / rtemsq; + s4 = s3 * rtemsq; + s1 = -15.0 * em * s4; + s5 = x1 * x3 + x2 * x4; + s6 = x2 * x3 + x1 * x4; + s7 = x2 * x4 - x1 * x3; + + /* ----------------------- do lunar terms ------------------- */ + if (lsflg == 1) + { + ss1 = s1; + ss2 = s2; + ss3 = s3; + ss4 = s4; + ss5 = s5; + ss6 = s6; + ss7 = s7; + sz1 = z1; + sz2 = z2; + sz3 = z3; + sz11 = z11; + sz12 = z12; + sz13 = z13; + sz21 = z21; + sz22 = z22; + sz23 = z23; + sz31 = z31; + sz32 = z32; + sz33 = z33; + zcosg = zcosgl; + zsing = zsingl; + zcosi = zcosil; + zsini = zsinil; + zcosh = zcoshl * cnodm + zsinhl * snodm; + zsinh = snodm * zcoshl - cnodm * zsinhl; + cc = c1l; + } + } + + zmol = fmod(4.7199672 + 0.22997150 * day - gam, twopi); + zmos = fmod(6.2565837 + 0.017201977 * day, twopi); + + /* ------------------------ do solar terms ---------------------- */ + se2 = 2.0 * ss1 * ss6; + se3 = 2.0 * ss1 * ss7; + si2 = 2.0 * ss2 * sz12; + si3 = 2.0 * ss2 * (sz13 - sz11); + sl2 = -2.0 * ss3 * sz2; + sl3 = -2.0 * ss3 * (sz3 - sz1); + sl4 = -2.0 * ss3 * (-21.0 - 9.0 * emsq) * zes; + sgh2 = 2.0 * ss4 * sz32; + sgh3 = 2.0 * ss4 * (sz33 - sz31); + sgh4 = -18.0 * ss4 * zes; + sh2 = -2.0 * ss2 * sz22; + sh3 = -2.0 * ss2 * (sz23 - sz21); + + /* ------------------------ do lunar terms ---------------------- */ + ee2 = 2.0 * s1 * s6; + e3 = 2.0 * s1 * s7; + xi2 = 2.0 * s2 * z12; + xi3 = 2.0 * s2 * (z13 - z11); + xl2 = -2.0 * s3 * z2; + xl3 = -2.0 * s3 * (z3 - z1); + xl4 = -2.0 * s3 * (-21.0 - 9.0 * emsq) * zel; + xgh2 = 2.0 * s4 * z32; + xgh3 = 2.0 * s4 * (z33 - z31); + xgh4 = -18.0 * s4 * zel; + xh2 = -2.0 * s2 * z22; + xh3 = -2.0 * s2 * (z23 - z21); + +//#include "debug2.cpp" +} // end dscom + +/*----------------------------------------------------------------------------- +* +* procedure dsinit +* +* this procedure provides deep space contributions to mean motion dot due +* to geopotential resonance with half day and one day orbits. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* cosim, sinim- +* emsq - eccentricity squared +* argpo - argument of perigee +* s1, s2, s3, s4, s5 - +* ss1, ss2, ss3, ss4, ss5 - +* sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33 - +* t - time +* tc - +* gsto - greenwich sidereal time rad +* mo - mean anomaly +* mdot - mean anomaly dot (rate) +* no - mean motion +* nodeo - right ascension of ascending node +* nodedot - right ascension of ascending node dot (rate) +* xpidot - +* z1, z3, z11, z13, z21, z23, z31, z33 - +* eccm - eccentricity +* argpm - argument of perigee +* inclm - inclination +* mm - mean anomaly +* xn - mean motion +* nodem - right ascension of ascending node +* +* outputs : +* em - eccentricity +* argpm - argument of perigee +* inclm - inclination +* mm - mean anomaly +* nm - mean motion +* nodem - right ascension of ascending node +* irez - flag for resonance 0-none, 1-one day, 2-half day +* atime - +* d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 - +* dedt - +* didt - +* dmdt - +* dndt - +* dnodt - +* domdt - +* del1, del2, del3 - +* ses , sghl , sghs , sgs , shl , shs , sis , sls +* theta - +* xfact - +* xlamo - +* xli - +* xni +* +* locals : +* ainv2 - +* aonv - +* cosisq - +* eoc - +* f220, f221, f311, f321, f322, f330, f441, f442, f522, f523, f542, f543 - +* g200, g201, g211, g300, g310, g322, g410, g422, g520, g521, g532, g533 - +* sini2 - +* temp - +* temp1 - +* theta - +* xno2 - +* +* coupling : +* getgravconst +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dsinit + ( + gravconsttype whichconst, + double cosim, double emsq, double argpo, double s1, double s2, + double s3, double s4, double s5, double sinim, double ss1, + double ss2, double ss3, double ss4, double ss5, double sz1, + double sz3, double sz11, double sz13, double sz21, double sz23, + double sz31, double sz33, double t, double tc, double gsto, + double mo, double mdot, double no, double nodeo, double nodedot, + double xpidot, double z1, double z3, double z11, double z13, + double z21, double z23, double z31, double z33, double ecco, + double eccsq, double& em, double& argpm, double& inclm, double& mm, + double& nm, double& nodem, + int& irez, + double& atime, double& d2201, double& d2211, double& d3210, double& d3222, + double& d4410, double& d4422, double& d5220, double& d5232, double& d5421, + double& d5433, double& dedt, double& didt, double& dmdt, double& dndt, + double& dnodt, double& domdt, double& del1, double& del2, double& del3, + double& xfact, double& xlamo, double& xli, double& xni + ) +{ + /* --------------------- local variables ------------------------ */ + const double twopi = 2.0 * pi; + + double ainv2 , aonv=0.0, cosisq, eoc, f220 , f221 , f311 , + f321 , f322 , f330 , f441 , f442 , f522 , f523 , + f542 , f543 , g200 , g201 , g211 , g300 , g310 , + g322 , g410 , g422 , g520 , g521 , g532 , g533 , + ses , sgs , sghl , sghs , shs , shll , sis , + sini2 , sls , temp , temp1 , theta , xno2 , q22 , + q31 , q33 , root22, root44, root54, rptim , root32, + root52, x2o3 , xke , znl , emo , zns , emsqo, + tumin, mu, radiusearthkm, j2, j3, j4, j3oj2; + + q22 = 1.7891679e-6; + q31 = 2.1460748e-6; + q33 = 2.2123015e-7; + root22 = 1.7891679e-6; + root44 = 7.3636953e-9; + root54 = 2.1765803e-9; + rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec + root32 = 3.7393792e-7; + root52 = 1.1428639e-7; + x2o3 = 2.0 / 3.0; + znl = 1.5835218e-4; + zns = 1.19459e-5; + + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + + /* -------------------- deep space initialization ------------ */ + irez = 0; + if ((nm < 0.0052359877) && (nm > 0.0034906585)) + irez = 1; + if ((nm >= 8.26e-3) && (nm <= 9.24e-3) && (em >= 0.5)) + irez = 2; + + /* ------------------------ do solar terms ------------------- */ + ses = ss1 * zns * ss5; + sis = ss2 * zns * (sz11 + sz13); + sls = -zns * ss3 * (sz1 + sz3 - 14.0 - 6.0 * emsq); + sghs = ss4 * zns * (sz31 + sz33 - 6.0); + shs = -zns * ss2 * (sz21 + sz23); + // sgp4fix for 180 deg incl + if ((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2)) + shs = 0.0; + if (sinim != 0.0) + shs = shs / sinim; + sgs = sghs - cosim * shs; + + /* ------------------------- do lunar terms ------------------ */ + dedt = ses + s1 * znl * s5; + didt = sis + s2 * znl * (z11 + z13); + dmdt = sls - znl * s3 * (z1 + z3 - 14.0 - 6.0 * emsq); + sghl = s4 * znl * (z31 + z33 - 6.0); + shll = -znl * s2 * (z21 + z23); + // sgp4fix for 180 deg incl + if ((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2)) + shll = 0.0; + domdt = sgs + sghl; + dnodt = shs; + if (sinim != 0.0) + { + domdt = domdt - cosim / sinim * shll; + dnodt = dnodt + shll / sinim; + } + + /* ----------- calculate deep space resonance effects -------- */ + dndt = 0.0; + theta = fmod(gsto + tc * rptim, twopi); + em = em + dedt * t; + inclm = inclm + didt * t; + argpm = argpm + domdt * t; + nodem = nodem + dnodt * t; + mm = mm + dmdt * t; + // sgp4fix for negative inclinations + // the following if statement should be commented out + //if (inclm < 0.0) + // { + // inclm = -inclm; + // argpm = argpm - pi; + // nodem = nodem + pi; + // } + + /* -------------- initialize the resonance terms ------------- */ + if (irez != 0) + { + aonv = pow(nm / xke, x2o3); + + /* ---------- geopotential resonance for 12 hour orbits ------ */ + if (irez == 2) + { + cosisq = cosim * cosim; + emo = em; + em = ecco; + emsqo = emsq; + emsq = eccsq; + eoc = em * emsq; + g201 = -0.306 - (em - 0.64) * 0.440; + + if (em <= 0.65) + { + g211 = 3.616 - 13.2470 * em + 16.2900 * emsq; + g310 = -19.302 + 117.3900 * em - 228.4190 * emsq + 156.5910 * eoc; + g322 = -18.9068 + 109.7927 * em - 214.6334 * emsq + 146.5816 * eoc; + g410 = -41.122 + 242.6940 * em - 471.0940 * emsq + 313.9530 * eoc; + g422 = -146.407 + 841.8800 * em - 1629.014 * emsq + 1083.4350 * eoc; + g520 = -532.114 + 3017.977 * em - 5740.032 * emsq + 3708.2760 * eoc; + } + else + { + g211 = -72.099 + 331.819 * em - 508.738 * emsq + 266.724 * eoc; + g310 = -346.844 + 1582.851 * em - 2415.925 * emsq + 1246.113 * eoc; + g322 = -342.585 + 1554.908 * em - 2366.899 * emsq + 1215.972 * eoc; + g410 = -1052.797 + 4758.686 * em - 7193.992 * emsq + 3651.957 * eoc; + g422 = -3581.690 + 16178.110 * em - 24462.770 * emsq + 12422.520 * eoc; + if (em > 0.715) + g520 =-5149.66 + 29936.92 * em - 54087.36 * emsq + 31324.56 * eoc; + else + g520 = 1464.74 - 4664.75 * em + 3763.64 * emsq; + } + if (em < 0.7) + { + g533 = -919.22770 + 4988.6100 * em - 9064.7700 * emsq + 5542.21 * eoc; + g521 = -822.71072 + 4568.6173 * em - 8491.4146 * emsq + 5337.524 * eoc; + g532 = -853.66600 + 4690.2500 * em - 8624.7700 * emsq + 5341.4 * eoc; + } + else + { + g533 =-37995.780 + 161616.52 * em - 229838.20 * emsq + 109377.94 * eoc; + g521 =-51752.104 + 218913.95 * em - 309468.16 * emsq + 146349.42 * eoc; + g532 =-40023.880 + 170470.89 * em - 242699.48 * emsq + 115605.82 * eoc; + } + + sini2= sinim * sinim; + f220 = 0.75 * (1.0 + 2.0 * cosim+cosisq); + f221 = 1.5 * sini2; + f321 = 1.875 * sinim * (1.0 - 2.0 * cosim - 3.0 * cosisq); + f322 = -1.875 * sinim * (1.0 + 2.0 * cosim - 3.0 * cosisq); + f441 = 35.0 * sini2 * f220; + f442 = 39.3750 * sini2 * sini2; + f522 = 9.84375 * sinim * (sini2 * (1.0 - 2.0 * cosim- 5.0 * cosisq) + + 0.33333333 * (-2.0 + 4.0 * cosim + 6.0 * cosisq) ); + f523 = sinim * (4.92187512 * sini2 * (-2.0 - 4.0 * cosim + + 10.0 * cosisq) + 6.56250012 * (1.0+2.0 * cosim - 3.0 * cosisq)); + f542 = 29.53125 * sinim * (2.0 - 8.0 * cosim+cosisq * + (-12.0 + 8.0 * cosim + 10.0 * cosisq)); + f543 = 29.53125 * sinim * (-2.0 - 8.0 * cosim+cosisq * + (12.0 + 8.0 * cosim - 10.0 * cosisq)); + xno2 = nm * nm; + ainv2 = aonv * aonv; + temp1 = 3.0 * xno2 * ainv2; + temp = temp1 * root22; + d2201 = temp * f220 * g201; + d2211 = temp * f221 * g211; + temp1 = temp1 * aonv; + temp = temp1 * root32; + d3210 = temp * f321 * g310; + d3222 = temp * f322 * g322; + temp1 = temp1 * aonv; + temp = 2.0 * temp1 * root44; + d4410 = temp * f441 * g410; + d4422 = temp * f442 * g422; + temp1 = temp1 * aonv; + temp = temp1 * root52; + d5220 = temp * f522 * g520; + d5232 = temp * f523 * g532; + temp = 2.0 * temp1 * root54; + d5421 = temp * f542 * g521; + d5433 = temp * f543 * g533; + xlamo = fmod(mo + nodeo + nodeo-theta - theta, twopi); + xfact = mdot + dmdt + 2.0 * (nodedot + dnodt - rptim) - no; + em = emo; + emsq = emsqo; + } + + /* ---------------- synchronous resonance terms -------------- */ + if (irez == 1) + { + g200 = 1.0 + emsq * (-2.5 + 0.8125 * emsq); + g310 = 1.0 + 2.0 * emsq; + g300 = 1.0 + emsq * (-6.0 + 6.60937 * emsq); + f220 = 0.75 * (1.0 + cosim) * (1.0 + cosim); + f311 = 0.9375 * sinim * sinim * (1.0 + 3.0 * cosim) - 0.75 * (1.0 + cosim); + f330 = 1.0 + cosim; + f330 = 1.875 * f330 * f330 * f330; + del1 = 3.0 * nm * nm * aonv * aonv; + del2 = 2.0 * del1 * f220 * g200 * q22; + del3 = 3.0 * del1 * f330 * g300 * q33 * aonv; + del1 = del1 * f311 * g310 * q31 * aonv; + xlamo = fmod(mo + nodeo + argpo - theta, twopi); + xfact = mdot + xpidot - rptim + dmdt + domdt + dnodt - no; + } + + /* ------------ for sgp4, initialize the integrator ---------- */ + xli = xlamo; + xni = no; + atime = 0.0; + nm = no + dndt; + } + +//#include "debug3.cpp" +} // end dsinit + +/*----------------------------------------------------------------------------- +* +* procedure dspace +* +* this procedure provides deep space contributions to mean elements for +* perturbing third body. these effects have been averaged over one +* revolution of the sun and moon. for earth resonance effects, the +* effects have been averaged over no revolutions of the satellite. +* (mean motion) +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 - +* dedt - +* del1, del2, del3 - +* didt - +* dmdt - +* dnodt - +* domdt - +* irez - flag for resonance 0-none, 1-one day, 2-half day +* argpo - argument of perigee +* argpdot - argument of perigee dot (rate) +* t - time +* tc - +* gsto - gst +* xfact - +* xlamo - +* no - mean motion +* atime - +* em - eccentricity +* ft - +* argpm - argument of perigee +* inclm - inclination +* xli - +* mm - mean anomaly +* xni - mean motion +* nodem - right ascension of ascending node +* +* outputs : +* atime - +* em - eccentricity +* argpm - argument of perigee +* inclm - inclination +* xli - +* mm - mean anomaly +* xni - +* nodem - right ascension of ascending node +* dndt - +* nm - mean motion +* +* locals : +* delt - +* ft - +* theta - +* x2li - +* x2omi - +* xl - +* xldot - +* xnddt - +* xndt - +* xomi - +* +* coupling : +* none - +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dspace + ( + int irez, + double d2201, double d2211, double d3210, double d3222, double d4410, + double d4422, double d5220, double d5232, double d5421, double d5433, + double dedt, double del1, double del2, double del3, double didt, + double dmdt, double dnodt, double domdt, double argpo, double argpdot, + double t, double tc, double gsto, double xfact, double xlamo, + double no, + double& atime, double& em, double& argpm, double& inclm, double& xli, + double& mm, double& xni, double& nodem, double& dndt, double& nm + ) +{ + const double twopi = 2.0 * pi; + int iretn , iret; + double delt, ft, theta, x2li, x2omi, xl, xldot , xnddt, xndt, xomi, g22, g32, + g44, g52, g54, fasx2, fasx4, fasx6, rptim , step2, stepn , stepp; + + ft = 0.0; + fasx2 = 0.13130908; + fasx4 = 2.8843198; + fasx6 = 0.37448087; + g22 = 5.7686396; + g32 = 0.95240898; + g44 = 1.8014998; + g52 = 1.0508330; + g54 = 4.4108898; + rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec + stepp = 720.0; + stepn = -720.0; + step2 = 259200.0; + + /* ----------- calculate deep space resonance effects ----------- */ + dndt = 0.0; + theta = fmod(gsto + tc * rptim, twopi); + em = em + dedt * t; + + inclm = inclm + didt * t; + argpm = argpm + domdt * t; + nodem = nodem + dnodt * t; + mm = mm + dmdt * t; + + // sgp4fix for negative inclinations + // the following if statement should be commented out + // if (inclm < 0.0) + // { + // inclm = -inclm; + // argpm = argpm - pi; + // nodem = nodem + pi; + // } + + /* - update resonances : numerical (euler-maclaurin) integration - */ + /* ------------------------- epoch restart ---------------------- */ + // sgp4fix for propagator problems + // the following integration works for negative time steps and periods + // the specific changes are unknown because the original code was so convoluted + + ft = 0.0; + atime = 0.0; + if (irez != 0) + { + if ((atime == 0.0) || ((t >= 0.0) && (atime < 0.0)) || + ((t < 0.0) && (atime >= 0.0))) + { + if (t >= 0.0) + delt = stepp; + else + delt = stepn; + atime = 0.0; + xni = no; + xli = xlamo; + } + iretn = 381; // added for do loop + iret = 0; // added for loop + while (iretn == 381) + { + if ((fabs(t) < fabs(atime)) || (iret == 351)) + { + if (t >= 0.0) + delt = stepn; + else + delt = stepp; + iret = 351; + iretn = 381; + } + else + { + if (t > 0.0) // error if prev if has atime:=0.0 and t:=0.0 (ge) + delt = stepp; + else + delt = stepn; + if (fabs(t - atime) >= stepp) + { + iret = 0; + iretn = 381; + } + else + { + ft = t - atime; + iretn = 0; + } + } + + /* ------------------- dot terms calculated ------------- */ + /* ----------- near - synchronous resonance terms ------- */ + if (irez != 2) + { + xndt = del1 * sin(xli - fasx2) + del2 * sin(2.0 * (xli - fasx4)) + + del3 * sin(3.0 * (xli - fasx6)); + xldot = xni + xfact; + xnddt = del1 * cos(xli - fasx2) + + 2.0 * del2 * cos(2.0 * (xli - fasx4)) + + 3.0 * del3 * cos(3.0 * (xli - fasx6)); + xnddt = xnddt * xldot; + } + else + { + /* --------- near - half-day resonance terms -------- */ + xomi = argpo + argpdot * atime; + x2omi = xomi + xomi; + x2li = xli + xli; + xndt = d2201 * sin(x2omi + xli - g22) + d2211 * sin(xli - g22) + + d3210 * sin(xomi + xli - g32) + d3222 * sin(-xomi + xli - g32)+ + d4410 * sin(x2omi + x2li - g44)+ d4422 * sin(x2li - g44) + + d5220 * sin(xomi + xli - g52) + d5232 * sin(-xomi + xli - g52)+ + d5421 * sin(xomi + x2li - g54) + d5433 * sin(-xomi + x2li - g54); + xldot = xni + xfact; + xnddt = d2201 * cos(x2omi + xli - g22) + d2211 * cos(xli - g22) + + d3210 * cos(xomi + xli - g32) + d3222 * cos(-xomi + xli - g32) + + d5220 * cos(xomi + xli - g52) + d5232 * cos(-xomi + xli - g52) + + 2.0 * (d4410 * cos(x2omi + x2li - g44) + + d4422 * cos(x2li - g44) + d5421 * cos(xomi + x2li - g54) + + d5433 * cos(-xomi + x2li - g54)); + xnddt = xnddt * xldot; + } + + /* ----------------------- integrator ------------------- */ + if (iretn == 381) + { + xli = xli + xldot * delt + xndt * step2; + xni = xni + xndt * delt + xnddt * step2; + atime = atime + delt; + } + } // while iretn = 381 + + nm = xni + xndt * ft + xnddt * ft * ft * 0.5; + xl = xli + xldot * ft + xndt * ft * ft * 0.5; + if (irez != 1) + { + mm = xl - 2.0 * nodem + 2.0 * theta; + dndt = nm - no; + } + else + { + mm = xl - nodem - argpm + theta; + dndt = nm - no; + } + nm = no + dndt; + } + +//#include "debug4.cpp" +} // end dsspace + +/*----------------------------------------------------------------------------- +* +* procedure initl +* +* this procedure initializes the spg4 propagator. all the initialization is +* consolidated here instead of having multiple loops inside other routines. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* ecco - eccentricity 0.0 - 1.0 +* epoch - epoch time in days from jan 0, 1950. 0 hr +* inclo - inclination of satellite +* no - mean motion of satellite +* satn - satellite number +* +* outputs : +* ainv - 1.0 / a +* ao - semi major axis +* con41 - +* con42 - 1.0 - 5.0 cos(i) +* cosio - cosine of inclination +* cosio2 - cosio squared +* eccsq - eccentricity squared +* method - flag for deep space 'd', 'n' +* omeosq - 1.0 - ecco * ecco +* posq - semi-parameter squared +* rp - radius of perigee +* rteosq - square root of (1.0 - ecco*ecco) +* sinio - sine of inclination +* gsto - gst at time of observation rad +* no - mean motion of satellite +* +* locals : +* ak - +* d1 - +* del - +* adel - +* po - +* +* coupling : +* getgravconst +* gstime - find greenwich sidereal time from the julian date +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void initl + ( + int satn, gravconsttype whichconst, + double ecco, double epoch, double inclo, double& no, + char& method, + double& ainv, double& ao, double& con41, double& con42, double& cosio, + double& cosio2,double& eccsq, double& omeosq, double& posq, + double& rp, double& rteosq,double& sinio , double& gsto + ) +{ + /* --------------------- local variables ------------------------ */ + double ak, d1, del, adel, po, x2o3, j2, xke, + tumin, mu, radiusearthkm, j3, j4, j3oj2; + + // sgp4fix use old way of finding gst + int ids70; + double ts70, ds70, tfrac, c1, thgr70, fk5r, c1p2p; + const double twopi = 2.0 * pi; + + /* ----------------------- earth constants ---------------------- */ + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + x2o3 = 2.0 / 3.0; + + /* ------------- calculate auxillary epoch quantities ---------- */ + eccsq = ecco * ecco; + omeosq = 1.0 - eccsq; + rteosq = sqrt(omeosq); + cosio = cos(inclo); + cosio2 = cosio * cosio; + + /* ------------------ un-kozai the mean motion ----------------- */ + ak = pow(xke / no, x2o3); + d1 = 0.75 * j2 * (3.0 * cosio2 - 1.0) / (rteosq * omeosq); + del = d1 / (ak * ak); + adel = ak * (1.0 - del * del - del * + (1.0 / 3.0 + 134.0 * del * del / 81.0)); + del = d1/(adel * adel); + no = no / (1.0 + del); + + ao = pow(xke / no, x2o3); + sinio = sin(inclo); + po = ao * omeosq; + con42 = 1.0 - 5.0 * cosio2; + con41 = -con42-cosio2-cosio2; + ainv = 1.0 / ao; + posq = po * po; + rp = ao * (1.0 - ecco); + method = 'n'; + + // sgp4fix modern approach to finding sidereal timew + // gsto = gstime(epoch + 2433281.5); + + // sgp4fix use old way of finding gst + // count integer number of days from 0 jan 1970 + ts70 = epoch - 7305.0; + ids70 = floor(ts70 + 1.0e-8); + ds70 = ids70; + tfrac = ts70 - ds70; + // find greenwich location at epoch + c1 = 1.72027916940703639e-2; + thgr70= 1.7321343856509374; + fk5r = 5.07551419432269442e-15; + c1p2p = c1 + twopi; + gsto = fmod( thgr70 + c1*ds70 + c1p2p*tfrac + ts70*ts70*fk5r, twopi); + if ( gsto < 0.0 ) + gsto = gsto + twopi; + +//#include "debug5.cpp" +} // end initl + +/*----------------------------------------------------------------------------- +* +* procedure sgp4init +* +* this procedure initializes variables for sgp4. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* satn - satellite number +* bstar - sgp4 type drag coefficient kg/m2er +* ecco - eccentricity +* epoch - epoch time in days from jan 0, 1950. 0 hr +* argpo - argument of perigee (output if ds) +* inclo - inclination +* mo - mean anomaly (output if ds) +* no - mean motion +* nodeo - right ascension of ascending node +* +* outputs : +* satrec - common values for subsequent calls +* return code - non-zero on error. +* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er +* 2 - mean motion less than 0.0 +* 3 - pert elements, ecc < 0.0 or ecc > 1.0 +* 4 - semi-latus rectum < 0.0 +* 5 - epoch elements are sub-orbital +* 6 - satellite has decayed +* +* locals : +* cnodm , snodm , cosim , sinim , cosomm , sinomm +* cc1sq , cc2 , cc3 +* coef , coef1 +* cosio4 - +* day - +* dndt - +* em - eccentricity +* emsq - eccentricity squared +* eeta - +* etasq - +* gam - +* argpm - argument of perigee +* nodem - +* inclm - inclination +* mm - mean anomaly +* nm - mean motion +* perige - perigee +* pinvsq - +* psisq - +* qzms24 - +* rtemsq - +* s1, s2, s3, s4, s5, s6, s7 - +* sfour - +* ss1, ss2, ss3, ss4, ss5, ss6, ss7 - +* sz1, sz2, sz3 +* sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33 - +* tc - +* temp - +* temp1, temp2, temp3 - +* tsi - +* xpidot - +* xhdot1 - +* z1, z2, z3 - +* z11, z12, z13, z21, z22, z23, z31, z32, z33 - +* +* coupling : +* getgravconst- +* initl - +* dscom - +* dpper - +* dsinit - +* sgp4 - +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +int sgp4init + ( + gravconsttype whichconst, const int satn, const double epoch, + const double xbstar, const double xecco, const double xargpo, + const double xinclo, const double xmo, const double xno, + const double xnodeo, elsetrec& satrec + ) +{ + /* --------------------- local variables ------------------------ */ + double ao, ainv, con42, cosio, sinio, cosio2, eccsq, + omeosq, posq, rp, rteosq, + cnodm , snodm , cosim , sinim , cosomm, sinomm, cc1sq , + cc2 , cc3 , coef , coef1 , cosio4, day , dndt , + em , emsq , eeta , etasq , gam , argpm , nodem , + inclm , mm , nm , perige, pinvsq, psisq , qzms24, + rtemsq, s1 , s2 , s3 , s4 , s5 , s6 , + s7 , sfour , ss1 = 0 , ss2 = 0 , ss3 = 0 , ss4 = 0 , ss5 = 0 , + ss6 = 0 , ss7 = 0 , sz1 = 0 , sz2 = 0 , sz3 = 0 , sz11 = 0 , sz12 = 0 , + sz13 = 0 , sz21 = 0 , sz22 = 0 , sz23 = 0 , sz31 = 0 , sz32 = 0 , sz33 = 0 , + tc , temp , temp1 , temp2 , temp3 , tsi , xpidot, + xhdot1, z1 , z2 , z3 , z11 , z12 , z13 , + z21 , z22 , z23 , z31 , z32 , z33, + qzms2t, ss, j2, j3oj2, j4, x2o3, r[3], v[3], + tumin, mu, radiusearthkm, xke, j3; + + /* ------------------------ initialization --------------------- */ + // sgp4fix divisor for divide by zero check on inclination + const double temp4 = 1.0 + cos(pi-1.0e-9); + + /* ----------- set all near earth variables to zero ------------ */ + satrec.isimp = 0; satrec.method = 'n'; satrec.aycof = 0.0; + satrec.con41 = 0.0; satrec.cc1 = 0.0; satrec.cc4 = 0.0; + satrec.cc5 = 0.0; satrec.d2 = 0.0; satrec.d3 = 0.0; + satrec.d4 = 0.0; satrec.delmo = 0.0; satrec.eta = 0.0; + satrec.argpdot = 0.0; satrec.omgcof = 0.0; satrec.sinmao = 0.0; + satrec.t = 0.0; satrec.t2cof = 0.0; satrec.t3cof = 0.0; + satrec.t4cof = 0.0; satrec.t5cof = 0.0; satrec.x1mth2 = 0.0; + satrec.x7thm1 = 0.0; satrec.mdot = 0.0; satrec.nodedot = 0.0; + satrec.xlcof = 0.0; satrec.xmcof = 0.0; satrec.nodecf = 0.0; + + /* ----------- set all deep space variables to zero ------------ */ + satrec.irez = 0; satrec.d2201 = 0.0; satrec.d2211 = 0.0; + satrec.d3210 = 0.0; satrec.d3222 = 0.0; satrec.d4410 = 0.0; + satrec.d4422 = 0.0; satrec.d5220 = 0.0; satrec.d5232 = 0.0; + satrec.d5421 = 0.0; satrec.d5433 = 0.0; satrec.dedt = 0.0; + satrec.del1 = 0.0; satrec.del2 = 0.0; satrec.del3 = 0.0; + satrec.didt = 0.0; satrec.dmdt = 0.0; satrec.dnodt = 0.0; + satrec.domdt = 0.0; satrec.e3 = 0.0; satrec.ee2 = 0.0; + satrec.peo = 0.0; satrec.pgho = 0.0; satrec.pho = 0.0; + satrec.pinco = 0.0; satrec.plo = 0.0; satrec.se2 = 0.0; + satrec.se3 = 0.0; satrec.sgh2 = 0.0; satrec.sgh3 = 0.0; + satrec.sgh4 = 0.0; satrec.sh2 = 0.0; satrec.sh3 = 0.0; + satrec.si2 = 0.0; satrec.si3 = 0.0; satrec.sl2 = 0.0; + satrec.sl3 = 0.0; satrec.sl4 = 0.0; satrec.gsto = 0.0; + satrec.xfact = 0.0; satrec.xgh2 = 0.0; satrec.xgh3 = 0.0; + satrec.xgh4 = 0.0; satrec.xh2 = 0.0; satrec.xh3 = 0.0; + satrec.xi2 = 0.0; satrec.xi3 = 0.0; satrec.xl2 = 0.0; + satrec.xl3 = 0.0; satrec.xl4 = 0.0; satrec.xlamo = 0.0; + satrec.zmol = 0.0; satrec.zmos = 0.0; satrec.atime = 0.0; + satrec.xli = 0.0; satrec.xni = 0.0; + + // sgp4fix - note the following variables are also passed directly via satrec. + // it is possible to streamline the sgp4init call by deleting the "x" + // variables, but the user would need to set the satrec.* values first. we + // include the additional assignments in case twoline2rv is not used. + satrec.bstar = xbstar; + satrec.ecco = xecco; + satrec.argpo = xargpo; + satrec.inclo = xinclo; + satrec.mo = xmo; + satrec.no = xno; + satrec.nodeo = xnodeo; + + /* ------------------------ earth constants ----------------------- */ + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + ss = 78.0 / radiusearthkm + 1.0; + qzms2t = pow(((120.0 - 78.0) / radiusearthkm), 4); + x2o3 = 2.0 / 3.0; + + satrec.init = 'y'; + satrec.t = 0.0; + + initl + ( + satn, whichconst, satrec.ecco, epoch, satrec.inclo, satrec.no, satrec.method, + ainv, ao, satrec.con41, con42, cosio, cosio2, eccsq, omeosq, + posq, rp, rteosq, sinio, satrec.gsto + ); + satrec.error = 0; + + if (rp < 1.0) + { +// printf("# *** satn%d epoch elts sub-orbital ***\n", satn); + satrec.error = 5; + } + + if ((omeosq >= 0.0 ) || ( satrec.no >= 0.0)) + { + satrec.isimp = 0; + if (rp < (220.0 / radiusearthkm + 1.0)) + satrec.isimp = 1; + sfour = ss; + qzms24 = qzms2t; + perige = (rp - 1.0) * radiusearthkm; + + /* - for perigees below 156 km, s and qoms2t are altered - */ + if (perige < 156.0) + { + sfour = perige - 78.0; + if (perige < 98.0) + sfour = 20.0; + qzms24 = pow(((120.0 - sfour) / radiusearthkm), 4.0); + sfour = sfour / radiusearthkm + 1.0; + } + pinvsq = 1.0 / posq; + + tsi = 1.0 / (ao - sfour); + satrec.eta = ao * satrec.ecco * tsi; + etasq = satrec.eta * satrec.eta; + eeta = satrec.ecco * satrec.eta; + psisq = fabs(1.0 - etasq); + coef = qzms24 * pow(tsi, 4.0); + coef1 = coef / pow(psisq, 3.5); + cc2 = coef1 * satrec.no * (ao * (1.0 + 1.5 * etasq + eeta * + (4.0 + etasq)) + 0.375 * j2 * tsi / psisq * satrec.con41 * + (8.0 + 3.0 * etasq * (8.0 + etasq))); + satrec.cc1 = satrec.bstar * cc2; + cc3 = 0.0; + if (satrec.ecco > 1.0e-4) + cc3 = -2.0 * coef * tsi * j3oj2 * satrec.no * sinio / satrec.ecco; + satrec.x1mth2 = 1.0 - cosio2; + satrec.cc4 = 2.0* satrec.no * coef1 * ao * omeosq * + (satrec.eta * (2.0 + 0.5 * etasq) + satrec.ecco * + (0.5 + 2.0 * etasq) - j2 * tsi / (ao * psisq) * + (-3.0 * satrec.con41 * (1.0 - 2.0 * eeta + etasq * + (1.5 - 0.5 * eeta)) + 0.75 * satrec.x1mth2 * + (2.0 * etasq - eeta * (1.0 + etasq)) * cos(2.0 * satrec.argpo))); + satrec.cc5 = 2.0 * coef1 * ao * omeosq * (1.0 + 2.75 * + (etasq + eeta) + eeta * etasq); + cosio4 = cosio2 * cosio2; + temp1 = 1.5 * j2 * pinvsq * satrec.no; + temp2 = 0.5 * temp1 * j2 * pinvsq; + temp3 = -0.46875 * j4 * pinvsq * pinvsq * satrec.no; + satrec.mdot = satrec.no + 0.5 * temp1 * rteosq * satrec.con41 + 0.0625 * + temp2 * rteosq * (13.0 - 78.0 * cosio2 + 137.0 * cosio4); + satrec.argpdot = -0.5 * temp1 * con42 + 0.0625 * temp2 * + (7.0 - 114.0 * cosio2 + 395.0 * cosio4) + + temp3 * (3.0 - 36.0 * cosio2 + 49.0 * cosio4); + xhdot1 = -temp1 * cosio; + satrec.nodedot = xhdot1 + (0.5 * temp2 * (4.0 - 19.0 * cosio2) + + 2.0 * temp3 * (3.0 - 7.0 * cosio2)) * cosio; + xpidot = satrec.argpdot+ satrec.nodedot; + satrec.omgcof = satrec.bstar * cc3 * cos(satrec.argpo); + satrec.xmcof = 0.0; + if (satrec.ecco > 1.0e-4) + satrec.xmcof = -x2o3 * coef * satrec.bstar / eeta; + satrec.nodecf = 3.5 * omeosq * xhdot1 * satrec.cc1; + satrec.t2cof = 1.5 * satrec.cc1; + // sgp4fix for divide by zero with xinco = 180 deg + if (fabs(cosio+1.0) > 1.5e-12) + satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / (1.0 + cosio); + else + satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / temp4; + satrec.aycof = -0.5 * j3oj2 * sinio; + satrec.delmo = pow((1.0 + satrec.eta * cos(satrec.mo)), 3); + satrec.sinmao = sin(satrec.mo); + satrec.x7thm1 = 7.0 * cosio2 - 1.0; + + /* --------------- deep space initialization ------------- */ + if ((2*pi / satrec.no) >= 225.0) + { + satrec.method = 'd'; + satrec.isimp = 1; + tc = 0.0; + inclm = satrec.inclo; + + dscom + ( + epoch, satrec.ecco, satrec.argpo, tc, satrec.inclo, satrec.nodeo, + satrec.no, snodm, cnodm, sinim, cosim,sinomm, cosomm, + day, satrec.e3, satrec.ee2, em, emsq, gam, + satrec.peo, satrec.pgho, satrec.pho, satrec.pinco, + satrec.plo, rtemsq, satrec.se2, satrec.se3, + satrec.sgh2, satrec.sgh3, satrec.sgh4, + satrec.sh2, satrec.sh3, satrec.si2, satrec.si3, + satrec.sl2, satrec.sl3, satrec.sl4, s1, s2, s3, s4, s5, + s6, s7, ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3, + sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33, + satrec.xgh2, satrec.xgh3, satrec.xgh4, satrec.xh2, + satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2, + satrec.xl3, satrec.xl4, nm, z1, z2, z3, z11, + z12, z13, z21, z22, z23, z31, z32, z33, + satrec.zmol, satrec.zmos + ); + dpper + ( + satrec.e3, satrec.ee2, satrec.peo, satrec.pgho, + satrec.pho, satrec.pinco, satrec.plo, satrec.se2, + satrec.se3, satrec.sgh2, satrec.sgh3, satrec.sgh4, + satrec.sh2, satrec.sh3, satrec.si2, satrec.si3, + satrec.sl2, satrec.sl3, satrec.sl4, satrec.t, + satrec.xgh2,satrec.xgh3,satrec.xgh4, satrec.xh2, + satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2, + satrec.xl3, satrec.xl4, satrec.zmol, satrec.zmos, inclm, satrec.init, + satrec.ecco, satrec.inclo, satrec.nodeo, satrec.argpo, satrec.mo + ); + + argpm = 0.0; + nodem = 0.0; + mm = 0.0; + + dsinit + ( + whichconst, + cosim, emsq, satrec.argpo, s1, s2, s3, s4, s5, sinim, ss1, ss2, ss3, ss4, + ss5, sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33, satrec.t, tc, + satrec.gsto, satrec.mo, satrec.mdot, satrec.no, satrec.nodeo, + satrec.nodedot, xpidot, z1, z3, z11, z13, z21, z23, z31, z33, + satrec.ecco, eccsq, em, argpm, inclm, mm, nm, nodem, + satrec.irez, satrec.atime, + satrec.d2201, satrec.d2211, satrec.d3210, satrec.d3222 , + satrec.d4410, satrec.d4422, satrec.d5220, satrec.d5232, + satrec.d5421, satrec.d5433, satrec.dedt, satrec.didt, + satrec.dmdt, dndt, satrec.dnodt, satrec.domdt , + satrec.del1, satrec.del2, satrec.del3, satrec.xfact, + satrec.xlamo, satrec.xli, satrec.xni + ); + } + + /* ----------- set variables if not deep space ----------- */ + if (satrec.isimp != 1) + { + cc1sq = satrec.cc1 * satrec.cc1; + satrec.d2 = 4.0 * ao * tsi * cc1sq; + temp = satrec.d2 * tsi * satrec.cc1 / 3.0; + satrec.d3 = (17.0 * ao + sfour) * temp; + satrec.d4 = 0.5 * temp * ao * tsi * (221.0 * ao + 31.0 * sfour) * + satrec.cc1; + satrec.t3cof = satrec.d2 + 2.0 * cc1sq; + satrec.t4cof = 0.25 * (3.0 * satrec.d3 + satrec.cc1 * + (12.0 * satrec.d2 + 10.0 * cc1sq)); + satrec.t5cof = 0.2 * (3.0 * satrec.d4 + + 12.0 * satrec.cc1 * satrec.d3 + + 6.0 * satrec.d2 * satrec.d2 + + 15.0 * cc1sq * (2.0 * satrec.d2 + cc1sq)); + } + } // if omeosq = 0 ... + + /* finally propogate to zero epoch to initialise all others. */ + if(satrec.error == 0) + sgp4(whichconst, satrec, 0.0, r, v); + + satrec.init = 'n'; + +//#include "debug6.cpp" + return satrec.error; +} // end sgp4init + +/*----------------------------------------------------------------------------- +* +* procedure sgp4 +* +* this procedure is the sgp4 prediction model from space command. this is an +* updated and combined version of sgp4 and sdp4, which were originally +* published separately in spacetrack report #3. this version follows the +* methodology from the aiaa paper (2006) describing the history and +* development of the code. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* satrec - initialised structure from sgp4init() call. +* tsince - time eince epoch (minutes) +* +* outputs : +* r - position vector km +* v - velocity km/sec +* return code - non-zero on error. +* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er +* 2 - mean motion less than 0.0 +* 3 - pert elements, ecc < 0.0 or ecc > 1.0 +* 4 - semi-latus rectum < 0.0 +* 5 - epoch elements are sub-orbital +* 6 - satellite has decayed +* +* locals : +* am - +* axnl, aynl - +* betal - +* cosim , sinim , cosomm , sinomm , cnod , snod , cos2u , +* sin2u , coseo1 , sineo1 , cosi , sini , cosip , sinip , +* cosisq , cossu , sinsu , cosu , sinu +* delm - +* delomg - +* dndt - +* eccm - +* emsq - +* ecose - +* el2 - +* eo1 - +* eccp - +* esine - +* argpm - +* argpp - +* omgadf - +* pl - +* r - +* rtemsq - +* rdotl - +* rl - +* rvdot - +* rvdotl - +* su - +* t2 , t3 , t4 , tc +* tem5, temp , temp1 , temp2 , tempa , tempe , templ +* u , ux , uy , uz , vx , vy , vz +* inclm - inclination +* mm - mean anomaly +* nm - mean motion +* nodem - right asc of ascending node +* xinc - +* xincp - +* xl - +* xlm - +* mp - +* xmdf - +* xmx - +* xmy - +* nodedf - +* xnode - +* nodep - +* np - +* +* coupling : +* getgravconst- +* dpper +* dpspace +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +int sgp4 + ( + gravconsttype whichconst, elsetrec& satrec, double tsince, + double r[3], double v[3] + ) +{ + double am , axnl , aynl , betal , cosim , cnod , + cos2u, coseo1, cosi , cosip , cosisq, cossu , cosu, + delm , delomg, em , emsq , ecose , el2 , eo1 , + ep , esine , argpm, argpp , argpdf, pl, mrt = 0.0, + mvt , rdotl , rl , rvdot , rvdotl, sinim , + sin2u, sineo1, sini , sinip , sinsu , sinu , + snod , su , t2 , t3 , t4 , tem5 , temp, + temp1, temp2 , tempa, tempe , templ , u , ux , + uy , uz , vx , vy , vz , inclm , mm , + nm , nodem, xinc , xincp , xl , xlm , mp , + xmdf , xmx , xmy , nodedf, xnode , nodep, tc , dndt, + twopi, x2o3 , j2 , j3 , tumin, j4 , xke , j3oj2, radiusearthkm, + mu, vkmpersec; + int ktr; + + /* ------------------ set mathematical constants --------------- */ + // sgp4fix divisor for divide by zero check on inclination + const double temp4 = 1.0 + cos(pi-1.0e-9); + twopi = 2.0 * pi; + x2o3 = 2.0 / 3.0; + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + vkmpersec = radiusearthkm * xke/60.0; + + /* --------------------- clear sgp4 error flag ----------------- */ + satrec.t = tsince; + satrec.error = 0; + + /* ------- update for secular gravity and atmospheric drag ----- */ + xmdf = satrec.mo + satrec.mdot * satrec.t; + argpdf = satrec.argpo + satrec.argpdot * satrec.t; + nodedf = satrec.nodeo + satrec.nodedot * satrec.t; + argpm = argpdf; + mm = xmdf; + t2 = satrec.t * satrec.t; + nodem = nodedf + satrec.nodecf * t2; + tempa = 1.0 - satrec.cc1 * satrec.t; + tempe = satrec.bstar * satrec.cc4 * satrec.t; + templ = satrec.t2cof * t2; + + if (satrec.isimp != 1) + { + delomg = satrec.omgcof * satrec.t; + delm = satrec.xmcof * + (pow((1.0 + satrec.eta * cos(xmdf)), 3) - + satrec.delmo); + temp = delomg + delm; + mm = xmdf + temp; + argpm = argpdf - temp; + t3 = t2 * satrec.t; + t4 = t3 * satrec.t; + tempa = tempa - satrec.d2 * t2 - satrec.d3 * t3 - + satrec.d4 * t4; + tempe = tempe + satrec.bstar * satrec.cc5 * (sin(mm) - + satrec.sinmao); + templ = templ + satrec.t3cof * t3 + t4 * (satrec.t4cof + + satrec.t * satrec.t5cof); + } + + nm = satrec.no; + em = satrec.ecco; + inclm = satrec.inclo; + if (satrec.method == 'd') + { + tc = satrec.t; + dspace + ( + satrec.irez, + satrec.d2201, satrec.d2211, satrec.d3210, + satrec.d3222, satrec.d4410, satrec.d4422, + satrec.d5220, satrec.d5232, satrec.d5421, + satrec.d5433, satrec.dedt, satrec.del1, + satrec.del2, satrec.del3, satrec.didt, + satrec.dmdt, satrec.dnodt, satrec.domdt, + satrec.argpo, satrec.argpdot, satrec.t, tc, + satrec.gsto, satrec.xfact, satrec.xlamo, + satrec.no, satrec.atime, + em, argpm, inclm, satrec.xli, mm, satrec.xni, + nodem, dndt, nm + ); + } // if method = d + + if (nm <= 0.0) + { +// printf("# error nm %f\n", nm); + satrec.error = 2; + } + am = pow((xke / nm),x2o3) * tempa * tempa; + nm = xke / pow(am, 1.5); + em = em - tempe; + + // fix tolerance for error recognition + if ((em >= 1.0) || (em < -0.001) || (am < 0.95)) + { +// printf("# error em %f\n", em); + satrec.error = 1; + } + if (em < 0.0) + em = 1.0e-6; + mm = mm + satrec.no * templ; + xlm = mm + argpm + nodem; + emsq = em * em; + temp = 1.0 - emsq; + + nodem = fmod(nodem, twopi); + argpm = fmod(argpm, twopi); + xlm = fmod(xlm, twopi); + mm = fmod(xlm - argpm - nodem, twopi); + + /* ----------------- compute extra mean quantities ------------- */ + sinim = sin(inclm); + cosim = cos(inclm); + + /* -------------------- add lunar-solar periodics -------------- */ + ep = em; + xincp = inclm; + argpp = argpm; + nodep = nodem; + mp = mm; + sinip = sinim; + cosip = cosim; + if (satrec.method == 'd') + { + dpper + ( + satrec.e3, satrec.ee2, satrec.peo, + satrec.pgho, satrec.pho, satrec.pinco, + satrec.plo, satrec.se2, satrec.se3, + satrec.sgh2, satrec.sgh3, satrec.sgh4, + satrec.sh2, satrec.sh3, satrec.si2, + satrec.si3, satrec.sl2, satrec.sl3, + satrec.sl4, satrec.t, satrec.xgh2, + satrec.xgh3, satrec.xgh4, satrec.xh2, + satrec.xh3, satrec.xi2, satrec.xi3, + satrec.xl2, satrec.xl3, satrec.xl4, + satrec.zmol, satrec.zmos, satrec.inclo, + 'n', ep, xincp, nodep, argpp, mp + ); + if (xincp < 0.0) + { + xincp = -xincp; + nodep = nodep + pi; + argpp = argpp - pi; + } + if ((ep < 0.0 ) || ( ep > 1.0)) + { + // printf("# error ep %f\n", ep); + satrec.error = 3; + } + } // if method = d + + /* -------------------- long period periodics ------------------ */ + if (satrec.method == 'd') + { + sinip = sin(xincp); + cosip = cos(xincp); + satrec.aycof = -0.5*j3oj2*sinip; + // sgp4fix for divide by zero for xincp = 180 deg + if (fabs(cosip+1.0) > 1.5e-12) + satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / (1.0 + cosip); + else + satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / temp4; + } + axnl = ep * cos(argpp); + temp = 1.0 / (am * (1.0 - ep * ep)); + aynl = ep* sin(argpp) + temp * satrec.aycof; + xl = mp + argpp + nodep + temp * satrec.xlcof * axnl; + + /* --------------------- solve kepler's equation --------------- */ + u = fmod(xl - nodep, twopi); + eo1 = u; + tem5 = 9999.9; + ktr = 1; + // sgp4fix for kepler iteration + // the following iteration needs better limits on corrections + while (( fabs(tem5) >= 1.0e-12) && (ktr <= 10) ) + { + sineo1 = sin(eo1); + coseo1 = cos(eo1); + tem5 = 1.0 - coseo1 * axnl - sineo1 * aynl; + tem5 = (u - aynl * coseo1 + axnl * sineo1 - eo1) / tem5; + if(fabs(tem5) >= 0.95) + tem5 = tem5 > 0.0 ? 0.95 : -0.95; + eo1 = eo1 + tem5; + ktr = ktr + 1; + } + + /* ------------- short period preliminary quantities ----------- */ + ecose = axnl*coseo1 + aynl*sineo1; + esine = axnl*sineo1 - aynl*coseo1; + el2 = axnl*axnl + aynl*aynl; + pl = am*(1.0-el2); + if (pl < 0.0) + { +// printf("# error pl %f\n", pl); + satrec.error = 4; + } + else + { + rl = am * (1.0 - ecose); + rdotl = sqrt(am) * esine/rl; + rvdotl = sqrt(pl) / rl; + betal = sqrt(1.0 - el2); + temp = esine / (1.0 + betal); + sinu = am / rl * (sineo1 - aynl - axnl * temp); + cosu = am / rl * (coseo1 - axnl + aynl * temp); + su = atan2(sinu, cosu); + sin2u = (cosu + cosu) * sinu; + cos2u = 1.0 - 2.0 * sinu * sinu; + temp = 1.0 / pl; + temp1 = 0.5 * j2 * temp; + temp2 = temp1 * temp; + + /* -------------- update for short period periodics ------------ */ + if (satrec.method == 'd') + { + cosisq = cosip * cosip; + satrec.con41 = 3.0*cosisq - 1.0; + satrec.x1mth2 = 1.0 - cosisq; + satrec.x7thm1 = 7.0*cosisq - 1.0; + } + mrt = rl * (1.0 - 1.5 * temp2 * betal * satrec.con41) + + 0.5 * temp1 * satrec.x1mth2 * cos2u; + su = su - 0.25 * temp2 * satrec.x7thm1 * sin2u; + xnode = nodep + 1.5 * temp2 * cosip * sin2u; + xinc = xincp + 1.5 * temp2 * cosip * sinip * cos2u; + mvt = rdotl - nm * temp1 * satrec.x1mth2 * sin2u / xke; + rvdot = rvdotl + nm * temp1 * (satrec.x1mth2 * cos2u + + 1.5 * satrec.con41) / xke; + + /* --------------------- orientation vectors ------------------- */ + sinsu = sin(su); + cossu = cos(su); + snod = sin(xnode); + cnod = cos(xnode); + sini = sin(xinc); + cosi = cos(xinc); + xmx = -snod * cosi; + xmy = cnod * cosi; + ux = xmx * sinsu + cnod * cossu; + uy = xmy * sinsu + snod * cossu; + uz = sini * sinsu; + vx = xmx * cossu - cnod * sinsu; + vy = xmy * cossu - snod * sinsu; + vz = sini * cossu; + + /* --------- position and velocity (in km and km/sec) ---------- */ + r[0] = (mrt * ux)* radiusearthkm; + r[1] = (mrt * uy)* radiusearthkm; + r[2] = (mrt * uz)* radiusearthkm; + v[0] = (mvt * ux + rvdot * vx) * vkmpersec; + v[1] = (mvt * uy + rvdot * vy) * vkmpersec; + v[2] = (mvt * uz + rvdot * vz) * vkmpersec; + } // if pl > 0 + + // sgp4fix for decaying satellites + if (mrt < 1.0) + { +// printf("# decay condition %11.6f \n",mrt); + satrec.error = 6; + } + + +//#include "debug7.cpp" + return satrec.error; +} // end sgp4 + + +/* ----------------------------------------------------------------------------- +* +* function gstime +* +* this function finds the greenwich sidereal time. +* +* author : david vallado 719-573-2600 1 mar 2001 +* +* inputs description range / units +* jdut1 - julian date in ut1 days from 4713 bc +* +* outputs : +* gstime - greenwich sidereal time 0 to 2pi rad +* +* locals : +* temp - temporary variable for doubles rad +* tut1 - julian centuries from the +* jan 1, 2000 12 h epoch (ut1) +* +* coupling : +* none +* +* references : +* vallado 2004, 191, eq 3-45 +* --------------------------------------------------------------------------- */ + +double gstime + ( + double jdut1 + ) + { + const double twopi = 2.0 * pi; + const double deg2rad = pi / 180.0; + double temp, tut1; + + tut1 = (jdut1 - 2451545.0) / 36525.0; + temp = -6.2e-6* tut1 * tut1 * tut1 + 0.093104 * tut1 * tut1 + + (876600.0*3600 + 8640184.812866) * tut1 + 67310.54841; // sec + temp = fmod(temp * deg2rad / 240.0, twopi); //360/86400 = 1/240, to deg, to rad + + // ------------------------ check quadrants --------------------- + if (temp < 0.0) + temp += twopi; + + return temp; + } // end gstime + +/* ----------------------------------------------------------------------------- +* +* function getgravconst +* +* this function gets constants for the propagator. note that mu is identified to +* facilitiate comparisons with newer models. the common useage is wgs72. +* +* author : david vallado 719-573-2600 21 jul 2006 +* +* inputs : +* whichconst - which set of constants to use wgs72old, wgs72, wgs84 +* +* outputs : +* tumin - minutes in one time unit +* mu - earth gravitational parameter +* radiusearthkm - radius of the earth in km +* xke - reciprocal of tumin +* j2, j3, j4 - un-normalized zonal harmonic values +* j3oj2 - j3 divided by j2 +* +* locals : +* +* coupling : +* none +* +* references : +* norad spacetrack report #3 +* vallado, crawford, hujsak, kelso 2006 + --------------------------------------------------------------------------- */ + +void getgravconst + ( + gravconsttype whichconst, + double& tumin, + double& mu, + double& radiusearthkm, + double& xke, + double& j2, + double& j3, + double& j4, + double& j3oj2 + ) + { + + switch (whichconst) + { + // -- wgs-72 low precision str#3 constants -- + case wgs72old: + mu = 398600.79964; // in km3 / s2 + radiusearthkm = 6378.135; // km + xke = 0.0743669161; + tumin = 1.0 / xke; + j2 = 0.001082616; + j3 = -0.00000253881; + j4 = -0.00000165597; + j3oj2 = j3 / j2; + break; + // ------------ wgs-72 constants ------------ + case wgs72: + mu = 398600.8; // in km3 / s2 + radiusearthkm = 6378.135; // km + xke = 60.0 / sqrt(radiusearthkm*radiusearthkm*radiusearthkm/mu); + tumin = 1.0 / xke; + j2 = 0.001082616; + j3 = -0.00000253881; + j4 = -0.00000165597; + j3oj2 = j3 / j2; + break; + case wgs84: + // ------------ wgs-84 constants ------------ + mu = 398600.5; // in km3 / s2 + radiusearthkm = 6378.137; // km + xke = 60.0 / sqrt(radiusearthkm*radiusearthkm*radiusearthkm/mu); + tumin = 1.0 / xke; + j2 = 0.00108262998905; + j3 = -0.00000253215306; + j4 = -0.00000161098761; + j3oj2 = j3 / j2; + break; + default: + fprintf(stderr,"unknown gravity option (%d)\n",whichconst); + break; + } + + } // end getgravconst + + + + + diff --git a/contrib/sgp4/sgp4unit.h b/contrib/sgp4/sgp4unit.h index 48c113d7..f16acbd9 100644 --- a/contrib/sgp4/sgp4unit.h +++ b/contrib/sgp4/sgp4unit.h @@ -1,117 +1,117 @@ -#ifndef _sgp4unit_ -#define _sgp4unit_ -/* ---------------------------------------------------------------- -* -* sgp4unit.h -* -* this file contains the sgp4 procedures for analytical propagation -* of a satellite. the code was originally released in the 1980 and 1986 -* spacetrack papers. a detailed discussion of the theory and history -* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, -* and kelso. -* -* companion code for -* fundamentals of astrodynamics and applications -* 2007 -* by david vallado -* -* (w) 719-573-2600, email dvallado@agi.com -* -* current : -* 20 apr 07 david vallado -* misc fixes for constants -* changes : -* 11 aug 06 david vallado -* chg lyddane choice back to strn3, constants, misc doc -* 15 dec 05 david vallado -* misc fixes -* 26 jul 05 david vallado -* fixes for paper -* note that each fix is preceded by a -* comment with "sgp4fix" and an explanation of -* what was changed -* 10 aug 04 david vallado -* 2nd printing baseline working -* 14 may 01 david vallado -* 2nd edition baseline -* 80 norad -* original baseline -* ---------------------------------------------------------------- */ - -#include -#include - -// -------------------------- structure declarations ---------------------------- -typedef enum -{ - wgs72old, - wgs72, - wgs84 -} gravconsttype; - -typedef struct elsetrec -{ - long int satnum; - int epochyr, epochtynumrev; - int error; - char init, method; - - /* Near Earth */ - int isimp; - double aycof , con41 , cc1 , cc4 , cc5 , d2 , d3 , d4 , - delmo , eta , argpdot, omgcof , sinmao , t , t2cof, t3cof , - t4cof , t5cof , x1mth2 , x7thm1 , mdot , nodedot, xlcof , xmcof , - nodecf; - - /* Deep Space */ - int irez; - double d2201 , d2211 , d3210 , d3222 , d4410 , d4422 , d5220 , d5232 , - d5421 , d5433 , dedt , del1 , del2 , del3 , didt , dmdt , - dnodt , domdt , e3 , ee2 , peo , pgho , pho , pinco , - plo , se2 , se3 , sgh2 , sgh3 , sgh4 , sh2 , sh3 , - si2 , si3 , sl2 , sl3 , sl4 , gsto , xfact , xgh2 , - xgh3 , xgh4 , xh2 , xh3 , xi2 , xi3 , xl2 , xl3 , - xl4 , xlamo , zmol , zmos , atime , xli , xni; - - double a , altp , alta , epochdays, jdsatepoch , nddot , ndot , - bstar , rcse , inclo , nodeo , ecco , argpo , mo , - no; -} elsetrec; - -// --------------------------- function declarations ---------------------------- -int sgp4init - ( - gravconsttype whichconst, const int satn, const double epoch, - const double xbstar, const double xecco, const double xargpo, - const double xinclo, const double xmo, const double xno, - const double xnodeo, - elsetrec& satrec - ); - -int sgp4 - ( - gravconsttype whichconst, - elsetrec& satrec, double tsince, - double r[], double v[] - ); - -double gstime - ( - double - ); - -void getgravconst - ( - gravconsttype, - double&, - double&, - double&, - double&, - double&, - double&, - double&, - double& - ); - -#endif - +#ifndef _sgp4unit_ +#define _sgp4unit_ +/* ---------------------------------------------------------------- +* +* sgp4unit.h +* +* this file contains the sgp4 procedures for analytical propagation +* of a satellite. the code was originally released in the 1980 and 1986 +* spacetrack papers. a detailed discussion of the theory and history +* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, +* and kelso. +* +* companion code for +* fundamentals of astrodynamics and applications +* 2007 +* by david vallado +* +* (w) 719-573-2600, email dvallado@agi.com +* +* current : +* 20 apr 07 david vallado +* misc fixes for constants +* changes : +* 11 aug 06 david vallado +* chg lyddane choice back to strn3, constants, misc doc +* 15 dec 05 david vallado +* misc fixes +* 26 jul 05 david vallado +* fixes for paper +* note that each fix is preceded by a +* comment with "sgp4fix" and an explanation of +* what was changed +* 10 aug 04 david vallado +* 2nd printing baseline working +* 14 may 01 david vallado +* 2nd edition baseline +* 80 norad +* original baseline +* ---------------------------------------------------------------- */ + +#include +#include + +// -------------------------- structure declarations ---------------------------- +typedef enum +{ + wgs72old, + wgs72, + wgs84 +} gravconsttype; + +typedef struct elsetrec +{ + long int satnum; + int epochyr, epochtynumrev; + int error; + char init, method; + + /* Near Earth */ + int isimp; + double aycof , con41 , cc1 , cc4 , cc5 , d2 , d3 , d4 , + delmo , eta , argpdot, omgcof , sinmao , t , t2cof, t3cof , + t4cof , t5cof , x1mth2 , x7thm1 , mdot , nodedot, xlcof , xmcof , + nodecf; + + /* Deep Space */ + int irez; + double d2201 , d2211 , d3210 , d3222 , d4410 , d4422 , d5220 , d5232 , + d5421 , d5433 , dedt , del1 , del2 , del3 , didt , dmdt , + dnodt , domdt , e3 , ee2 , peo , pgho , pho , pinco , + plo , se2 , se3 , sgh2 , sgh3 , sgh4 , sh2 , sh3 , + si2 , si3 , sl2 , sl3 , sl4 , gsto , xfact , xgh2 , + xgh3 , xgh4 , xh2 , xh3 , xi2 , xi3 , xl2 , xl3 , + xl4 , xlamo , zmol , zmos , atime , xli , xni; + + double a , altp , alta , epochdays, jdsatepoch , nddot , ndot , + bstar , rcse , inclo , nodeo , ecco , argpo , mo , + no; +} elsetrec; + +// --------------------------- function declarations ---------------------------- +int sgp4init + ( + gravconsttype whichconst, const int satn, const double epoch, + const double xbstar, const double xecco, const double xargpo, + const double xinclo, const double xmo, const double xno, + const double xnodeo, + elsetrec& satrec + ); + +int sgp4 + ( + gravconsttype whichconst, + elsetrec& satrec, double tsince, + double r[], double v[] + ); + +double gstime + ( + double + ); + +void getgravconst + ( + gravconsttype, + double&, + double&, + double&, + double&, + double&, + double&, + double&, + double& + ); + +#endif + diff --git a/devicehandlers/ChildHandlerBase.cpp b/devicehandlers/ChildHandlerBase.cpp index f18c3812..e800cd56 100644 --- a/devicehandlers/ChildHandlerBase.cpp +++ b/devicehandlers/ChildHandlerBase.cpp @@ -1,45 +1,45 @@ -#include "../subsystem/SubsystemBase.h" -#include "../devicehandlers/ChildHandlerBase.h" -#include "../subsystem/SubsystemBase.h" - -ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId, - object_id_t deviceCommunication, CookieIF * cookie, - uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, - object_id_t parent, FailureIsolationBase* customFdir, - size_t cmdQueueSize) : - DeviceHandlerBase(setObjectId, deviceCommunication, cookie, - (customFdir == nullptr? &childHandlerFdir : customFdir), - cmdQueueSize), - parentId(parent), childHandlerFdir(setObjectId) { - this->setThermalStateRequestPoolIds(thermalStatePoolId, - thermalRequestPoolId); - -} - -ChildHandlerBase::~ChildHandlerBase() { -} - -ReturnValue_t ChildHandlerBase::initialize() { - ReturnValue_t result = DeviceHandlerBase::initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - - MessageQueueId_t parentQueue = 0; - - if (parentId != objects::NO_OBJECT) { - SubsystemBase *parent = objectManager->get(parentId); - if (parent == NULL) { - return RETURN_FAILED; - } - parentQueue = parent->getCommandQueue(); - - parent->registerChild(getObjectId()); - } - - healthHelper.setParentQueue(parentQueue); - - modeHelper.setParentQueue(parentQueue); - - return RETURN_OK; -} +#include "../subsystem/SubsystemBase.h" +#include "../devicehandlers/ChildHandlerBase.h" +#include "../subsystem/SubsystemBase.h" + +ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId, + object_id_t deviceCommunication, CookieIF * cookie, + uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, + object_id_t parent, FailureIsolationBase* customFdir, + size_t cmdQueueSize) : + DeviceHandlerBase(setObjectId, deviceCommunication, cookie, + (customFdir == nullptr? &childHandlerFdir : customFdir), + cmdQueueSize), + parentId(parent), childHandlerFdir(setObjectId) { + this->setThermalStateRequestPoolIds(thermalStatePoolId, + thermalRequestPoolId); + +} + +ChildHandlerBase::~ChildHandlerBase() { +} + +ReturnValue_t ChildHandlerBase::initialize() { + ReturnValue_t result = DeviceHandlerBase::initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + MessageQueueId_t parentQueue = 0; + + if (parentId != objects::NO_OBJECT) { + SubsystemBase *parent = objectManager->get(parentId); + if (parent == NULL) { + return RETURN_FAILED; + } + parentQueue = parent->getCommandQueue(); + + parent->registerChild(getObjectId()); + } + + healthHelper.setParentQueue(parentQueue); + + modeHelper.setParentQueue(parentQueue); + + return RETURN_OK; +} diff --git a/devicehandlers/ChildHandlerBase.h b/devicehandlers/ChildHandlerBase.h index 3e9652a3..f6bf318a 100644 --- a/devicehandlers/ChildHandlerBase.h +++ b/devicehandlers/ChildHandlerBase.h @@ -1,26 +1,26 @@ #ifndef FSFW_DEVICES_CHILDHANDLERBASE_H_ -#define FSFW_DEVICES_CHILDHANDLERBASE_H_ - -#include "ChildHandlerFDIR.h" -#include "DeviceHandlerBase.h" - -class ChildHandlerBase: public DeviceHandlerBase { -public: - ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, - CookieIF * cookie, uint32_t thermalStatePoolId, - uint32_t thermalRequestPoolId, - object_id_t parent = objects::NO_OBJECT, - FailureIsolationBase* customFdir = nullptr, - size_t cmdQueueSize = 20); - virtual ~ChildHandlerBase(); - - virtual ReturnValue_t initialize(); - -protected: - const uint32_t parentId; - ChildHandlerFDIR childHandlerFdir; - -}; - -#endif /* FSFW_DEVICES_CHILDHANDLERBASE_H_ */ +#define FSFW_DEVICES_CHILDHANDLERBASE_H_ + +#include "ChildHandlerFDIR.h" +#include "DeviceHandlerBase.h" + +class ChildHandlerBase: public DeviceHandlerBase { +public: + ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, + CookieIF * cookie, uint32_t thermalStatePoolId, + uint32_t thermalRequestPoolId, + object_id_t parent = objects::NO_OBJECT, + FailureIsolationBase* customFdir = nullptr, + size_t cmdQueueSize = 20); + virtual ~ChildHandlerBase(); + + virtual ReturnValue_t initialize(); + +protected: + const uint32_t parentId; + ChildHandlerFDIR childHandlerFdir; + +}; + +#endif /* FSFW_DEVICES_CHILDHANDLERBASE_H_ */ diff --git a/osal/FreeRTOS/TaskManagement.cpp b/osal/FreeRTOS/TaskManagement.cpp index 16682d36..b77f12a9 100644 --- a/osal/FreeRTOS/TaskManagement.cpp +++ b/osal/FreeRTOS/TaskManagement.cpp @@ -1,24 +1,24 @@ -#include "../../osal/FreeRTOS/TaskManagement.h" - -void TaskManagement::vRequestContextSwitchFromTask() { - vTaskDelay(0); -} - -void TaskManagement::requestContextSwitch( - CallContext callContext = CallContext::TASK) { - if(callContext == CallContext::ISR) { - // This function depends on the partmacro.h definition for the specific device - vRequestContextSwitchFromISR(); - } else { - vRequestContextSwitchFromTask(); - } -} - -TaskHandle_t TaskManagement::getCurrentTaskHandle() { - return xTaskGetCurrentTaskHandle(); -} - -size_t TaskManagement::getTaskStackHighWatermark( - TaskHandle_t task) { - return uxTaskGetStackHighWaterMark(task) * sizeof(StackType_t); -} +#include "../../osal/FreeRTOS/TaskManagement.h" + +void TaskManagement::vRequestContextSwitchFromTask() { + vTaskDelay(0); +} + +void TaskManagement::requestContextSwitch( + CallContext callContext = CallContext::TASK) { + if(callContext == CallContext::ISR) { + // This function depends on the partmacro.h definition for the specific device + vRequestContextSwitchFromISR(); + } else { + vRequestContextSwitchFromTask(); + } +} + +TaskHandle_t TaskManagement::getCurrentTaskHandle() { + return xTaskGetCurrentTaskHandle(); +} + +size_t TaskManagement::getTaskStackHighWatermark( + TaskHandle_t task) { + return uxTaskGetStackHighWaterMark(task) * sizeof(StackType_t); +} diff --git a/osal/FreeRTOS/TaskManagement.h b/osal/FreeRTOS/TaskManagement.h index 43003d76..4b7fe3eb 100644 --- a/osal/FreeRTOS/TaskManagement.h +++ b/osal/FreeRTOS/TaskManagement.h @@ -1,64 +1,64 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ -#define FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ - -#include "../../returnvalues/HasReturnvaluesIF.h" - -extern "C" { -#include -#include -} -#include - -/** - * Architecture dependant portmacro.h function call. - * Should be implemented in bsp. - */ -extern void vRequestContextSwitchFromISR(); - -/*! - * Used by functions to tell if they are being called from - * within an ISR or from a regular task. This is required because FreeRTOS - * has different functions for handling semaphores and messages from within - * an ISR and task. - */ -enum class CallContext { - TASK = 0x00,//!< task_context - ISR = 0xFF //!< isr_context -}; - - -class TaskManagement { -public: - /** - * @brief In this function, a function dependant on the portmacro.h header - * function calls to request a context switch can be specified. - * This can be used if sending to the queue from an ISR caused a task - * to unblock and a context switch is required. - */ - static void requestContextSwitch(CallContext callContext); - - /** - * If task preemption in FreeRTOS is disabled, a context switch - * can be requested manually by calling this function. - */ - static void vRequestContextSwitchFromTask(void); - - /** - * @return The current task handle - */ - static TaskHandle_t getCurrentTaskHandle(); - - /** - * Get returns the minimum amount of remaining stack space in words - * that was a available to the task since the task started executing. - * Please note that the actual value in bytes depends - * on the stack depth type. - * E.g. on a 32 bit machine, a value of 200 means 800 bytes. - * @return Smallest value of stack remaining since the task was started in - * words. - */ - static size_t getTaskStackHighWatermark( - TaskHandle_t task = nullptr); -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ +#define FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ + +#include "../../returnvalues/HasReturnvaluesIF.h" + +extern "C" { +#include +#include +} +#include + +/** + * Architecture dependant portmacro.h function call. + * Should be implemented in bsp. + */ +extern void vRequestContextSwitchFromISR(); + +/*! + * Used by functions to tell if they are being called from + * within an ISR or from a regular task. This is required because FreeRTOS + * has different functions for handling semaphores and messages from within + * an ISR and task. + */ +enum class CallContext { + TASK = 0x00,//!< task_context + ISR = 0xFF //!< isr_context +}; + + +class TaskManagement { +public: + /** + * @brief In this function, a function dependant on the portmacro.h header + * function calls to request a context switch can be specified. + * This can be used if sending to the queue from an ISR caused a task + * to unblock and a context switch is required. + */ + static void requestContextSwitch(CallContext callContext); + + /** + * If task preemption in FreeRTOS is disabled, a context switch + * can be requested manually by calling this function. + */ + static void vRequestContextSwitchFromTask(void); + + /** + * @return The current task handle + */ + static TaskHandle_t getCurrentTaskHandle(); + + /** + * Get returns the minimum amount of remaining stack space in words + * that was a available to the task since the task started executing. + * Please note that the actual value in bytes depends + * on the stack depth type. + * E.g. on a 32 bit machine, a value of 200 means 800 bytes. + * @return Smallest value of stack remaining since the task was started in + * words. + */ + static size_t getTaskStackHighWatermark( + TaskHandle_t task = nullptr); +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */ diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index 812cd34b..1c11afd4 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -1,129 +1,129 @@ -#include "../serialize/SerialBufferAdapter.h" -#include "../serviceinterface/ServiceInterfaceStream.h" -#include - -template -SerialBufferAdapter::SerialBufferAdapter(const uint8_t* buffer, - count_t bufferLength, bool serializeLength) : - serializeLength(serializeLength), - constBuffer(buffer), buffer(nullptr), - bufferLength(bufferLength) {} - -template -SerialBufferAdapter::SerialBufferAdapter(uint8_t* buffer, - count_t bufferLength, bool serializeLength) : - serializeLength(serializeLength), constBuffer(buffer), buffer(buffer), - bufferLength(bufferLength) {} - - -template -SerialBufferAdapter::~SerialBufferAdapter() { -} - -template -ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, - size_t* size, size_t maxSize, Endianness streamEndianness) const { - if (serializeLength) { - ReturnValue_t result = SerializeAdapter::serialize(&bufferLength, - buffer, size, maxSize, streamEndianness); - if(result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - } - - if (*size + bufferLength > maxSize) { - return BUFFER_TOO_SHORT; - } - - if (this->constBuffer != nullptr) { - std::memcpy(*buffer, this->constBuffer, bufferLength); - } - else if (this->buffer != nullptr) { - // This will propably be never reached, constBuffer should always be - // set if non-const buffer is set. - std::memcpy(*buffer, this->buffer, bufferLength); - } - else { - return HasReturnvaluesIF::RETURN_FAILED; - } - *size += bufferLength; - (*buffer) += bufferLength; - return HasReturnvaluesIF::RETURN_OK; - -} - -template -size_t SerialBufferAdapter::getSerializedSize() const { - if (serializeLength) { - return bufferLength + SerializeAdapter::getSerializedSize(&bufferLength); - } else { - return bufferLength; - } -} - -template -ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, - size_t* size, Endianness streamEndianness) { - if (this->buffer == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - - if(serializeLength){ - count_t lengthField = 0; - ReturnValue_t result = SerializeAdapter::deSerialize(&lengthField, - buffer, size, streamEndianness); - if(result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - if(lengthField > bufferLength) { - return TOO_MANY_ELEMENTS; - } - bufferLength = lengthField; - } - - if (bufferLength <= *size) { - *size -= bufferLength; - std::memcpy(this->buffer, *buffer, bufferLength); - (*buffer) += bufferLength; - return HasReturnvaluesIF::RETURN_OK; - } - else { - return STREAM_TOO_SHORT; - } -} - -template -uint8_t * SerialBufferAdapter::getBuffer() { - if(buffer == nullptr) { - sif::error << "Wrong access function for stored type !" - " Use getConstBuffer()." << std::endl; - return nullptr; - } - return buffer; -} - -template -const uint8_t * SerialBufferAdapter::getConstBuffer() { - if(constBuffer == nullptr) { - sif::error << "SerialBufferAdapter::getConstBuffer:" - " Buffers are unitialized!" << std::endl; - return nullptr; - } - return constBuffer; -} - -template -void SerialBufferAdapter::setBuffer(uint8_t* buffer, - count_t bufferLength) { - this->buffer = buffer; - this->constBuffer = buffer; - this->bufferLength = bufferLength; -} - - -//forward Template declaration for linker -template class SerialBufferAdapter; -template class SerialBufferAdapter; -template class SerialBufferAdapter; -template class SerialBufferAdapter; - +#include "../serialize/SerialBufferAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include + +template +SerialBufferAdapter::SerialBufferAdapter(const uint8_t* buffer, + count_t bufferLength, bool serializeLength) : + serializeLength(serializeLength), + constBuffer(buffer), buffer(nullptr), + bufferLength(bufferLength) {} + +template +SerialBufferAdapter::SerialBufferAdapter(uint8_t* buffer, + count_t bufferLength, bool serializeLength) : + serializeLength(serializeLength), constBuffer(buffer), buffer(buffer), + bufferLength(bufferLength) {} + + +template +SerialBufferAdapter::~SerialBufferAdapter() { +} + +template +ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, + size_t* size, size_t maxSize, Endianness streamEndianness) const { + if (serializeLength) { + ReturnValue_t result = SerializeAdapter::serialize(&bufferLength, + buffer, size, maxSize, streamEndianness); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + + if (*size + bufferLength > maxSize) { + return BUFFER_TOO_SHORT; + } + + if (this->constBuffer != nullptr) { + std::memcpy(*buffer, this->constBuffer, bufferLength); + } + else if (this->buffer != nullptr) { + // This will propably be never reached, constBuffer should always be + // set if non-const buffer is set. + std::memcpy(*buffer, this->buffer, bufferLength); + } + else { + return HasReturnvaluesIF::RETURN_FAILED; + } + *size += bufferLength; + (*buffer) += bufferLength; + return HasReturnvaluesIF::RETURN_OK; + +} + +template +size_t SerialBufferAdapter::getSerializedSize() const { + if (serializeLength) { + return bufferLength + SerializeAdapter::getSerializedSize(&bufferLength); + } else { + return bufferLength; + } +} + +template +ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, + size_t* size, Endianness streamEndianness) { + if (this->buffer == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + + if(serializeLength){ + count_t lengthField = 0; + ReturnValue_t result = SerializeAdapter::deSerialize(&lengthField, + buffer, size, streamEndianness); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + if(lengthField > bufferLength) { + return TOO_MANY_ELEMENTS; + } + bufferLength = lengthField; + } + + if (bufferLength <= *size) { + *size -= bufferLength; + std::memcpy(this->buffer, *buffer, bufferLength); + (*buffer) += bufferLength; + return HasReturnvaluesIF::RETURN_OK; + } + else { + return STREAM_TOO_SHORT; + } +} + +template +uint8_t * SerialBufferAdapter::getBuffer() { + if(buffer == nullptr) { + sif::error << "Wrong access function for stored type !" + " Use getConstBuffer()." << std::endl; + return nullptr; + } + return buffer; +} + +template +const uint8_t * SerialBufferAdapter::getConstBuffer() { + if(constBuffer == nullptr) { + sif::error << "SerialBufferAdapter::getConstBuffer:" + " Buffers are unitialized!" << std::endl; + return nullptr; + } + return constBuffer; +} + +template +void SerialBufferAdapter::setBuffer(uint8_t* buffer, + count_t bufferLength) { + this->buffer = buffer; + this->constBuffer = buffer; + this->bufferLength = bufferLength; +} + + +//forward Template declaration for linker +template class SerialBufferAdapter; +template class SerialBufferAdapter; +template class SerialBufferAdapter; +template class SerialBufferAdapter; + diff --git a/serialize/SerialBufferAdapter.h b/serialize/SerialBufferAdapter.h index c3dfcd8f..9a89e18b 100644 --- a/serialize/SerialBufferAdapter.h +++ b/serialize/SerialBufferAdapter.h @@ -1,78 +1,78 @@ -#ifndef SERIALBUFFERADAPTER_H_ -#define SERIALBUFFERADAPTER_H_ - -#include "../serialize/SerializeIF.h" -#include "../serialize/SerializeAdapter.h" - -/** - * 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>. - * Right now, the SerialBufferAdapter must always - * be initialized with the buffer and size ! - * - * \ingroup serialize - */ -template -class SerialBufferAdapter: public SerializeIF { -public: - - /** - * Constructor for constant uint8_t buffer. Length field can be serialized optionally. - * Type of length can be supplied as template type. - * @param buffer - * @param bufferLength - * @param serializeLength - */ - SerialBufferAdapter(const uint8_t* buffer, count_t bufferLength, - bool serializeLength = false); - - /** - * Constructor for non-constant uint8_t buffer. - * Length field can be serialized optionally. - * Type of length can be supplied as template type. - * @param buffer - * @param bufferLength - * @param serializeLength Length field will be serialized with size count_t - */ - SerialBufferAdapter(uint8_t* buffer, count_t bufferLength, - bool serializeLength = false); - - virtual ~SerialBufferAdapter(); - - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, - size_t maxSize, Endianness streamEndianness) const override; - - virtual size_t getSerializedSize() const override; - - /** - * @brief This function deserializes a buffer into the member buffer. - * @details - * If a length field is present, it is ignored, as the size should have - * been set in the constructor. If the size is not known beforehand, - * consider using SerialFixedArrayListAdapter instead. - * @param buffer [out] Resulting buffer - * @param size remaining size to deserialize, should be larger than buffer - * + size field size - * @param bigEndian - * @return - */ - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) override; - - uint8_t * getBuffer(); - const uint8_t * getConstBuffer(); - void setBuffer(uint8_t* buffer, count_t bufferLength); -private: - bool serializeLength = false; - const uint8_t *constBuffer = nullptr; - uint8_t *buffer = nullptr; - count_t bufferLength = 0; -}; - -#endif /* SERIALBUFFERADAPTER_H_ */ +#ifndef SERIALBUFFERADAPTER_H_ +#define SERIALBUFFERADAPTER_H_ + +#include "../serialize/SerializeIF.h" +#include "../serialize/SerializeAdapter.h" + +/** + * 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>. + * Right now, the SerialBufferAdapter must always + * be initialized with the buffer and size ! + * + * \ingroup serialize + */ +template +class SerialBufferAdapter: public SerializeIF { +public: + + /** + * Constructor for constant uint8_t buffer. Length field can be serialized optionally. + * Type of length can be supplied as template type. + * @param buffer + * @param bufferLength + * @param serializeLength + */ + SerialBufferAdapter(const uint8_t* buffer, count_t bufferLength, + bool serializeLength = false); + + /** + * Constructor for non-constant uint8_t buffer. + * Length field can be serialized optionally. + * Type of length can be supplied as template type. + * @param buffer + * @param bufferLength + * @param serializeLength Length field will be serialized with size count_t + */ + SerialBufferAdapter(uint8_t* buffer, count_t bufferLength, + bool serializeLength = false); + + virtual ~SerialBufferAdapter(); + + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const override; + + virtual size_t getSerializedSize() const override; + + /** + * @brief This function deserializes a buffer into the member buffer. + * @details + * If a length field is present, it is ignored, as the size should have + * been set in the constructor. If the size is not known beforehand, + * consider using SerialFixedArrayListAdapter instead. + * @param buffer [out] Resulting buffer + * @param size remaining size to deserialize, should be larger than buffer + * + size field size + * @param bigEndian + * @return + */ + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; + + uint8_t * getBuffer(); + const uint8_t * getConstBuffer(); + void setBuffer(uint8_t* buffer, count_t bufferLength); +private: + bool serializeLength = false; + const uint8_t *constBuffer = nullptr; + uint8_t *buffer = nullptr; + count_t bufferLength = 0; +}; + +#endif /* SERIALBUFFERADAPTER_H_ */ From 4abdc436fbd995ada2090bbb4ce4cc2b09c147bf Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 1 Sep 2020 11:51:43 +0200 Subject: [PATCH 283/653] Revert "renormalize CHB" This reverts commit a4d9c761a78831a963c06c5969410daedd48e4dd. --- contrib/sgp4/sgp4unit.cpp | 4180 +++++++++++++-------------- contrib/sgp4/sgp4unit.h | 234 +- devicehandlers/ChildHandlerBase.cpp | 90 +- devicehandlers/ChildHandlerBase.h | 44 +- osal/FreeRTOS/TaskManagement.cpp | 48 +- osal/FreeRTOS/TaskManagement.h | 128 +- serialize/SerialBufferAdapter.cpp | 258 +- serialize/SerialBufferAdapter.h | 156 +- 8 files changed, 2569 insertions(+), 2569 deletions(-) diff --git a/contrib/sgp4/sgp4unit.cpp b/contrib/sgp4/sgp4unit.cpp index b707a7a2..24d63aa9 100644 --- a/contrib/sgp4/sgp4unit.cpp +++ b/contrib/sgp4/sgp4unit.cpp @@ -1,2090 +1,2090 @@ -/* ---------------------------------------------------------------- -* -* sgp4unit.cpp -* -* this file contains the sgp4 procedures for analytical propagation -* of a satellite. the code was originally released in the 1980 and 1986 -* spacetrack papers. a detailed discussion of the theory and history -* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, -* and kelso. -* -* companion code for -* fundamentals of astrodynamics and applications -* 2007 -* by david vallado -* -* (w) 719-573-2600, email dvallado@agi.com -* -* current : -* 16 nov 07 david vallado -* misc fixes for better compliance -* changes : -* 20 apr 07 david vallado -* misc fixes for constants -* 11 aug 06 david vallado -* chg lyddane choice back to strn3, constants, misc doc -* 15 dec 05 david vallado -* misc fixes -* 26 jul 05 david vallado -* fixes for paper -* note that each fix is preceded by a -* comment with "sgp4fix" and an explanation of -* what was changed -* 10 aug 04 david vallado -* 2nd printing baseline working -* 14 may 01 david vallado -* 2nd edition baseline -* 80 norad -* original baseline -* ---------------------------------------------------------------- */ - -#include "sgp4unit.h" - -const char help = 'n'; -FILE *dbgfile; - -#define pi 3.14159265358979323846 - - -/* ----------- local functions - only ever used internally by sgp4 ---------- */ -static void dpper - ( - double e3, double ee2, double peo, double pgho, double pho, - double pinco, double plo, double se2, double se3, double sgh2, - double sgh3, double sgh4, double sh2, double sh3, double si2, - double si3, double sl2, double sl3, double sl4, double t, - double xgh2, double xgh3, double xgh4, double xh2, double xh3, - double xi2, double xi3, double xl2, double xl3, double xl4, - double zmol, double zmos, double inclo, - char init, - double& ep, double& inclp, double& nodep, double& argpp, double& mp - ); - -static void dscom - ( - double epoch, double ep, double argpp, double tc, double inclp, - double nodep, double np, - double& snodm, double& cnodm, double& sinim, double& cosim, double& sinomm, - double& cosomm,double& day, double& e3, double& ee2, double& em, - double& emsq, double& gam, double& peo, double& pgho, double& pho, - double& pinco, double& plo, double& rtemsq, double& se2, double& se3, - double& sgh2, double& sgh3, double& sgh4, double& sh2, double& sh3, - double& si2, double& si3, double& sl2, double& sl3, double& sl4, - double& s1, double& s2, double& s3, double& s4, double& s5, - double& s6, double& s7, double& ss1, double& ss2, double& ss3, - double& ss4, double& ss5, double& ss6, double& ss7, double& sz1, - double& sz2, double& sz3, double& sz11, double& sz12, double& sz13, - double& sz21, double& sz22, double& sz23, double& sz31, double& sz32, - double& sz33, double& xgh2, double& xgh3, double& xgh4, double& xh2, - double& xh3, double& xi2, double& xi3, double& xl2, double& xl3, - double& xl4, double& nm, double& z1, double& z2, double& z3, - double& z11, double& z12, double& z13, double& z21, double& z22, - double& z23, double& z31, double& z32, double& z33, double& zmol, - double& zmos - ); - -static void dsinit - ( - gravconsttype whichconst, - double cosim, double emsq, double argpo, double s1, double s2, - double s3, double s4, double s5, double sinim, double ss1, - double ss2, double ss3, double ss4, double ss5, double sz1, - double sz3, double sz11, double sz13, double sz21, double sz23, - double sz31, double sz33, double t, double tc, double gsto, - double mo, double mdot, double no, double nodeo, double nodedot, - double xpidot, double z1, double z3, double z11, double z13, - double z21, double z23, double z31, double z33, double ecco, - double eccsq, double& em, double& argpm, double& inclm, double& mm, - double& nm, double& nodem, - int& irez, - double& atime, double& d2201, double& d2211, double& d3210, double& d3222, - double& d4410, double& d4422, double& d5220, double& d5232, double& d5421, - double& d5433, double& dedt, double& didt, double& dmdt, double& dndt, - double& dnodt, double& domdt, double& del1, double& del2, double& del3, - double& xfact, double& xlamo, double& xli, double& xni - ); - -static void dspace - ( - int irez, - double d2201, double d2211, double d3210, double d3222, double d4410, - double d4422, double d5220, double d5232, double d5421, double d5433, - double dedt, double del1, double del2, double del3, double didt, - double dmdt, double dnodt, double domdt, double argpo, double argpdot, - double t, double tc, double gsto, double xfact, double xlamo, - double no, - double& atime, double& em, double& argpm, double& inclm, double& xli, - double& mm, double& xni, double& nodem, double& dndt, double& nm - ); - -static void initl - ( - int satn, gravconsttype whichconst, - double ecco, double epoch, double inclo, double& no, - char& method, - double& ainv, double& ao, double& con41, double& con42, double& cosio, - double& cosio2,double& eccsq, double& omeosq, double& posq, - double& rp, double& rteosq,double& sinio , double& gsto - ); - -/* ----------------------------------------------------------------------------- -* -* procedure dpper -* -* this procedure provides deep space long period periodic contributions -* to the mean elements. by design, these periodics are zero at epoch. -* this used to be dscom which included initialization, but it's really a -* recurring function. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* e3 - -* ee2 - -* peo - -* pgho - -* pho - -* pinco - -* plo - -* se2 , se3 , sgh2, sgh3, sgh4, sh2, sh3, si2, si3, sl2, sl3, sl4 - -* t - -* xh2, xh3, xi2, xi3, xl2, xl3, xl4 - -* zmol - -* zmos - -* ep - eccentricity 0.0 - 1.0 -* inclo - inclination - needed for lyddane modification -* nodep - right ascension of ascending node -* argpp - argument of perigee -* mp - mean anomaly -* -* outputs : -* ep - eccentricity 0.0 - 1.0 -* inclp - inclination -* nodep - right ascension of ascending node -* argpp - argument of perigee -* mp - mean anomaly -* -* locals : -* alfdp - -* betdp - -* cosip , sinip , cosop , sinop , -* dalf - -* dbet - -* dls - -* f2, f3 - -* pe - -* pgh - -* ph - -* pinc - -* pl - -* sel , ses , sghl , sghs , shl , shs , sil , sinzf , sis , -* sll , sls -* xls - -* xnoh - -* zf - -* zm - -* -* coupling : -* none. -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void dpper - ( - double e3, double ee2, double peo, double pgho, double pho, - double pinco, double plo, double se2, double se3, double sgh2, - double sgh3, double sgh4, double sh2, double sh3, double si2, - double si3, double sl2, double sl3, double sl4, double t, - double xgh2, double xgh3, double xgh4, double xh2, double xh3, - double xi2, double xi3, double xl2, double xl3, double xl4, - double zmol, double zmos, double inclo, - char init, - double& ep, double& inclp, double& nodep, double& argpp, double& mp - ) -{ - /* --------------------- local variables ------------------------ */ - const double twopi = 2.0 * pi; - double alfdp, betdp, cosip, cosop, dalf, dbet, dls, - f2, f3, pe, pgh, ph, pinc, pl , - sel, ses, sghl, sghs, shll, shs, sil, - sinip, sinop, sinzf, sis, sll, sls, xls, - xnoh, zf, zm, zel, zes, znl, zns; - - /* ---------------------- constants ----------------------------- */ - zns = 1.19459e-5; - zes = 0.01675; - znl = 1.5835218e-4; - zel = 0.05490; - - /* --------------- calculate time varying periodics ----------- */ - zm = zmos + zns * t; - // be sure that the initial call has time set to zero - if (init == 'y') - zm = zmos; - zf = zm + 2.0 * zes * sin(zm); - sinzf = sin(zf); - f2 = 0.5 * sinzf * sinzf - 0.25; - f3 = -0.5 * sinzf * cos(zf); - ses = se2* f2 + se3 * f3; - sis = si2 * f2 + si3 * f3; - sls = sl2 * f2 + sl3 * f3 + sl4 * sinzf; - sghs = sgh2 * f2 + sgh3 * f3 + sgh4 * sinzf; - shs = sh2 * f2 + sh3 * f3; - zm = zmol + znl * t; - if (init == 'y') - zm = zmol; - zf = zm + 2.0 * zel * sin(zm); - sinzf = sin(zf); - f2 = 0.5 * sinzf * sinzf - 0.25; - f3 = -0.5 * sinzf * cos(zf); - sel = ee2 * f2 + e3 * f3; - sil = xi2 * f2 + xi3 * f3; - sll = xl2 * f2 + xl3 * f3 + xl4 * sinzf; - sghl = xgh2 * f2 + xgh3 * f3 + xgh4 * sinzf; - shll = xh2 * f2 + xh3 * f3; - pe = ses + sel; - pinc = sis + sil; - pl = sls + sll; - pgh = sghs + sghl; - ph = shs + shll; - - if (init == 'n') - { - pe = pe - peo; - pinc = pinc - pinco; - pl = pl - plo; - pgh = pgh - pgho; - ph = ph - pho; - inclp = inclp + pinc; - ep = ep + pe; - sinip = sin(inclp); - cosip = cos(inclp); - - /* ----------------- apply periodics directly ------------ */ - // sgp4fix for lyddane choice - // strn3 used original inclination - this is technically feasible - // gsfc used perturbed inclination - also technically feasible - // probably best to readjust the 0.2 limit value and limit discontinuity - // 0.2 rad = 11.45916 deg - // use next line for original strn3 approach and original inclination - // if (inclo >= 0.2) - // use next line for gsfc version and perturbed inclination - if (inclp >= 0.2) - { - ph = ph / sinip; - pgh = pgh - cosip * ph; - argpp = argpp + pgh; - nodep = nodep + ph; - mp = mp + pl; - } - else - { - /* ---- apply periodics with lyddane modification ---- */ - sinop = sin(nodep); - cosop = cos(nodep); - alfdp = sinip * sinop; - betdp = sinip * cosop; - dalf = ph * cosop + pinc * cosip * sinop; - dbet = -ph * sinop + pinc * cosip * cosop; - alfdp = alfdp + dalf; - betdp = betdp + dbet; - nodep = fmod(nodep, twopi); - // sgp4fix for afspc written intrinsic functions - // nodep used without a trigonometric function ahead - if (nodep < 0.0) - nodep = nodep + twopi; - xls = mp + argpp + cosip * nodep; - dls = pl + pgh - pinc * nodep * sinip; - xls = xls + dls; - xnoh = nodep; - nodep = atan2(alfdp, betdp); - // sgp4fix for afspc written intrinsic functions - // nodep used without a trigonometric function ahead - if (nodep < 0.0) - nodep = nodep + twopi; - if (fabs(xnoh - nodep) > pi){ - if (nodep < xnoh) - nodep = nodep + twopi; - else - nodep = nodep - twopi; - } - mp = mp + pl; - argpp = xls - mp - cosip * nodep; - } - } // if init == 'n' - -//#include "debug1.cpp" -} // end dpper - -/*----------------------------------------------------------------------------- -* -* procedure dscom -* -* this procedure provides deep space common items used by both the secular -* and periodics subroutines. input is provided as shown. this routine -* used to be called dpper, but the functions inside weren't well organized. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* epoch - -* ep - eccentricity -* argpp - argument of perigee -* tc - -* inclp - inclination -* nodep - right ascension of ascending node -* np - mean motion -* -* outputs : -* sinim , cosim , sinomm , cosomm , snodm , cnodm -* day - -* e3 - -* ee2 - -* em - eccentricity -* emsq - eccentricity squared -* gam - -* peo - -* pgho - -* pho - -* pinco - -* plo - -* rtemsq - -* se2, se3 - -* sgh2, sgh3, sgh4 - -* sh2, sh3, si2, si3, sl2, sl3, sl4 - -* s1, s2, s3, s4, s5, s6, s7 - -* ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3 - -* sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33 - -* xgh2, xgh3, xgh4, xh2, xh3, xi2, xi3, xl2, xl3, xl4 - -* nm - mean motion -* z1, z2, z3, z11, z12, z13, z21, z22, z23, z31, z32, z33 - -* zmol - -* zmos - -* -* locals : -* a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 - -* betasq - -* cc - -* ctem, stem - -* x1, x2, x3, x4, x5, x6, x7, x8 - -* xnodce - -* xnoi - -* zcosg , zsing , zcosgl , zsingl , zcosh , zsinh , zcoshl , zsinhl , -* zcosi , zsini , zcosil , zsinil , -* zx - -* zy - -* -* coupling : -* none. -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void dscom - ( - double epoch, double ep, double argpp, double tc, double inclp, - double nodep, double np, - double& snodm, double& cnodm, double& sinim, double& cosim, double& sinomm, - double& cosomm,double& day, double& e3, double& ee2, double& em, - double& emsq, double& gam, double& peo, double& pgho, double& pho, - double& pinco, double& plo, double& rtemsq, double& se2, double& se3, - double& sgh2, double& sgh3, double& sgh4, double& sh2, double& sh3, - double& si2, double& si3, double& sl2, double& sl3, double& sl4, - double& s1, double& s2, double& s3, double& s4, double& s5, - double& s6, double& s7, double& ss1, double& ss2, double& ss3, - double& ss4, double& ss5, double& ss6, double& ss7, double& sz1, - double& sz2, double& sz3, double& sz11, double& sz12, double& sz13, - double& sz21, double& sz22, double& sz23, double& sz31, double& sz32, - double& sz33, double& xgh2, double& xgh3, double& xgh4, double& xh2, - double& xh3, double& xi2, double& xi3, double& xl2, double& xl3, - double& xl4, double& nm, double& z1, double& z2, double& z3, - double& z11, double& z12, double& z13, double& z21, double& z22, - double& z23, double& z31, double& z32, double& z33, double& zmol, - double& zmos - ) -{ - /* -------------------------- constants ------------------------- */ - const double zes = 0.01675; - const double zel = 0.05490; - const double c1ss = 2.9864797e-6; - const double c1l = 4.7968065e-7; - const double zsinis = 0.39785416; - const double zcosis = 0.91744867; - const double zcosgs = 0.1945905; - const double zsings = -0.98088458; - const double twopi = 2.0 * pi; - - /* --------------------- local variables ------------------------ */ - int lsflg; - double a1 , a2 , a3 , a4 , a5 , a6 , a7 , - a8 , a9 , a10 , betasq, cc , ctem , stem , - x1 , x2 , x3 , x4 , x5 , x6 , x7 , - x8 , xnodce, xnoi , zcosg , zcosgl, zcosh , zcoshl, - zcosi , zcosil, zsing , zsingl, zsinh , zsinhl, zsini , - zsinil, zx , zy; - - nm = np; - em = ep; - snodm = sin(nodep); - cnodm = cos(nodep); - sinomm = sin(argpp); - cosomm = cos(argpp); - sinim = sin(inclp); - cosim = cos(inclp); - emsq = em * em; - betasq = 1.0 - emsq; - rtemsq = sqrt(betasq); - - /* ----------------- initialize lunar solar terms --------------- */ - peo = 0.0; - pinco = 0.0; - plo = 0.0; - pgho = 0.0; - pho = 0.0; - day = epoch + 18261.5 + tc / 1440.0; - xnodce = fmod(4.5236020 - 9.2422029e-4 * day, twopi); - stem = sin(xnodce); - ctem = cos(xnodce); - zcosil = 0.91375164 - 0.03568096 * ctem; - zsinil = sqrt(1.0 - zcosil * zcosil); - zsinhl = 0.089683511 * stem / zsinil; - zcoshl = sqrt(1.0 - zsinhl * zsinhl); - gam = 5.8351514 + 0.0019443680 * day; - zx = 0.39785416 * stem / zsinil; - zy = zcoshl * ctem + 0.91744867 * zsinhl * stem; - zx = atan2(zx, zy); - zx = gam + zx - xnodce; - zcosgl = cos(zx); - zsingl = sin(zx); - - /* ------------------------- do solar terms --------------------- */ - zcosg = zcosgs; - zsing = zsings; - zcosi = zcosis; - zsini = zsinis; - zcosh = cnodm; - zsinh = snodm; - cc = c1ss; - xnoi = 1.0 / nm; - - for (lsflg = 1; lsflg <= 2; lsflg++) - { - a1 = zcosg * zcosh + zsing * zcosi * zsinh; - a3 = -zsing * zcosh + zcosg * zcosi * zsinh; - a7 = -zcosg * zsinh + zsing * zcosi * zcosh; - a8 = zsing * zsini; - a9 = zsing * zsinh + zcosg * zcosi * zcosh; - a10 = zcosg * zsini; - a2 = cosim * a7 + sinim * a8; - a4 = cosim * a9 + sinim * a10; - a5 = -sinim * a7 + cosim * a8; - a6 = -sinim * a9 + cosim * a10; - - x1 = a1 * cosomm + a2 * sinomm; - x2 = a3 * cosomm + a4 * sinomm; - x3 = -a1 * sinomm + a2 * cosomm; - x4 = -a3 * sinomm + a4 * cosomm; - x5 = a5 * sinomm; - x6 = a6 * sinomm; - x7 = a5 * cosomm; - x8 = a6 * cosomm; - - z31 = 12.0 * x1 * x1 - 3.0 * x3 * x3; - z32 = 24.0 * x1 * x2 - 6.0 * x3 * x4; - z33 = 12.0 * x2 * x2 - 3.0 * x4 * x4; - z1 = 3.0 * (a1 * a1 + a2 * a2) + z31 * emsq; - z2 = 6.0 * (a1 * a3 + a2 * a4) + z32 * emsq; - z3 = 3.0 * (a3 * a3 + a4 * a4) + z33 * emsq; - z11 = -6.0 * a1 * a5 + emsq * (-24.0 * x1 * x7-6.0 * x3 * x5); - z12 = -6.0 * (a1 * a6 + a3 * a5) + emsq * - (-24.0 * (x2 * x7 + x1 * x8) - 6.0 * (x3 * x6 + x4 * x5)); - z13 = -6.0 * a3 * a6 + emsq * (-24.0 * x2 * x8 - 6.0 * x4 * x6); - z21 = 6.0 * a2 * a5 + emsq * (24.0 * x1 * x5 - 6.0 * x3 * x7); - z22 = 6.0 * (a4 * a5 + a2 * a6) + emsq * - (24.0 * (x2 * x5 + x1 * x6) - 6.0 * (x4 * x7 + x3 * x8)); - z23 = 6.0 * a4 * a6 + emsq * (24.0 * x2 * x6 - 6.0 * x4 * x8); - z1 = z1 + z1 + betasq * z31; - z2 = z2 + z2 + betasq * z32; - z3 = z3 + z3 + betasq * z33; - s3 = cc * xnoi; - s2 = -0.5 * s3 / rtemsq; - s4 = s3 * rtemsq; - s1 = -15.0 * em * s4; - s5 = x1 * x3 + x2 * x4; - s6 = x2 * x3 + x1 * x4; - s7 = x2 * x4 - x1 * x3; - - /* ----------------------- do lunar terms ------------------- */ - if (lsflg == 1) - { - ss1 = s1; - ss2 = s2; - ss3 = s3; - ss4 = s4; - ss5 = s5; - ss6 = s6; - ss7 = s7; - sz1 = z1; - sz2 = z2; - sz3 = z3; - sz11 = z11; - sz12 = z12; - sz13 = z13; - sz21 = z21; - sz22 = z22; - sz23 = z23; - sz31 = z31; - sz32 = z32; - sz33 = z33; - zcosg = zcosgl; - zsing = zsingl; - zcosi = zcosil; - zsini = zsinil; - zcosh = zcoshl * cnodm + zsinhl * snodm; - zsinh = snodm * zcoshl - cnodm * zsinhl; - cc = c1l; - } - } - - zmol = fmod(4.7199672 + 0.22997150 * day - gam, twopi); - zmos = fmod(6.2565837 + 0.017201977 * day, twopi); - - /* ------------------------ do solar terms ---------------------- */ - se2 = 2.0 * ss1 * ss6; - se3 = 2.0 * ss1 * ss7; - si2 = 2.0 * ss2 * sz12; - si3 = 2.0 * ss2 * (sz13 - sz11); - sl2 = -2.0 * ss3 * sz2; - sl3 = -2.0 * ss3 * (sz3 - sz1); - sl4 = -2.0 * ss3 * (-21.0 - 9.0 * emsq) * zes; - sgh2 = 2.0 * ss4 * sz32; - sgh3 = 2.0 * ss4 * (sz33 - sz31); - sgh4 = -18.0 * ss4 * zes; - sh2 = -2.0 * ss2 * sz22; - sh3 = -2.0 * ss2 * (sz23 - sz21); - - /* ------------------------ do lunar terms ---------------------- */ - ee2 = 2.0 * s1 * s6; - e3 = 2.0 * s1 * s7; - xi2 = 2.0 * s2 * z12; - xi3 = 2.0 * s2 * (z13 - z11); - xl2 = -2.0 * s3 * z2; - xl3 = -2.0 * s3 * (z3 - z1); - xl4 = -2.0 * s3 * (-21.0 - 9.0 * emsq) * zel; - xgh2 = 2.0 * s4 * z32; - xgh3 = 2.0 * s4 * (z33 - z31); - xgh4 = -18.0 * s4 * zel; - xh2 = -2.0 * s2 * z22; - xh3 = -2.0 * s2 * (z23 - z21); - -//#include "debug2.cpp" -} // end dscom - -/*----------------------------------------------------------------------------- -* -* procedure dsinit -* -* this procedure provides deep space contributions to mean motion dot due -* to geopotential resonance with half day and one day orbits. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* cosim, sinim- -* emsq - eccentricity squared -* argpo - argument of perigee -* s1, s2, s3, s4, s5 - -* ss1, ss2, ss3, ss4, ss5 - -* sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33 - -* t - time -* tc - -* gsto - greenwich sidereal time rad -* mo - mean anomaly -* mdot - mean anomaly dot (rate) -* no - mean motion -* nodeo - right ascension of ascending node -* nodedot - right ascension of ascending node dot (rate) -* xpidot - -* z1, z3, z11, z13, z21, z23, z31, z33 - -* eccm - eccentricity -* argpm - argument of perigee -* inclm - inclination -* mm - mean anomaly -* xn - mean motion -* nodem - right ascension of ascending node -* -* outputs : -* em - eccentricity -* argpm - argument of perigee -* inclm - inclination -* mm - mean anomaly -* nm - mean motion -* nodem - right ascension of ascending node -* irez - flag for resonance 0-none, 1-one day, 2-half day -* atime - -* d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 - -* dedt - -* didt - -* dmdt - -* dndt - -* dnodt - -* domdt - -* del1, del2, del3 - -* ses , sghl , sghs , sgs , shl , shs , sis , sls -* theta - -* xfact - -* xlamo - -* xli - -* xni -* -* locals : -* ainv2 - -* aonv - -* cosisq - -* eoc - -* f220, f221, f311, f321, f322, f330, f441, f442, f522, f523, f542, f543 - -* g200, g201, g211, g300, g310, g322, g410, g422, g520, g521, g532, g533 - -* sini2 - -* temp - -* temp1 - -* theta - -* xno2 - -* -* coupling : -* getgravconst -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void dsinit - ( - gravconsttype whichconst, - double cosim, double emsq, double argpo, double s1, double s2, - double s3, double s4, double s5, double sinim, double ss1, - double ss2, double ss3, double ss4, double ss5, double sz1, - double sz3, double sz11, double sz13, double sz21, double sz23, - double sz31, double sz33, double t, double tc, double gsto, - double mo, double mdot, double no, double nodeo, double nodedot, - double xpidot, double z1, double z3, double z11, double z13, - double z21, double z23, double z31, double z33, double ecco, - double eccsq, double& em, double& argpm, double& inclm, double& mm, - double& nm, double& nodem, - int& irez, - double& atime, double& d2201, double& d2211, double& d3210, double& d3222, - double& d4410, double& d4422, double& d5220, double& d5232, double& d5421, - double& d5433, double& dedt, double& didt, double& dmdt, double& dndt, - double& dnodt, double& domdt, double& del1, double& del2, double& del3, - double& xfact, double& xlamo, double& xli, double& xni - ) -{ - /* --------------------- local variables ------------------------ */ - const double twopi = 2.0 * pi; - - double ainv2 , aonv=0.0, cosisq, eoc, f220 , f221 , f311 , - f321 , f322 , f330 , f441 , f442 , f522 , f523 , - f542 , f543 , g200 , g201 , g211 , g300 , g310 , - g322 , g410 , g422 , g520 , g521 , g532 , g533 , - ses , sgs , sghl , sghs , shs , shll , sis , - sini2 , sls , temp , temp1 , theta , xno2 , q22 , - q31 , q33 , root22, root44, root54, rptim , root32, - root52, x2o3 , xke , znl , emo , zns , emsqo, - tumin, mu, radiusearthkm, j2, j3, j4, j3oj2; - - q22 = 1.7891679e-6; - q31 = 2.1460748e-6; - q33 = 2.2123015e-7; - root22 = 1.7891679e-6; - root44 = 7.3636953e-9; - root54 = 2.1765803e-9; - rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec - root32 = 3.7393792e-7; - root52 = 1.1428639e-7; - x2o3 = 2.0 / 3.0; - znl = 1.5835218e-4; - zns = 1.19459e-5; - - // sgp4fix identify constants and allow alternate values - getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); - - /* -------------------- deep space initialization ------------ */ - irez = 0; - if ((nm < 0.0052359877) && (nm > 0.0034906585)) - irez = 1; - if ((nm >= 8.26e-3) && (nm <= 9.24e-3) && (em >= 0.5)) - irez = 2; - - /* ------------------------ do solar terms ------------------- */ - ses = ss1 * zns * ss5; - sis = ss2 * zns * (sz11 + sz13); - sls = -zns * ss3 * (sz1 + sz3 - 14.0 - 6.0 * emsq); - sghs = ss4 * zns * (sz31 + sz33 - 6.0); - shs = -zns * ss2 * (sz21 + sz23); - // sgp4fix for 180 deg incl - if ((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2)) - shs = 0.0; - if (sinim != 0.0) - shs = shs / sinim; - sgs = sghs - cosim * shs; - - /* ------------------------- do lunar terms ------------------ */ - dedt = ses + s1 * znl * s5; - didt = sis + s2 * znl * (z11 + z13); - dmdt = sls - znl * s3 * (z1 + z3 - 14.0 - 6.0 * emsq); - sghl = s4 * znl * (z31 + z33 - 6.0); - shll = -znl * s2 * (z21 + z23); - // sgp4fix for 180 deg incl - if ((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2)) - shll = 0.0; - domdt = sgs + sghl; - dnodt = shs; - if (sinim != 0.0) - { - domdt = domdt - cosim / sinim * shll; - dnodt = dnodt + shll / sinim; - } - - /* ----------- calculate deep space resonance effects -------- */ - dndt = 0.0; - theta = fmod(gsto + tc * rptim, twopi); - em = em + dedt * t; - inclm = inclm + didt * t; - argpm = argpm + domdt * t; - nodem = nodem + dnodt * t; - mm = mm + dmdt * t; - // sgp4fix for negative inclinations - // the following if statement should be commented out - //if (inclm < 0.0) - // { - // inclm = -inclm; - // argpm = argpm - pi; - // nodem = nodem + pi; - // } - - /* -------------- initialize the resonance terms ------------- */ - if (irez != 0) - { - aonv = pow(nm / xke, x2o3); - - /* ---------- geopotential resonance for 12 hour orbits ------ */ - if (irez == 2) - { - cosisq = cosim * cosim; - emo = em; - em = ecco; - emsqo = emsq; - emsq = eccsq; - eoc = em * emsq; - g201 = -0.306 - (em - 0.64) * 0.440; - - if (em <= 0.65) - { - g211 = 3.616 - 13.2470 * em + 16.2900 * emsq; - g310 = -19.302 + 117.3900 * em - 228.4190 * emsq + 156.5910 * eoc; - g322 = -18.9068 + 109.7927 * em - 214.6334 * emsq + 146.5816 * eoc; - g410 = -41.122 + 242.6940 * em - 471.0940 * emsq + 313.9530 * eoc; - g422 = -146.407 + 841.8800 * em - 1629.014 * emsq + 1083.4350 * eoc; - g520 = -532.114 + 3017.977 * em - 5740.032 * emsq + 3708.2760 * eoc; - } - else - { - g211 = -72.099 + 331.819 * em - 508.738 * emsq + 266.724 * eoc; - g310 = -346.844 + 1582.851 * em - 2415.925 * emsq + 1246.113 * eoc; - g322 = -342.585 + 1554.908 * em - 2366.899 * emsq + 1215.972 * eoc; - g410 = -1052.797 + 4758.686 * em - 7193.992 * emsq + 3651.957 * eoc; - g422 = -3581.690 + 16178.110 * em - 24462.770 * emsq + 12422.520 * eoc; - if (em > 0.715) - g520 =-5149.66 + 29936.92 * em - 54087.36 * emsq + 31324.56 * eoc; - else - g520 = 1464.74 - 4664.75 * em + 3763.64 * emsq; - } - if (em < 0.7) - { - g533 = -919.22770 + 4988.6100 * em - 9064.7700 * emsq + 5542.21 * eoc; - g521 = -822.71072 + 4568.6173 * em - 8491.4146 * emsq + 5337.524 * eoc; - g532 = -853.66600 + 4690.2500 * em - 8624.7700 * emsq + 5341.4 * eoc; - } - else - { - g533 =-37995.780 + 161616.52 * em - 229838.20 * emsq + 109377.94 * eoc; - g521 =-51752.104 + 218913.95 * em - 309468.16 * emsq + 146349.42 * eoc; - g532 =-40023.880 + 170470.89 * em - 242699.48 * emsq + 115605.82 * eoc; - } - - sini2= sinim * sinim; - f220 = 0.75 * (1.0 + 2.0 * cosim+cosisq); - f221 = 1.5 * sini2; - f321 = 1.875 * sinim * (1.0 - 2.0 * cosim - 3.0 * cosisq); - f322 = -1.875 * sinim * (1.0 + 2.0 * cosim - 3.0 * cosisq); - f441 = 35.0 * sini2 * f220; - f442 = 39.3750 * sini2 * sini2; - f522 = 9.84375 * sinim * (sini2 * (1.0 - 2.0 * cosim- 5.0 * cosisq) + - 0.33333333 * (-2.0 + 4.0 * cosim + 6.0 * cosisq) ); - f523 = sinim * (4.92187512 * sini2 * (-2.0 - 4.0 * cosim + - 10.0 * cosisq) + 6.56250012 * (1.0+2.0 * cosim - 3.0 * cosisq)); - f542 = 29.53125 * sinim * (2.0 - 8.0 * cosim+cosisq * - (-12.0 + 8.0 * cosim + 10.0 * cosisq)); - f543 = 29.53125 * sinim * (-2.0 - 8.0 * cosim+cosisq * - (12.0 + 8.0 * cosim - 10.0 * cosisq)); - xno2 = nm * nm; - ainv2 = aonv * aonv; - temp1 = 3.0 * xno2 * ainv2; - temp = temp1 * root22; - d2201 = temp * f220 * g201; - d2211 = temp * f221 * g211; - temp1 = temp1 * aonv; - temp = temp1 * root32; - d3210 = temp * f321 * g310; - d3222 = temp * f322 * g322; - temp1 = temp1 * aonv; - temp = 2.0 * temp1 * root44; - d4410 = temp * f441 * g410; - d4422 = temp * f442 * g422; - temp1 = temp1 * aonv; - temp = temp1 * root52; - d5220 = temp * f522 * g520; - d5232 = temp * f523 * g532; - temp = 2.0 * temp1 * root54; - d5421 = temp * f542 * g521; - d5433 = temp * f543 * g533; - xlamo = fmod(mo + nodeo + nodeo-theta - theta, twopi); - xfact = mdot + dmdt + 2.0 * (nodedot + dnodt - rptim) - no; - em = emo; - emsq = emsqo; - } - - /* ---------------- synchronous resonance terms -------------- */ - if (irez == 1) - { - g200 = 1.0 + emsq * (-2.5 + 0.8125 * emsq); - g310 = 1.0 + 2.0 * emsq; - g300 = 1.0 + emsq * (-6.0 + 6.60937 * emsq); - f220 = 0.75 * (1.0 + cosim) * (1.0 + cosim); - f311 = 0.9375 * sinim * sinim * (1.0 + 3.0 * cosim) - 0.75 * (1.0 + cosim); - f330 = 1.0 + cosim; - f330 = 1.875 * f330 * f330 * f330; - del1 = 3.0 * nm * nm * aonv * aonv; - del2 = 2.0 * del1 * f220 * g200 * q22; - del3 = 3.0 * del1 * f330 * g300 * q33 * aonv; - del1 = del1 * f311 * g310 * q31 * aonv; - xlamo = fmod(mo + nodeo + argpo - theta, twopi); - xfact = mdot + xpidot - rptim + dmdt + domdt + dnodt - no; - } - - /* ------------ for sgp4, initialize the integrator ---------- */ - xli = xlamo; - xni = no; - atime = 0.0; - nm = no + dndt; - } - -//#include "debug3.cpp" -} // end dsinit - -/*----------------------------------------------------------------------------- -* -* procedure dspace -* -* this procedure provides deep space contributions to mean elements for -* perturbing third body. these effects have been averaged over one -* revolution of the sun and moon. for earth resonance effects, the -* effects have been averaged over no revolutions of the satellite. -* (mean motion) -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 - -* dedt - -* del1, del2, del3 - -* didt - -* dmdt - -* dnodt - -* domdt - -* irez - flag for resonance 0-none, 1-one day, 2-half day -* argpo - argument of perigee -* argpdot - argument of perigee dot (rate) -* t - time -* tc - -* gsto - gst -* xfact - -* xlamo - -* no - mean motion -* atime - -* em - eccentricity -* ft - -* argpm - argument of perigee -* inclm - inclination -* xli - -* mm - mean anomaly -* xni - mean motion -* nodem - right ascension of ascending node -* -* outputs : -* atime - -* em - eccentricity -* argpm - argument of perigee -* inclm - inclination -* xli - -* mm - mean anomaly -* xni - -* nodem - right ascension of ascending node -* dndt - -* nm - mean motion -* -* locals : -* delt - -* ft - -* theta - -* x2li - -* x2omi - -* xl - -* xldot - -* xnddt - -* xndt - -* xomi - -* -* coupling : -* none - -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void dspace - ( - int irez, - double d2201, double d2211, double d3210, double d3222, double d4410, - double d4422, double d5220, double d5232, double d5421, double d5433, - double dedt, double del1, double del2, double del3, double didt, - double dmdt, double dnodt, double domdt, double argpo, double argpdot, - double t, double tc, double gsto, double xfact, double xlamo, - double no, - double& atime, double& em, double& argpm, double& inclm, double& xli, - double& mm, double& xni, double& nodem, double& dndt, double& nm - ) -{ - const double twopi = 2.0 * pi; - int iretn , iret; - double delt, ft, theta, x2li, x2omi, xl, xldot , xnddt, xndt, xomi, g22, g32, - g44, g52, g54, fasx2, fasx4, fasx6, rptim , step2, stepn , stepp; - - ft = 0.0; - fasx2 = 0.13130908; - fasx4 = 2.8843198; - fasx6 = 0.37448087; - g22 = 5.7686396; - g32 = 0.95240898; - g44 = 1.8014998; - g52 = 1.0508330; - g54 = 4.4108898; - rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec - stepp = 720.0; - stepn = -720.0; - step2 = 259200.0; - - /* ----------- calculate deep space resonance effects ----------- */ - dndt = 0.0; - theta = fmod(gsto + tc * rptim, twopi); - em = em + dedt * t; - - inclm = inclm + didt * t; - argpm = argpm + domdt * t; - nodem = nodem + dnodt * t; - mm = mm + dmdt * t; - - // sgp4fix for negative inclinations - // the following if statement should be commented out - // if (inclm < 0.0) - // { - // inclm = -inclm; - // argpm = argpm - pi; - // nodem = nodem + pi; - // } - - /* - update resonances : numerical (euler-maclaurin) integration - */ - /* ------------------------- epoch restart ---------------------- */ - // sgp4fix for propagator problems - // the following integration works for negative time steps and periods - // the specific changes are unknown because the original code was so convoluted - - ft = 0.0; - atime = 0.0; - if (irez != 0) - { - if ((atime == 0.0) || ((t >= 0.0) && (atime < 0.0)) || - ((t < 0.0) && (atime >= 0.0))) - { - if (t >= 0.0) - delt = stepp; - else - delt = stepn; - atime = 0.0; - xni = no; - xli = xlamo; - } - iretn = 381; // added for do loop - iret = 0; // added for loop - while (iretn == 381) - { - if ((fabs(t) < fabs(atime)) || (iret == 351)) - { - if (t >= 0.0) - delt = stepn; - else - delt = stepp; - iret = 351; - iretn = 381; - } - else - { - if (t > 0.0) // error if prev if has atime:=0.0 and t:=0.0 (ge) - delt = stepp; - else - delt = stepn; - if (fabs(t - atime) >= stepp) - { - iret = 0; - iretn = 381; - } - else - { - ft = t - atime; - iretn = 0; - } - } - - /* ------------------- dot terms calculated ------------- */ - /* ----------- near - synchronous resonance terms ------- */ - if (irez != 2) - { - xndt = del1 * sin(xli - fasx2) + del2 * sin(2.0 * (xli - fasx4)) + - del3 * sin(3.0 * (xli - fasx6)); - xldot = xni + xfact; - xnddt = del1 * cos(xli - fasx2) + - 2.0 * del2 * cos(2.0 * (xli - fasx4)) + - 3.0 * del3 * cos(3.0 * (xli - fasx6)); - xnddt = xnddt * xldot; - } - else - { - /* --------- near - half-day resonance terms -------- */ - xomi = argpo + argpdot * atime; - x2omi = xomi + xomi; - x2li = xli + xli; - xndt = d2201 * sin(x2omi + xli - g22) + d2211 * sin(xli - g22) + - d3210 * sin(xomi + xli - g32) + d3222 * sin(-xomi + xli - g32)+ - d4410 * sin(x2omi + x2li - g44)+ d4422 * sin(x2li - g44) + - d5220 * sin(xomi + xli - g52) + d5232 * sin(-xomi + xli - g52)+ - d5421 * sin(xomi + x2li - g54) + d5433 * sin(-xomi + x2li - g54); - xldot = xni + xfact; - xnddt = d2201 * cos(x2omi + xli - g22) + d2211 * cos(xli - g22) + - d3210 * cos(xomi + xli - g32) + d3222 * cos(-xomi + xli - g32) + - d5220 * cos(xomi + xli - g52) + d5232 * cos(-xomi + xli - g52) + - 2.0 * (d4410 * cos(x2omi + x2li - g44) + - d4422 * cos(x2li - g44) + d5421 * cos(xomi + x2li - g54) + - d5433 * cos(-xomi + x2li - g54)); - xnddt = xnddt * xldot; - } - - /* ----------------------- integrator ------------------- */ - if (iretn == 381) - { - xli = xli + xldot * delt + xndt * step2; - xni = xni + xndt * delt + xnddt * step2; - atime = atime + delt; - } - } // while iretn = 381 - - nm = xni + xndt * ft + xnddt * ft * ft * 0.5; - xl = xli + xldot * ft + xndt * ft * ft * 0.5; - if (irez != 1) - { - mm = xl - 2.0 * nodem + 2.0 * theta; - dndt = nm - no; - } - else - { - mm = xl - nodem - argpm + theta; - dndt = nm - no; - } - nm = no + dndt; - } - -//#include "debug4.cpp" -} // end dsspace - -/*----------------------------------------------------------------------------- -* -* procedure initl -* -* this procedure initializes the spg4 propagator. all the initialization is -* consolidated here instead of having multiple loops inside other routines. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* ecco - eccentricity 0.0 - 1.0 -* epoch - epoch time in days from jan 0, 1950. 0 hr -* inclo - inclination of satellite -* no - mean motion of satellite -* satn - satellite number -* -* outputs : -* ainv - 1.0 / a -* ao - semi major axis -* con41 - -* con42 - 1.0 - 5.0 cos(i) -* cosio - cosine of inclination -* cosio2 - cosio squared -* eccsq - eccentricity squared -* method - flag for deep space 'd', 'n' -* omeosq - 1.0 - ecco * ecco -* posq - semi-parameter squared -* rp - radius of perigee -* rteosq - square root of (1.0 - ecco*ecco) -* sinio - sine of inclination -* gsto - gst at time of observation rad -* no - mean motion of satellite -* -* locals : -* ak - -* d1 - -* del - -* adel - -* po - -* -* coupling : -* getgravconst -* gstime - find greenwich sidereal time from the julian date -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void initl - ( - int satn, gravconsttype whichconst, - double ecco, double epoch, double inclo, double& no, - char& method, - double& ainv, double& ao, double& con41, double& con42, double& cosio, - double& cosio2,double& eccsq, double& omeosq, double& posq, - double& rp, double& rteosq,double& sinio , double& gsto - ) -{ - /* --------------------- local variables ------------------------ */ - double ak, d1, del, adel, po, x2o3, j2, xke, - tumin, mu, radiusearthkm, j3, j4, j3oj2; - - // sgp4fix use old way of finding gst - int ids70; - double ts70, ds70, tfrac, c1, thgr70, fk5r, c1p2p; - const double twopi = 2.0 * pi; - - /* ----------------------- earth constants ---------------------- */ - // sgp4fix identify constants and allow alternate values - getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); - x2o3 = 2.0 / 3.0; - - /* ------------- calculate auxillary epoch quantities ---------- */ - eccsq = ecco * ecco; - omeosq = 1.0 - eccsq; - rteosq = sqrt(omeosq); - cosio = cos(inclo); - cosio2 = cosio * cosio; - - /* ------------------ un-kozai the mean motion ----------------- */ - ak = pow(xke / no, x2o3); - d1 = 0.75 * j2 * (3.0 * cosio2 - 1.0) / (rteosq * omeosq); - del = d1 / (ak * ak); - adel = ak * (1.0 - del * del - del * - (1.0 / 3.0 + 134.0 * del * del / 81.0)); - del = d1/(adel * adel); - no = no / (1.0 + del); - - ao = pow(xke / no, x2o3); - sinio = sin(inclo); - po = ao * omeosq; - con42 = 1.0 - 5.0 * cosio2; - con41 = -con42-cosio2-cosio2; - ainv = 1.0 / ao; - posq = po * po; - rp = ao * (1.0 - ecco); - method = 'n'; - - // sgp4fix modern approach to finding sidereal timew - // gsto = gstime(epoch + 2433281.5); - - // sgp4fix use old way of finding gst - // count integer number of days from 0 jan 1970 - ts70 = epoch - 7305.0; - ids70 = floor(ts70 + 1.0e-8); - ds70 = ids70; - tfrac = ts70 - ds70; - // find greenwich location at epoch - c1 = 1.72027916940703639e-2; - thgr70= 1.7321343856509374; - fk5r = 5.07551419432269442e-15; - c1p2p = c1 + twopi; - gsto = fmod( thgr70 + c1*ds70 + c1p2p*tfrac + ts70*ts70*fk5r, twopi); - if ( gsto < 0.0 ) - gsto = gsto + twopi; - -//#include "debug5.cpp" -} // end initl - -/*----------------------------------------------------------------------------- -* -* procedure sgp4init -* -* this procedure initializes variables for sgp4. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* satn - satellite number -* bstar - sgp4 type drag coefficient kg/m2er -* ecco - eccentricity -* epoch - epoch time in days from jan 0, 1950. 0 hr -* argpo - argument of perigee (output if ds) -* inclo - inclination -* mo - mean anomaly (output if ds) -* no - mean motion -* nodeo - right ascension of ascending node -* -* outputs : -* satrec - common values for subsequent calls -* return code - non-zero on error. -* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er -* 2 - mean motion less than 0.0 -* 3 - pert elements, ecc < 0.0 or ecc > 1.0 -* 4 - semi-latus rectum < 0.0 -* 5 - epoch elements are sub-orbital -* 6 - satellite has decayed -* -* locals : -* cnodm , snodm , cosim , sinim , cosomm , sinomm -* cc1sq , cc2 , cc3 -* coef , coef1 -* cosio4 - -* day - -* dndt - -* em - eccentricity -* emsq - eccentricity squared -* eeta - -* etasq - -* gam - -* argpm - argument of perigee -* nodem - -* inclm - inclination -* mm - mean anomaly -* nm - mean motion -* perige - perigee -* pinvsq - -* psisq - -* qzms24 - -* rtemsq - -* s1, s2, s3, s4, s5, s6, s7 - -* sfour - -* ss1, ss2, ss3, ss4, ss5, ss6, ss7 - -* sz1, sz2, sz3 -* sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33 - -* tc - -* temp - -* temp1, temp2, temp3 - -* tsi - -* xpidot - -* xhdot1 - -* z1, z2, z3 - -* z11, z12, z13, z21, z22, z23, z31, z32, z33 - -* -* coupling : -* getgravconst- -* initl - -* dscom - -* dpper - -* dsinit - -* sgp4 - -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -int sgp4init - ( - gravconsttype whichconst, const int satn, const double epoch, - const double xbstar, const double xecco, const double xargpo, - const double xinclo, const double xmo, const double xno, - const double xnodeo, elsetrec& satrec - ) -{ - /* --------------------- local variables ------------------------ */ - double ao, ainv, con42, cosio, sinio, cosio2, eccsq, - omeosq, posq, rp, rteosq, - cnodm , snodm , cosim , sinim , cosomm, sinomm, cc1sq , - cc2 , cc3 , coef , coef1 , cosio4, day , dndt , - em , emsq , eeta , etasq , gam , argpm , nodem , - inclm , mm , nm , perige, pinvsq, psisq , qzms24, - rtemsq, s1 , s2 , s3 , s4 , s5 , s6 , - s7 , sfour , ss1 = 0 , ss2 = 0 , ss3 = 0 , ss4 = 0 , ss5 = 0 , - ss6 = 0 , ss7 = 0 , sz1 = 0 , sz2 = 0 , sz3 = 0 , sz11 = 0 , sz12 = 0 , - sz13 = 0 , sz21 = 0 , sz22 = 0 , sz23 = 0 , sz31 = 0 , sz32 = 0 , sz33 = 0 , - tc , temp , temp1 , temp2 , temp3 , tsi , xpidot, - xhdot1, z1 , z2 , z3 , z11 , z12 , z13 , - z21 , z22 , z23 , z31 , z32 , z33, - qzms2t, ss, j2, j3oj2, j4, x2o3, r[3], v[3], - tumin, mu, radiusearthkm, xke, j3; - - /* ------------------------ initialization --------------------- */ - // sgp4fix divisor for divide by zero check on inclination - const double temp4 = 1.0 + cos(pi-1.0e-9); - - /* ----------- set all near earth variables to zero ------------ */ - satrec.isimp = 0; satrec.method = 'n'; satrec.aycof = 0.0; - satrec.con41 = 0.0; satrec.cc1 = 0.0; satrec.cc4 = 0.0; - satrec.cc5 = 0.0; satrec.d2 = 0.0; satrec.d3 = 0.0; - satrec.d4 = 0.0; satrec.delmo = 0.0; satrec.eta = 0.0; - satrec.argpdot = 0.0; satrec.omgcof = 0.0; satrec.sinmao = 0.0; - satrec.t = 0.0; satrec.t2cof = 0.0; satrec.t3cof = 0.0; - satrec.t4cof = 0.0; satrec.t5cof = 0.0; satrec.x1mth2 = 0.0; - satrec.x7thm1 = 0.0; satrec.mdot = 0.0; satrec.nodedot = 0.0; - satrec.xlcof = 0.0; satrec.xmcof = 0.0; satrec.nodecf = 0.0; - - /* ----------- set all deep space variables to zero ------------ */ - satrec.irez = 0; satrec.d2201 = 0.0; satrec.d2211 = 0.0; - satrec.d3210 = 0.0; satrec.d3222 = 0.0; satrec.d4410 = 0.0; - satrec.d4422 = 0.0; satrec.d5220 = 0.0; satrec.d5232 = 0.0; - satrec.d5421 = 0.0; satrec.d5433 = 0.0; satrec.dedt = 0.0; - satrec.del1 = 0.0; satrec.del2 = 0.0; satrec.del3 = 0.0; - satrec.didt = 0.0; satrec.dmdt = 0.0; satrec.dnodt = 0.0; - satrec.domdt = 0.0; satrec.e3 = 0.0; satrec.ee2 = 0.0; - satrec.peo = 0.0; satrec.pgho = 0.0; satrec.pho = 0.0; - satrec.pinco = 0.0; satrec.plo = 0.0; satrec.se2 = 0.0; - satrec.se3 = 0.0; satrec.sgh2 = 0.0; satrec.sgh3 = 0.0; - satrec.sgh4 = 0.0; satrec.sh2 = 0.0; satrec.sh3 = 0.0; - satrec.si2 = 0.0; satrec.si3 = 0.0; satrec.sl2 = 0.0; - satrec.sl3 = 0.0; satrec.sl4 = 0.0; satrec.gsto = 0.0; - satrec.xfact = 0.0; satrec.xgh2 = 0.0; satrec.xgh3 = 0.0; - satrec.xgh4 = 0.0; satrec.xh2 = 0.0; satrec.xh3 = 0.0; - satrec.xi2 = 0.0; satrec.xi3 = 0.0; satrec.xl2 = 0.0; - satrec.xl3 = 0.0; satrec.xl4 = 0.0; satrec.xlamo = 0.0; - satrec.zmol = 0.0; satrec.zmos = 0.0; satrec.atime = 0.0; - satrec.xli = 0.0; satrec.xni = 0.0; - - // sgp4fix - note the following variables are also passed directly via satrec. - // it is possible to streamline the sgp4init call by deleting the "x" - // variables, but the user would need to set the satrec.* values first. we - // include the additional assignments in case twoline2rv is not used. - satrec.bstar = xbstar; - satrec.ecco = xecco; - satrec.argpo = xargpo; - satrec.inclo = xinclo; - satrec.mo = xmo; - satrec.no = xno; - satrec.nodeo = xnodeo; - - /* ------------------------ earth constants ----------------------- */ - // sgp4fix identify constants and allow alternate values - getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); - ss = 78.0 / radiusearthkm + 1.0; - qzms2t = pow(((120.0 - 78.0) / radiusearthkm), 4); - x2o3 = 2.0 / 3.0; - - satrec.init = 'y'; - satrec.t = 0.0; - - initl - ( - satn, whichconst, satrec.ecco, epoch, satrec.inclo, satrec.no, satrec.method, - ainv, ao, satrec.con41, con42, cosio, cosio2, eccsq, omeosq, - posq, rp, rteosq, sinio, satrec.gsto - ); - satrec.error = 0; - - if (rp < 1.0) - { -// printf("# *** satn%d epoch elts sub-orbital ***\n", satn); - satrec.error = 5; - } - - if ((omeosq >= 0.0 ) || ( satrec.no >= 0.0)) - { - satrec.isimp = 0; - if (rp < (220.0 / radiusearthkm + 1.0)) - satrec.isimp = 1; - sfour = ss; - qzms24 = qzms2t; - perige = (rp - 1.0) * radiusearthkm; - - /* - for perigees below 156 km, s and qoms2t are altered - */ - if (perige < 156.0) - { - sfour = perige - 78.0; - if (perige < 98.0) - sfour = 20.0; - qzms24 = pow(((120.0 - sfour) / radiusearthkm), 4.0); - sfour = sfour / radiusearthkm + 1.0; - } - pinvsq = 1.0 / posq; - - tsi = 1.0 / (ao - sfour); - satrec.eta = ao * satrec.ecco * tsi; - etasq = satrec.eta * satrec.eta; - eeta = satrec.ecco * satrec.eta; - psisq = fabs(1.0 - etasq); - coef = qzms24 * pow(tsi, 4.0); - coef1 = coef / pow(psisq, 3.5); - cc2 = coef1 * satrec.no * (ao * (1.0 + 1.5 * etasq + eeta * - (4.0 + etasq)) + 0.375 * j2 * tsi / psisq * satrec.con41 * - (8.0 + 3.0 * etasq * (8.0 + etasq))); - satrec.cc1 = satrec.bstar * cc2; - cc3 = 0.0; - if (satrec.ecco > 1.0e-4) - cc3 = -2.0 * coef * tsi * j3oj2 * satrec.no * sinio / satrec.ecco; - satrec.x1mth2 = 1.0 - cosio2; - satrec.cc4 = 2.0* satrec.no * coef1 * ao * omeosq * - (satrec.eta * (2.0 + 0.5 * etasq) + satrec.ecco * - (0.5 + 2.0 * etasq) - j2 * tsi / (ao * psisq) * - (-3.0 * satrec.con41 * (1.0 - 2.0 * eeta + etasq * - (1.5 - 0.5 * eeta)) + 0.75 * satrec.x1mth2 * - (2.0 * etasq - eeta * (1.0 + etasq)) * cos(2.0 * satrec.argpo))); - satrec.cc5 = 2.0 * coef1 * ao * omeosq * (1.0 + 2.75 * - (etasq + eeta) + eeta * etasq); - cosio4 = cosio2 * cosio2; - temp1 = 1.5 * j2 * pinvsq * satrec.no; - temp2 = 0.5 * temp1 * j2 * pinvsq; - temp3 = -0.46875 * j4 * pinvsq * pinvsq * satrec.no; - satrec.mdot = satrec.no + 0.5 * temp1 * rteosq * satrec.con41 + 0.0625 * - temp2 * rteosq * (13.0 - 78.0 * cosio2 + 137.0 * cosio4); - satrec.argpdot = -0.5 * temp1 * con42 + 0.0625 * temp2 * - (7.0 - 114.0 * cosio2 + 395.0 * cosio4) + - temp3 * (3.0 - 36.0 * cosio2 + 49.0 * cosio4); - xhdot1 = -temp1 * cosio; - satrec.nodedot = xhdot1 + (0.5 * temp2 * (4.0 - 19.0 * cosio2) + - 2.0 * temp3 * (3.0 - 7.0 * cosio2)) * cosio; - xpidot = satrec.argpdot+ satrec.nodedot; - satrec.omgcof = satrec.bstar * cc3 * cos(satrec.argpo); - satrec.xmcof = 0.0; - if (satrec.ecco > 1.0e-4) - satrec.xmcof = -x2o3 * coef * satrec.bstar / eeta; - satrec.nodecf = 3.5 * omeosq * xhdot1 * satrec.cc1; - satrec.t2cof = 1.5 * satrec.cc1; - // sgp4fix for divide by zero with xinco = 180 deg - if (fabs(cosio+1.0) > 1.5e-12) - satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / (1.0 + cosio); - else - satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / temp4; - satrec.aycof = -0.5 * j3oj2 * sinio; - satrec.delmo = pow((1.0 + satrec.eta * cos(satrec.mo)), 3); - satrec.sinmao = sin(satrec.mo); - satrec.x7thm1 = 7.0 * cosio2 - 1.0; - - /* --------------- deep space initialization ------------- */ - if ((2*pi / satrec.no) >= 225.0) - { - satrec.method = 'd'; - satrec.isimp = 1; - tc = 0.0; - inclm = satrec.inclo; - - dscom - ( - epoch, satrec.ecco, satrec.argpo, tc, satrec.inclo, satrec.nodeo, - satrec.no, snodm, cnodm, sinim, cosim,sinomm, cosomm, - day, satrec.e3, satrec.ee2, em, emsq, gam, - satrec.peo, satrec.pgho, satrec.pho, satrec.pinco, - satrec.plo, rtemsq, satrec.se2, satrec.se3, - satrec.sgh2, satrec.sgh3, satrec.sgh4, - satrec.sh2, satrec.sh3, satrec.si2, satrec.si3, - satrec.sl2, satrec.sl3, satrec.sl4, s1, s2, s3, s4, s5, - s6, s7, ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3, - sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33, - satrec.xgh2, satrec.xgh3, satrec.xgh4, satrec.xh2, - satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2, - satrec.xl3, satrec.xl4, nm, z1, z2, z3, z11, - z12, z13, z21, z22, z23, z31, z32, z33, - satrec.zmol, satrec.zmos - ); - dpper - ( - satrec.e3, satrec.ee2, satrec.peo, satrec.pgho, - satrec.pho, satrec.pinco, satrec.plo, satrec.se2, - satrec.se3, satrec.sgh2, satrec.sgh3, satrec.sgh4, - satrec.sh2, satrec.sh3, satrec.si2, satrec.si3, - satrec.sl2, satrec.sl3, satrec.sl4, satrec.t, - satrec.xgh2,satrec.xgh3,satrec.xgh4, satrec.xh2, - satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2, - satrec.xl3, satrec.xl4, satrec.zmol, satrec.zmos, inclm, satrec.init, - satrec.ecco, satrec.inclo, satrec.nodeo, satrec.argpo, satrec.mo - ); - - argpm = 0.0; - nodem = 0.0; - mm = 0.0; - - dsinit - ( - whichconst, - cosim, emsq, satrec.argpo, s1, s2, s3, s4, s5, sinim, ss1, ss2, ss3, ss4, - ss5, sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33, satrec.t, tc, - satrec.gsto, satrec.mo, satrec.mdot, satrec.no, satrec.nodeo, - satrec.nodedot, xpidot, z1, z3, z11, z13, z21, z23, z31, z33, - satrec.ecco, eccsq, em, argpm, inclm, mm, nm, nodem, - satrec.irez, satrec.atime, - satrec.d2201, satrec.d2211, satrec.d3210, satrec.d3222 , - satrec.d4410, satrec.d4422, satrec.d5220, satrec.d5232, - satrec.d5421, satrec.d5433, satrec.dedt, satrec.didt, - satrec.dmdt, dndt, satrec.dnodt, satrec.domdt , - satrec.del1, satrec.del2, satrec.del3, satrec.xfact, - satrec.xlamo, satrec.xli, satrec.xni - ); - } - - /* ----------- set variables if not deep space ----------- */ - if (satrec.isimp != 1) - { - cc1sq = satrec.cc1 * satrec.cc1; - satrec.d2 = 4.0 * ao * tsi * cc1sq; - temp = satrec.d2 * tsi * satrec.cc1 / 3.0; - satrec.d3 = (17.0 * ao + sfour) * temp; - satrec.d4 = 0.5 * temp * ao * tsi * (221.0 * ao + 31.0 * sfour) * - satrec.cc1; - satrec.t3cof = satrec.d2 + 2.0 * cc1sq; - satrec.t4cof = 0.25 * (3.0 * satrec.d3 + satrec.cc1 * - (12.0 * satrec.d2 + 10.0 * cc1sq)); - satrec.t5cof = 0.2 * (3.0 * satrec.d4 + - 12.0 * satrec.cc1 * satrec.d3 + - 6.0 * satrec.d2 * satrec.d2 + - 15.0 * cc1sq * (2.0 * satrec.d2 + cc1sq)); - } - } // if omeosq = 0 ... - - /* finally propogate to zero epoch to initialise all others. */ - if(satrec.error == 0) - sgp4(whichconst, satrec, 0.0, r, v); - - satrec.init = 'n'; - -//#include "debug6.cpp" - return satrec.error; -} // end sgp4init - -/*----------------------------------------------------------------------------- -* -* procedure sgp4 -* -* this procedure is the sgp4 prediction model from space command. this is an -* updated and combined version of sgp4 and sdp4, which were originally -* published separately in spacetrack report #3. this version follows the -* methodology from the aiaa paper (2006) describing the history and -* development of the code. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* satrec - initialised structure from sgp4init() call. -* tsince - time eince epoch (minutes) -* -* outputs : -* r - position vector km -* v - velocity km/sec -* return code - non-zero on error. -* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er -* 2 - mean motion less than 0.0 -* 3 - pert elements, ecc < 0.0 or ecc > 1.0 -* 4 - semi-latus rectum < 0.0 -* 5 - epoch elements are sub-orbital -* 6 - satellite has decayed -* -* locals : -* am - -* axnl, aynl - -* betal - -* cosim , sinim , cosomm , sinomm , cnod , snod , cos2u , -* sin2u , coseo1 , sineo1 , cosi , sini , cosip , sinip , -* cosisq , cossu , sinsu , cosu , sinu -* delm - -* delomg - -* dndt - -* eccm - -* emsq - -* ecose - -* el2 - -* eo1 - -* eccp - -* esine - -* argpm - -* argpp - -* omgadf - -* pl - -* r - -* rtemsq - -* rdotl - -* rl - -* rvdot - -* rvdotl - -* su - -* t2 , t3 , t4 , tc -* tem5, temp , temp1 , temp2 , tempa , tempe , templ -* u , ux , uy , uz , vx , vy , vz -* inclm - inclination -* mm - mean anomaly -* nm - mean motion -* nodem - right asc of ascending node -* xinc - -* xincp - -* xl - -* xlm - -* mp - -* xmdf - -* xmx - -* xmy - -* nodedf - -* xnode - -* nodep - -* np - -* -* coupling : -* getgravconst- -* dpper -* dpspace -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -int sgp4 - ( - gravconsttype whichconst, elsetrec& satrec, double tsince, - double r[3], double v[3] - ) -{ - double am , axnl , aynl , betal , cosim , cnod , - cos2u, coseo1, cosi , cosip , cosisq, cossu , cosu, - delm , delomg, em , emsq , ecose , el2 , eo1 , - ep , esine , argpm, argpp , argpdf, pl, mrt = 0.0, - mvt , rdotl , rl , rvdot , rvdotl, sinim , - sin2u, sineo1, sini , sinip , sinsu , sinu , - snod , su , t2 , t3 , t4 , tem5 , temp, - temp1, temp2 , tempa, tempe , templ , u , ux , - uy , uz , vx , vy , vz , inclm , mm , - nm , nodem, xinc , xincp , xl , xlm , mp , - xmdf , xmx , xmy , nodedf, xnode , nodep, tc , dndt, - twopi, x2o3 , j2 , j3 , tumin, j4 , xke , j3oj2, radiusearthkm, - mu, vkmpersec; - int ktr; - - /* ------------------ set mathematical constants --------------- */ - // sgp4fix divisor for divide by zero check on inclination - const double temp4 = 1.0 + cos(pi-1.0e-9); - twopi = 2.0 * pi; - x2o3 = 2.0 / 3.0; - // sgp4fix identify constants and allow alternate values - getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); - vkmpersec = radiusearthkm * xke/60.0; - - /* --------------------- clear sgp4 error flag ----------------- */ - satrec.t = tsince; - satrec.error = 0; - - /* ------- update for secular gravity and atmospheric drag ----- */ - xmdf = satrec.mo + satrec.mdot * satrec.t; - argpdf = satrec.argpo + satrec.argpdot * satrec.t; - nodedf = satrec.nodeo + satrec.nodedot * satrec.t; - argpm = argpdf; - mm = xmdf; - t2 = satrec.t * satrec.t; - nodem = nodedf + satrec.nodecf * t2; - tempa = 1.0 - satrec.cc1 * satrec.t; - tempe = satrec.bstar * satrec.cc4 * satrec.t; - templ = satrec.t2cof * t2; - - if (satrec.isimp != 1) - { - delomg = satrec.omgcof * satrec.t; - delm = satrec.xmcof * - (pow((1.0 + satrec.eta * cos(xmdf)), 3) - - satrec.delmo); - temp = delomg + delm; - mm = xmdf + temp; - argpm = argpdf - temp; - t3 = t2 * satrec.t; - t4 = t3 * satrec.t; - tempa = tempa - satrec.d2 * t2 - satrec.d3 * t3 - - satrec.d4 * t4; - tempe = tempe + satrec.bstar * satrec.cc5 * (sin(mm) - - satrec.sinmao); - templ = templ + satrec.t3cof * t3 + t4 * (satrec.t4cof + - satrec.t * satrec.t5cof); - } - - nm = satrec.no; - em = satrec.ecco; - inclm = satrec.inclo; - if (satrec.method == 'd') - { - tc = satrec.t; - dspace - ( - satrec.irez, - satrec.d2201, satrec.d2211, satrec.d3210, - satrec.d3222, satrec.d4410, satrec.d4422, - satrec.d5220, satrec.d5232, satrec.d5421, - satrec.d5433, satrec.dedt, satrec.del1, - satrec.del2, satrec.del3, satrec.didt, - satrec.dmdt, satrec.dnodt, satrec.domdt, - satrec.argpo, satrec.argpdot, satrec.t, tc, - satrec.gsto, satrec.xfact, satrec.xlamo, - satrec.no, satrec.atime, - em, argpm, inclm, satrec.xli, mm, satrec.xni, - nodem, dndt, nm - ); - } // if method = d - - if (nm <= 0.0) - { -// printf("# error nm %f\n", nm); - satrec.error = 2; - } - am = pow((xke / nm),x2o3) * tempa * tempa; - nm = xke / pow(am, 1.5); - em = em - tempe; - - // fix tolerance for error recognition - if ((em >= 1.0) || (em < -0.001) || (am < 0.95)) - { -// printf("# error em %f\n", em); - satrec.error = 1; - } - if (em < 0.0) - em = 1.0e-6; - mm = mm + satrec.no * templ; - xlm = mm + argpm + nodem; - emsq = em * em; - temp = 1.0 - emsq; - - nodem = fmod(nodem, twopi); - argpm = fmod(argpm, twopi); - xlm = fmod(xlm, twopi); - mm = fmod(xlm - argpm - nodem, twopi); - - /* ----------------- compute extra mean quantities ------------- */ - sinim = sin(inclm); - cosim = cos(inclm); - - /* -------------------- add lunar-solar periodics -------------- */ - ep = em; - xincp = inclm; - argpp = argpm; - nodep = nodem; - mp = mm; - sinip = sinim; - cosip = cosim; - if (satrec.method == 'd') - { - dpper - ( - satrec.e3, satrec.ee2, satrec.peo, - satrec.pgho, satrec.pho, satrec.pinco, - satrec.plo, satrec.se2, satrec.se3, - satrec.sgh2, satrec.sgh3, satrec.sgh4, - satrec.sh2, satrec.sh3, satrec.si2, - satrec.si3, satrec.sl2, satrec.sl3, - satrec.sl4, satrec.t, satrec.xgh2, - satrec.xgh3, satrec.xgh4, satrec.xh2, - satrec.xh3, satrec.xi2, satrec.xi3, - satrec.xl2, satrec.xl3, satrec.xl4, - satrec.zmol, satrec.zmos, satrec.inclo, - 'n', ep, xincp, nodep, argpp, mp - ); - if (xincp < 0.0) - { - xincp = -xincp; - nodep = nodep + pi; - argpp = argpp - pi; - } - if ((ep < 0.0 ) || ( ep > 1.0)) - { - // printf("# error ep %f\n", ep); - satrec.error = 3; - } - } // if method = d - - /* -------------------- long period periodics ------------------ */ - if (satrec.method == 'd') - { - sinip = sin(xincp); - cosip = cos(xincp); - satrec.aycof = -0.5*j3oj2*sinip; - // sgp4fix for divide by zero for xincp = 180 deg - if (fabs(cosip+1.0) > 1.5e-12) - satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / (1.0 + cosip); - else - satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / temp4; - } - axnl = ep * cos(argpp); - temp = 1.0 / (am * (1.0 - ep * ep)); - aynl = ep* sin(argpp) + temp * satrec.aycof; - xl = mp + argpp + nodep + temp * satrec.xlcof * axnl; - - /* --------------------- solve kepler's equation --------------- */ - u = fmod(xl - nodep, twopi); - eo1 = u; - tem5 = 9999.9; - ktr = 1; - // sgp4fix for kepler iteration - // the following iteration needs better limits on corrections - while (( fabs(tem5) >= 1.0e-12) && (ktr <= 10) ) - { - sineo1 = sin(eo1); - coseo1 = cos(eo1); - tem5 = 1.0 - coseo1 * axnl - sineo1 * aynl; - tem5 = (u - aynl * coseo1 + axnl * sineo1 - eo1) / tem5; - if(fabs(tem5) >= 0.95) - tem5 = tem5 > 0.0 ? 0.95 : -0.95; - eo1 = eo1 + tem5; - ktr = ktr + 1; - } - - /* ------------- short period preliminary quantities ----------- */ - ecose = axnl*coseo1 + aynl*sineo1; - esine = axnl*sineo1 - aynl*coseo1; - el2 = axnl*axnl + aynl*aynl; - pl = am*(1.0-el2); - if (pl < 0.0) - { -// printf("# error pl %f\n", pl); - satrec.error = 4; - } - else - { - rl = am * (1.0 - ecose); - rdotl = sqrt(am) * esine/rl; - rvdotl = sqrt(pl) / rl; - betal = sqrt(1.0 - el2); - temp = esine / (1.0 + betal); - sinu = am / rl * (sineo1 - aynl - axnl * temp); - cosu = am / rl * (coseo1 - axnl + aynl * temp); - su = atan2(sinu, cosu); - sin2u = (cosu + cosu) * sinu; - cos2u = 1.0 - 2.0 * sinu * sinu; - temp = 1.0 / pl; - temp1 = 0.5 * j2 * temp; - temp2 = temp1 * temp; - - /* -------------- update for short period periodics ------------ */ - if (satrec.method == 'd') - { - cosisq = cosip * cosip; - satrec.con41 = 3.0*cosisq - 1.0; - satrec.x1mth2 = 1.0 - cosisq; - satrec.x7thm1 = 7.0*cosisq - 1.0; - } - mrt = rl * (1.0 - 1.5 * temp2 * betal * satrec.con41) + - 0.5 * temp1 * satrec.x1mth2 * cos2u; - su = su - 0.25 * temp2 * satrec.x7thm1 * sin2u; - xnode = nodep + 1.5 * temp2 * cosip * sin2u; - xinc = xincp + 1.5 * temp2 * cosip * sinip * cos2u; - mvt = rdotl - nm * temp1 * satrec.x1mth2 * sin2u / xke; - rvdot = rvdotl + nm * temp1 * (satrec.x1mth2 * cos2u + - 1.5 * satrec.con41) / xke; - - /* --------------------- orientation vectors ------------------- */ - sinsu = sin(su); - cossu = cos(su); - snod = sin(xnode); - cnod = cos(xnode); - sini = sin(xinc); - cosi = cos(xinc); - xmx = -snod * cosi; - xmy = cnod * cosi; - ux = xmx * sinsu + cnod * cossu; - uy = xmy * sinsu + snod * cossu; - uz = sini * sinsu; - vx = xmx * cossu - cnod * sinsu; - vy = xmy * cossu - snod * sinsu; - vz = sini * cossu; - - /* --------- position and velocity (in km and km/sec) ---------- */ - r[0] = (mrt * ux)* radiusearthkm; - r[1] = (mrt * uy)* radiusearthkm; - r[2] = (mrt * uz)* radiusearthkm; - v[0] = (mvt * ux + rvdot * vx) * vkmpersec; - v[1] = (mvt * uy + rvdot * vy) * vkmpersec; - v[2] = (mvt * uz + rvdot * vz) * vkmpersec; - } // if pl > 0 - - // sgp4fix for decaying satellites - if (mrt < 1.0) - { -// printf("# decay condition %11.6f \n",mrt); - satrec.error = 6; - } - - -//#include "debug7.cpp" - return satrec.error; -} // end sgp4 - - -/* ----------------------------------------------------------------------------- -* -* function gstime -* -* this function finds the greenwich sidereal time. -* -* author : david vallado 719-573-2600 1 mar 2001 -* -* inputs description range / units -* jdut1 - julian date in ut1 days from 4713 bc -* -* outputs : -* gstime - greenwich sidereal time 0 to 2pi rad -* -* locals : -* temp - temporary variable for doubles rad -* tut1 - julian centuries from the -* jan 1, 2000 12 h epoch (ut1) -* -* coupling : -* none -* -* references : -* vallado 2004, 191, eq 3-45 -* --------------------------------------------------------------------------- */ - -double gstime - ( - double jdut1 - ) - { - const double twopi = 2.0 * pi; - const double deg2rad = pi / 180.0; - double temp, tut1; - - tut1 = (jdut1 - 2451545.0) / 36525.0; - temp = -6.2e-6* tut1 * tut1 * tut1 + 0.093104 * tut1 * tut1 + - (876600.0*3600 + 8640184.812866) * tut1 + 67310.54841; // sec - temp = fmod(temp * deg2rad / 240.0, twopi); //360/86400 = 1/240, to deg, to rad - - // ------------------------ check quadrants --------------------- - if (temp < 0.0) - temp += twopi; - - return temp; - } // end gstime - -/* ----------------------------------------------------------------------------- -* -* function getgravconst -* -* this function gets constants for the propagator. note that mu is identified to -* facilitiate comparisons with newer models. the common useage is wgs72. -* -* author : david vallado 719-573-2600 21 jul 2006 -* -* inputs : -* whichconst - which set of constants to use wgs72old, wgs72, wgs84 -* -* outputs : -* tumin - minutes in one time unit -* mu - earth gravitational parameter -* radiusearthkm - radius of the earth in km -* xke - reciprocal of tumin -* j2, j3, j4 - un-normalized zonal harmonic values -* j3oj2 - j3 divided by j2 -* -* locals : -* -* coupling : -* none -* -* references : -* norad spacetrack report #3 -* vallado, crawford, hujsak, kelso 2006 - --------------------------------------------------------------------------- */ - -void getgravconst - ( - gravconsttype whichconst, - double& tumin, - double& mu, - double& radiusearthkm, - double& xke, - double& j2, - double& j3, - double& j4, - double& j3oj2 - ) - { - - switch (whichconst) - { - // -- wgs-72 low precision str#3 constants -- - case wgs72old: - mu = 398600.79964; // in km3 / s2 - radiusearthkm = 6378.135; // km - xke = 0.0743669161; - tumin = 1.0 / xke; - j2 = 0.001082616; - j3 = -0.00000253881; - j4 = -0.00000165597; - j3oj2 = j3 / j2; - break; - // ------------ wgs-72 constants ------------ - case wgs72: - mu = 398600.8; // in km3 / s2 - radiusearthkm = 6378.135; // km - xke = 60.0 / sqrt(radiusearthkm*radiusearthkm*radiusearthkm/mu); - tumin = 1.0 / xke; - j2 = 0.001082616; - j3 = -0.00000253881; - j4 = -0.00000165597; - j3oj2 = j3 / j2; - break; - case wgs84: - // ------------ wgs-84 constants ------------ - mu = 398600.5; // in km3 / s2 - radiusearthkm = 6378.137; // km - xke = 60.0 / sqrt(radiusearthkm*radiusearthkm*radiusearthkm/mu); - tumin = 1.0 / xke; - j2 = 0.00108262998905; - j3 = -0.00000253215306; - j4 = -0.00000161098761; - j3oj2 = j3 / j2; - break; - default: - fprintf(stderr,"unknown gravity option (%d)\n",whichconst); - break; - } - - } // end getgravconst - - - - - +/* ---------------------------------------------------------------- +* +* sgp4unit.cpp +* +* this file contains the sgp4 procedures for analytical propagation +* of a satellite. the code was originally released in the 1980 and 1986 +* spacetrack papers. a detailed discussion of the theory and history +* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, +* and kelso. +* +* companion code for +* fundamentals of astrodynamics and applications +* 2007 +* by david vallado +* +* (w) 719-573-2600, email dvallado@agi.com +* +* current : +* 16 nov 07 david vallado +* misc fixes for better compliance +* changes : +* 20 apr 07 david vallado +* misc fixes for constants +* 11 aug 06 david vallado +* chg lyddane choice back to strn3, constants, misc doc +* 15 dec 05 david vallado +* misc fixes +* 26 jul 05 david vallado +* fixes for paper +* note that each fix is preceded by a +* comment with "sgp4fix" and an explanation of +* what was changed +* 10 aug 04 david vallado +* 2nd printing baseline working +* 14 may 01 david vallado +* 2nd edition baseline +* 80 norad +* original baseline +* ---------------------------------------------------------------- */ + +#include "sgp4unit.h" + +const char help = 'n'; +FILE *dbgfile; + +#define pi 3.14159265358979323846 + + +/* ----------- local functions - only ever used internally by sgp4 ---------- */ +static void dpper + ( + double e3, double ee2, double peo, double pgho, double pho, + double pinco, double plo, double se2, double se3, double sgh2, + double sgh3, double sgh4, double sh2, double sh3, double si2, + double si3, double sl2, double sl3, double sl4, double t, + double xgh2, double xgh3, double xgh4, double xh2, double xh3, + double xi2, double xi3, double xl2, double xl3, double xl4, + double zmol, double zmos, double inclo, + char init, + double& ep, double& inclp, double& nodep, double& argpp, double& mp + ); + +static void dscom + ( + double epoch, double ep, double argpp, double tc, double inclp, + double nodep, double np, + double& snodm, double& cnodm, double& sinim, double& cosim, double& sinomm, + double& cosomm,double& day, double& e3, double& ee2, double& em, + double& emsq, double& gam, double& peo, double& pgho, double& pho, + double& pinco, double& plo, double& rtemsq, double& se2, double& se3, + double& sgh2, double& sgh3, double& sgh4, double& sh2, double& sh3, + double& si2, double& si3, double& sl2, double& sl3, double& sl4, + double& s1, double& s2, double& s3, double& s4, double& s5, + double& s6, double& s7, double& ss1, double& ss2, double& ss3, + double& ss4, double& ss5, double& ss6, double& ss7, double& sz1, + double& sz2, double& sz3, double& sz11, double& sz12, double& sz13, + double& sz21, double& sz22, double& sz23, double& sz31, double& sz32, + double& sz33, double& xgh2, double& xgh3, double& xgh4, double& xh2, + double& xh3, double& xi2, double& xi3, double& xl2, double& xl3, + double& xl4, double& nm, double& z1, double& z2, double& z3, + double& z11, double& z12, double& z13, double& z21, double& z22, + double& z23, double& z31, double& z32, double& z33, double& zmol, + double& zmos + ); + +static void dsinit + ( + gravconsttype whichconst, + double cosim, double emsq, double argpo, double s1, double s2, + double s3, double s4, double s5, double sinim, double ss1, + double ss2, double ss3, double ss4, double ss5, double sz1, + double sz3, double sz11, double sz13, double sz21, double sz23, + double sz31, double sz33, double t, double tc, double gsto, + double mo, double mdot, double no, double nodeo, double nodedot, + double xpidot, double z1, double z3, double z11, double z13, + double z21, double z23, double z31, double z33, double ecco, + double eccsq, double& em, double& argpm, double& inclm, double& mm, + double& nm, double& nodem, + int& irez, + double& atime, double& d2201, double& d2211, double& d3210, double& d3222, + double& d4410, double& d4422, double& d5220, double& d5232, double& d5421, + double& d5433, double& dedt, double& didt, double& dmdt, double& dndt, + double& dnodt, double& domdt, double& del1, double& del2, double& del3, + double& xfact, double& xlamo, double& xli, double& xni + ); + +static void dspace + ( + int irez, + double d2201, double d2211, double d3210, double d3222, double d4410, + double d4422, double d5220, double d5232, double d5421, double d5433, + double dedt, double del1, double del2, double del3, double didt, + double dmdt, double dnodt, double domdt, double argpo, double argpdot, + double t, double tc, double gsto, double xfact, double xlamo, + double no, + double& atime, double& em, double& argpm, double& inclm, double& xli, + double& mm, double& xni, double& nodem, double& dndt, double& nm + ); + +static void initl + ( + int satn, gravconsttype whichconst, + double ecco, double epoch, double inclo, double& no, + char& method, + double& ainv, double& ao, double& con41, double& con42, double& cosio, + double& cosio2,double& eccsq, double& omeosq, double& posq, + double& rp, double& rteosq,double& sinio , double& gsto + ); + +/* ----------------------------------------------------------------------------- +* +* procedure dpper +* +* this procedure provides deep space long period periodic contributions +* to the mean elements. by design, these periodics are zero at epoch. +* this used to be dscom which included initialization, but it's really a +* recurring function. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* e3 - +* ee2 - +* peo - +* pgho - +* pho - +* pinco - +* plo - +* se2 , se3 , sgh2, sgh3, sgh4, sh2, sh3, si2, si3, sl2, sl3, sl4 - +* t - +* xh2, xh3, xi2, xi3, xl2, xl3, xl4 - +* zmol - +* zmos - +* ep - eccentricity 0.0 - 1.0 +* inclo - inclination - needed for lyddane modification +* nodep - right ascension of ascending node +* argpp - argument of perigee +* mp - mean anomaly +* +* outputs : +* ep - eccentricity 0.0 - 1.0 +* inclp - inclination +* nodep - right ascension of ascending node +* argpp - argument of perigee +* mp - mean anomaly +* +* locals : +* alfdp - +* betdp - +* cosip , sinip , cosop , sinop , +* dalf - +* dbet - +* dls - +* f2, f3 - +* pe - +* pgh - +* ph - +* pinc - +* pl - +* sel , ses , sghl , sghs , shl , shs , sil , sinzf , sis , +* sll , sls +* xls - +* xnoh - +* zf - +* zm - +* +* coupling : +* none. +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dpper + ( + double e3, double ee2, double peo, double pgho, double pho, + double pinco, double plo, double se2, double se3, double sgh2, + double sgh3, double sgh4, double sh2, double sh3, double si2, + double si3, double sl2, double sl3, double sl4, double t, + double xgh2, double xgh3, double xgh4, double xh2, double xh3, + double xi2, double xi3, double xl2, double xl3, double xl4, + double zmol, double zmos, double inclo, + char init, + double& ep, double& inclp, double& nodep, double& argpp, double& mp + ) +{ + /* --------------------- local variables ------------------------ */ + const double twopi = 2.0 * pi; + double alfdp, betdp, cosip, cosop, dalf, dbet, dls, + f2, f3, pe, pgh, ph, pinc, pl , + sel, ses, sghl, sghs, shll, shs, sil, + sinip, sinop, sinzf, sis, sll, sls, xls, + xnoh, zf, zm, zel, zes, znl, zns; + + /* ---------------------- constants ----------------------------- */ + zns = 1.19459e-5; + zes = 0.01675; + znl = 1.5835218e-4; + zel = 0.05490; + + /* --------------- calculate time varying periodics ----------- */ + zm = zmos + zns * t; + // be sure that the initial call has time set to zero + if (init == 'y') + zm = zmos; + zf = zm + 2.0 * zes * sin(zm); + sinzf = sin(zf); + f2 = 0.5 * sinzf * sinzf - 0.25; + f3 = -0.5 * sinzf * cos(zf); + ses = se2* f2 + se3 * f3; + sis = si2 * f2 + si3 * f3; + sls = sl2 * f2 + sl3 * f3 + sl4 * sinzf; + sghs = sgh2 * f2 + sgh3 * f3 + sgh4 * sinzf; + shs = sh2 * f2 + sh3 * f3; + zm = zmol + znl * t; + if (init == 'y') + zm = zmol; + zf = zm + 2.0 * zel * sin(zm); + sinzf = sin(zf); + f2 = 0.5 * sinzf * sinzf - 0.25; + f3 = -0.5 * sinzf * cos(zf); + sel = ee2 * f2 + e3 * f3; + sil = xi2 * f2 + xi3 * f3; + sll = xl2 * f2 + xl3 * f3 + xl4 * sinzf; + sghl = xgh2 * f2 + xgh3 * f3 + xgh4 * sinzf; + shll = xh2 * f2 + xh3 * f3; + pe = ses + sel; + pinc = sis + sil; + pl = sls + sll; + pgh = sghs + sghl; + ph = shs + shll; + + if (init == 'n') + { + pe = pe - peo; + pinc = pinc - pinco; + pl = pl - plo; + pgh = pgh - pgho; + ph = ph - pho; + inclp = inclp + pinc; + ep = ep + pe; + sinip = sin(inclp); + cosip = cos(inclp); + + /* ----------------- apply periodics directly ------------ */ + // sgp4fix for lyddane choice + // strn3 used original inclination - this is technically feasible + // gsfc used perturbed inclination - also technically feasible + // probably best to readjust the 0.2 limit value and limit discontinuity + // 0.2 rad = 11.45916 deg + // use next line for original strn3 approach and original inclination + // if (inclo >= 0.2) + // use next line for gsfc version and perturbed inclination + if (inclp >= 0.2) + { + ph = ph / sinip; + pgh = pgh - cosip * ph; + argpp = argpp + pgh; + nodep = nodep + ph; + mp = mp + pl; + } + else + { + /* ---- apply periodics with lyddane modification ---- */ + sinop = sin(nodep); + cosop = cos(nodep); + alfdp = sinip * sinop; + betdp = sinip * cosop; + dalf = ph * cosop + pinc * cosip * sinop; + dbet = -ph * sinop + pinc * cosip * cosop; + alfdp = alfdp + dalf; + betdp = betdp + dbet; + nodep = fmod(nodep, twopi); + // sgp4fix for afspc written intrinsic functions + // nodep used without a trigonometric function ahead + if (nodep < 0.0) + nodep = nodep + twopi; + xls = mp + argpp + cosip * nodep; + dls = pl + pgh - pinc * nodep * sinip; + xls = xls + dls; + xnoh = nodep; + nodep = atan2(alfdp, betdp); + // sgp4fix for afspc written intrinsic functions + // nodep used without a trigonometric function ahead + if (nodep < 0.0) + nodep = nodep + twopi; + if (fabs(xnoh - nodep) > pi){ + if (nodep < xnoh) + nodep = nodep + twopi; + else + nodep = nodep - twopi; + } + mp = mp + pl; + argpp = xls - mp - cosip * nodep; + } + } // if init == 'n' + +//#include "debug1.cpp" +} // end dpper + +/*----------------------------------------------------------------------------- +* +* procedure dscom +* +* this procedure provides deep space common items used by both the secular +* and periodics subroutines. input is provided as shown. this routine +* used to be called dpper, but the functions inside weren't well organized. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* epoch - +* ep - eccentricity +* argpp - argument of perigee +* tc - +* inclp - inclination +* nodep - right ascension of ascending node +* np - mean motion +* +* outputs : +* sinim , cosim , sinomm , cosomm , snodm , cnodm +* day - +* e3 - +* ee2 - +* em - eccentricity +* emsq - eccentricity squared +* gam - +* peo - +* pgho - +* pho - +* pinco - +* plo - +* rtemsq - +* se2, se3 - +* sgh2, sgh3, sgh4 - +* sh2, sh3, si2, si3, sl2, sl3, sl4 - +* s1, s2, s3, s4, s5, s6, s7 - +* ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3 - +* sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33 - +* xgh2, xgh3, xgh4, xh2, xh3, xi2, xi3, xl2, xl3, xl4 - +* nm - mean motion +* z1, z2, z3, z11, z12, z13, z21, z22, z23, z31, z32, z33 - +* zmol - +* zmos - +* +* locals : +* a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 - +* betasq - +* cc - +* ctem, stem - +* x1, x2, x3, x4, x5, x6, x7, x8 - +* xnodce - +* xnoi - +* zcosg , zsing , zcosgl , zsingl , zcosh , zsinh , zcoshl , zsinhl , +* zcosi , zsini , zcosil , zsinil , +* zx - +* zy - +* +* coupling : +* none. +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dscom + ( + double epoch, double ep, double argpp, double tc, double inclp, + double nodep, double np, + double& snodm, double& cnodm, double& sinim, double& cosim, double& sinomm, + double& cosomm,double& day, double& e3, double& ee2, double& em, + double& emsq, double& gam, double& peo, double& pgho, double& pho, + double& pinco, double& plo, double& rtemsq, double& se2, double& se3, + double& sgh2, double& sgh3, double& sgh4, double& sh2, double& sh3, + double& si2, double& si3, double& sl2, double& sl3, double& sl4, + double& s1, double& s2, double& s3, double& s4, double& s5, + double& s6, double& s7, double& ss1, double& ss2, double& ss3, + double& ss4, double& ss5, double& ss6, double& ss7, double& sz1, + double& sz2, double& sz3, double& sz11, double& sz12, double& sz13, + double& sz21, double& sz22, double& sz23, double& sz31, double& sz32, + double& sz33, double& xgh2, double& xgh3, double& xgh4, double& xh2, + double& xh3, double& xi2, double& xi3, double& xl2, double& xl3, + double& xl4, double& nm, double& z1, double& z2, double& z3, + double& z11, double& z12, double& z13, double& z21, double& z22, + double& z23, double& z31, double& z32, double& z33, double& zmol, + double& zmos + ) +{ + /* -------------------------- constants ------------------------- */ + const double zes = 0.01675; + const double zel = 0.05490; + const double c1ss = 2.9864797e-6; + const double c1l = 4.7968065e-7; + const double zsinis = 0.39785416; + const double zcosis = 0.91744867; + const double zcosgs = 0.1945905; + const double zsings = -0.98088458; + const double twopi = 2.0 * pi; + + /* --------------------- local variables ------------------------ */ + int lsflg; + double a1 , a2 , a3 , a4 , a5 , a6 , a7 , + a8 , a9 , a10 , betasq, cc , ctem , stem , + x1 , x2 , x3 , x4 , x5 , x6 , x7 , + x8 , xnodce, xnoi , zcosg , zcosgl, zcosh , zcoshl, + zcosi , zcosil, zsing , zsingl, zsinh , zsinhl, zsini , + zsinil, zx , zy; + + nm = np; + em = ep; + snodm = sin(nodep); + cnodm = cos(nodep); + sinomm = sin(argpp); + cosomm = cos(argpp); + sinim = sin(inclp); + cosim = cos(inclp); + emsq = em * em; + betasq = 1.0 - emsq; + rtemsq = sqrt(betasq); + + /* ----------------- initialize lunar solar terms --------------- */ + peo = 0.0; + pinco = 0.0; + plo = 0.0; + pgho = 0.0; + pho = 0.0; + day = epoch + 18261.5 + tc / 1440.0; + xnodce = fmod(4.5236020 - 9.2422029e-4 * day, twopi); + stem = sin(xnodce); + ctem = cos(xnodce); + zcosil = 0.91375164 - 0.03568096 * ctem; + zsinil = sqrt(1.0 - zcosil * zcosil); + zsinhl = 0.089683511 * stem / zsinil; + zcoshl = sqrt(1.0 - zsinhl * zsinhl); + gam = 5.8351514 + 0.0019443680 * day; + zx = 0.39785416 * stem / zsinil; + zy = zcoshl * ctem + 0.91744867 * zsinhl * stem; + zx = atan2(zx, zy); + zx = gam + zx - xnodce; + zcosgl = cos(zx); + zsingl = sin(zx); + + /* ------------------------- do solar terms --------------------- */ + zcosg = zcosgs; + zsing = zsings; + zcosi = zcosis; + zsini = zsinis; + zcosh = cnodm; + zsinh = snodm; + cc = c1ss; + xnoi = 1.0 / nm; + + for (lsflg = 1; lsflg <= 2; lsflg++) + { + a1 = zcosg * zcosh + zsing * zcosi * zsinh; + a3 = -zsing * zcosh + zcosg * zcosi * zsinh; + a7 = -zcosg * zsinh + zsing * zcosi * zcosh; + a8 = zsing * zsini; + a9 = zsing * zsinh + zcosg * zcosi * zcosh; + a10 = zcosg * zsini; + a2 = cosim * a7 + sinim * a8; + a4 = cosim * a9 + sinim * a10; + a5 = -sinim * a7 + cosim * a8; + a6 = -sinim * a9 + cosim * a10; + + x1 = a1 * cosomm + a2 * sinomm; + x2 = a3 * cosomm + a4 * sinomm; + x3 = -a1 * sinomm + a2 * cosomm; + x4 = -a3 * sinomm + a4 * cosomm; + x5 = a5 * sinomm; + x6 = a6 * sinomm; + x7 = a5 * cosomm; + x8 = a6 * cosomm; + + z31 = 12.0 * x1 * x1 - 3.0 * x3 * x3; + z32 = 24.0 * x1 * x2 - 6.0 * x3 * x4; + z33 = 12.0 * x2 * x2 - 3.0 * x4 * x4; + z1 = 3.0 * (a1 * a1 + a2 * a2) + z31 * emsq; + z2 = 6.0 * (a1 * a3 + a2 * a4) + z32 * emsq; + z3 = 3.0 * (a3 * a3 + a4 * a4) + z33 * emsq; + z11 = -6.0 * a1 * a5 + emsq * (-24.0 * x1 * x7-6.0 * x3 * x5); + z12 = -6.0 * (a1 * a6 + a3 * a5) + emsq * + (-24.0 * (x2 * x7 + x1 * x8) - 6.0 * (x3 * x6 + x4 * x5)); + z13 = -6.0 * a3 * a6 + emsq * (-24.0 * x2 * x8 - 6.0 * x4 * x6); + z21 = 6.0 * a2 * a5 + emsq * (24.0 * x1 * x5 - 6.0 * x3 * x7); + z22 = 6.0 * (a4 * a5 + a2 * a6) + emsq * + (24.0 * (x2 * x5 + x1 * x6) - 6.0 * (x4 * x7 + x3 * x8)); + z23 = 6.0 * a4 * a6 + emsq * (24.0 * x2 * x6 - 6.0 * x4 * x8); + z1 = z1 + z1 + betasq * z31; + z2 = z2 + z2 + betasq * z32; + z3 = z3 + z3 + betasq * z33; + s3 = cc * xnoi; + s2 = -0.5 * s3 / rtemsq; + s4 = s3 * rtemsq; + s1 = -15.0 * em * s4; + s5 = x1 * x3 + x2 * x4; + s6 = x2 * x3 + x1 * x4; + s7 = x2 * x4 - x1 * x3; + + /* ----------------------- do lunar terms ------------------- */ + if (lsflg == 1) + { + ss1 = s1; + ss2 = s2; + ss3 = s3; + ss4 = s4; + ss5 = s5; + ss6 = s6; + ss7 = s7; + sz1 = z1; + sz2 = z2; + sz3 = z3; + sz11 = z11; + sz12 = z12; + sz13 = z13; + sz21 = z21; + sz22 = z22; + sz23 = z23; + sz31 = z31; + sz32 = z32; + sz33 = z33; + zcosg = zcosgl; + zsing = zsingl; + zcosi = zcosil; + zsini = zsinil; + zcosh = zcoshl * cnodm + zsinhl * snodm; + zsinh = snodm * zcoshl - cnodm * zsinhl; + cc = c1l; + } + } + + zmol = fmod(4.7199672 + 0.22997150 * day - gam, twopi); + zmos = fmod(6.2565837 + 0.017201977 * day, twopi); + + /* ------------------------ do solar terms ---------------------- */ + se2 = 2.0 * ss1 * ss6; + se3 = 2.0 * ss1 * ss7; + si2 = 2.0 * ss2 * sz12; + si3 = 2.0 * ss2 * (sz13 - sz11); + sl2 = -2.0 * ss3 * sz2; + sl3 = -2.0 * ss3 * (sz3 - sz1); + sl4 = -2.0 * ss3 * (-21.0 - 9.0 * emsq) * zes; + sgh2 = 2.0 * ss4 * sz32; + sgh3 = 2.0 * ss4 * (sz33 - sz31); + sgh4 = -18.0 * ss4 * zes; + sh2 = -2.0 * ss2 * sz22; + sh3 = -2.0 * ss2 * (sz23 - sz21); + + /* ------------------------ do lunar terms ---------------------- */ + ee2 = 2.0 * s1 * s6; + e3 = 2.0 * s1 * s7; + xi2 = 2.0 * s2 * z12; + xi3 = 2.0 * s2 * (z13 - z11); + xl2 = -2.0 * s3 * z2; + xl3 = -2.0 * s3 * (z3 - z1); + xl4 = -2.0 * s3 * (-21.0 - 9.0 * emsq) * zel; + xgh2 = 2.0 * s4 * z32; + xgh3 = 2.0 * s4 * (z33 - z31); + xgh4 = -18.0 * s4 * zel; + xh2 = -2.0 * s2 * z22; + xh3 = -2.0 * s2 * (z23 - z21); + +//#include "debug2.cpp" +} // end dscom + +/*----------------------------------------------------------------------------- +* +* procedure dsinit +* +* this procedure provides deep space contributions to mean motion dot due +* to geopotential resonance with half day and one day orbits. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* cosim, sinim- +* emsq - eccentricity squared +* argpo - argument of perigee +* s1, s2, s3, s4, s5 - +* ss1, ss2, ss3, ss4, ss5 - +* sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33 - +* t - time +* tc - +* gsto - greenwich sidereal time rad +* mo - mean anomaly +* mdot - mean anomaly dot (rate) +* no - mean motion +* nodeo - right ascension of ascending node +* nodedot - right ascension of ascending node dot (rate) +* xpidot - +* z1, z3, z11, z13, z21, z23, z31, z33 - +* eccm - eccentricity +* argpm - argument of perigee +* inclm - inclination +* mm - mean anomaly +* xn - mean motion +* nodem - right ascension of ascending node +* +* outputs : +* em - eccentricity +* argpm - argument of perigee +* inclm - inclination +* mm - mean anomaly +* nm - mean motion +* nodem - right ascension of ascending node +* irez - flag for resonance 0-none, 1-one day, 2-half day +* atime - +* d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 - +* dedt - +* didt - +* dmdt - +* dndt - +* dnodt - +* domdt - +* del1, del2, del3 - +* ses , sghl , sghs , sgs , shl , shs , sis , sls +* theta - +* xfact - +* xlamo - +* xli - +* xni +* +* locals : +* ainv2 - +* aonv - +* cosisq - +* eoc - +* f220, f221, f311, f321, f322, f330, f441, f442, f522, f523, f542, f543 - +* g200, g201, g211, g300, g310, g322, g410, g422, g520, g521, g532, g533 - +* sini2 - +* temp - +* temp1 - +* theta - +* xno2 - +* +* coupling : +* getgravconst +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dsinit + ( + gravconsttype whichconst, + double cosim, double emsq, double argpo, double s1, double s2, + double s3, double s4, double s5, double sinim, double ss1, + double ss2, double ss3, double ss4, double ss5, double sz1, + double sz3, double sz11, double sz13, double sz21, double sz23, + double sz31, double sz33, double t, double tc, double gsto, + double mo, double mdot, double no, double nodeo, double nodedot, + double xpidot, double z1, double z3, double z11, double z13, + double z21, double z23, double z31, double z33, double ecco, + double eccsq, double& em, double& argpm, double& inclm, double& mm, + double& nm, double& nodem, + int& irez, + double& atime, double& d2201, double& d2211, double& d3210, double& d3222, + double& d4410, double& d4422, double& d5220, double& d5232, double& d5421, + double& d5433, double& dedt, double& didt, double& dmdt, double& dndt, + double& dnodt, double& domdt, double& del1, double& del2, double& del3, + double& xfact, double& xlamo, double& xli, double& xni + ) +{ + /* --------------------- local variables ------------------------ */ + const double twopi = 2.0 * pi; + + double ainv2 , aonv=0.0, cosisq, eoc, f220 , f221 , f311 , + f321 , f322 , f330 , f441 , f442 , f522 , f523 , + f542 , f543 , g200 , g201 , g211 , g300 , g310 , + g322 , g410 , g422 , g520 , g521 , g532 , g533 , + ses , sgs , sghl , sghs , shs , shll , sis , + sini2 , sls , temp , temp1 , theta , xno2 , q22 , + q31 , q33 , root22, root44, root54, rptim , root32, + root52, x2o3 , xke , znl , emo , zns , emsqo, + tumin, mu, radiusearthkm, j2, j3, j4, j3oj2; + + q22 = 1.7891679e-6; + q31 = 2.1460748e-6; + q33 = 2.2123015e-7; + root22 = 1.7891679e-6; + root44 = 7.3636953e-9; + root54 = 2.1765803e-9; + rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec + root32 = 3.7393792e-7; + root52 = 1.1428639e-7; + x2o3 = 2.0 / 3.0; + znl = 1.5835218e-4; + zns = 1.19459e-5; + + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + + /* -------------------- deep space initialization ------------ */ + irez = 0; + if ((nm < 0.0052359877) && (nm > 0.0034906585)) + irez = 1; + if ((nm >= 8.26e-3) && (nm <= 9.24e-3) && (em >= 0.5)) + irez = 2; + + /* ------------------------ do solar terms ------------------- */ + ses = ss1 * zns * ss5; + sis = ss2 * zns * (sz11 + sz13); + sls = -zns * ss3 * (sz1 + sz3 - 14.0 - 6.0 * emsq); + sghs = ss4 * zns * (sz31 + sz33 - 6.0); + shs = -zns * ss2 * (sz21 + sz23); + // sgp4fix for 180 deg incl + if ((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2)) + shs = 0.0; + if (sinim != 0.0) + shs = shs / sinim; + sgs = sghs - cosim * shs; + + /* ------------------------- do lunar terms ------------------ */ + dedt = ses + s1 * znl * s5; + didt = sis + s2 * znl * (z11 + z13); + dmdt = sls - znl * s3 * (z1 + z3 - 14.0 - 6.0 * emsq); + sghl = s4 * znl * (z31 + z33 - 6.0); + shll = -znl * s2 * (z21 + z23); + // sgp4fix for 180 deg incl + if ((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2)) + shll = 0.0; + domdt = sgs + sghl; + dnodt = shs; + if (sinim != 0.0) + { + domdt = domdt - cosim / sinim * shll; + dnodt = dnodt + shll / sinim; + } + + /* ----------- calculate deep space resonance effects -------- */ + dndt = 0.0; + theta = fmod(gsto + tc * rptim, twopi); + em = em + dedt * t; + inclm = inclm + didt * t; + argpm = argpm + domdt * t; + nodem = nodem + dnodt * t; + mm = mm + dmdt * t; + // sgp4fix for negative inclinations + // the following if statement should be commented out + //if (inclm < 0.0) + // { + // inclm = -inclm; + // argpm = argpm - pi; + // nodem = nodem + pi; + // } + + /* -------------- initialize the resonance terms ------------- */ + if (irez != 0) + { + aonv = pow(nm / xke, x2o3); + + /* ---------- geopotential resonance for 12 hour orbits ------ */ + if (irez == 2) + { + cosisq = cosim * cosim; + emo = em; + em = ecco; + emsqo = emsq; + emsq = eccsq; + eoc = em * emsq; + g201 = -0.306 - (em - 0.64) * 0.440; + + if (em <= 0.65) + { + g211 = 3.616 - 13.2470 * em + 16.2900 * emsq; + g310 = -19.302 + 117.3900 * em - 228.4190 * emsq + 156.5910 * eoc; + g322 = -18.9068 + 109.7927 * em - 214.6334 * emsq + 146.5816 * eoc; + g410 = -41.122 + 242.6940 * em - 471.0940 * emsq + 313.9530 * eoc; + g422 = -146.407 + 841.8800 * em - 1629.014 * emsq + 1083.4350 * eoc; + g520 = -532.114 + 3017.977 * em - 5740.032 * emsq + 3708.2760 * eoc; + } + else + { + g211 = -72.099 + 331.819 * em - 508.738 * emsq + 266.724 * eoc; + g310 = -346.844 + 1582.851 * em - 2415.925 * emsq + 1246.113 * eoc; + g322 = -342.585 + 1554.908 * em - 2366.899 * emsq + 1215.972 * eoc; + g410 = -1052.797 + 4758.686 * em - 7193.992 * emsq + 3651.957 * eoc; + g422 = -3581.690 + 16178.110 * em - 24462.770 * emsq + 12422.520 * eoc; + if (em > 0.715) + g520 =-5149.66 + 29936.92 * em - 54087.36 * emsq + 31324.56 * eoc; + else + g520 = 1464.74 - 4664.75 * em + 3763.64 * emsq; + } + if (em < 0.7) + { + g533 = -919.22770 + 4988.6100 * em - 9064.7700 * emsq + 5542.21 * eoc; + g521 = -822.71072 + 4568.6173 * em - 8491.4146 * emsq + 5337.524 * eoc; + g532 = -853.66600 + 4690.2500 * em - 8624.7700 * emsq + 5341.4 * eoc; + } + else + { + g533 =-37995.780 + 161616.52 * em - 229838.20 * emsq + 109377.94 * eoc; + g521 =-51752.104 + 218913.95 * em - 309468.16 * emsq + 146349.42 * eoc; + g532 =-40023.880 + 170470.89 * em - 242699.48 * emsq + 115605.82 * eoc; + } + + sini2= sinim * sinim; + f220 = 0.75 * (1.0 + 2.0 * cosim+cosisq); + f221 = 1.5 * sini2; + f321 = 1.875 * sinim * (1.0 - 2.0 * cosim - 3.0 * cosisq); + f322 = -1.875 * sinim * (1.0 + 2.0 * cosim - 3.0 * cosisq); + f441 = 35.0 * sini2 * f220; + f442 = 39.3750 * sini2 * sini2; + f522 = 9.84375 * sinim * (sini2 * (1.0 - 2.0 * cosim- 5.0 * cosisq) + + 0.33333333 * (-2.0 + 4.0 * cosim + 6.0 * cosisq) ); + f523 = sinim * (4.92187512 * sini2 * (-2.0 - 4.0 * cosim + + 10.0 * cosisq) + 6.56250012 * (1.0+2.0 * cosim - 3.0 * cosisq)); + f542 = 29.53125 * sinim * (2.0 - 8.0 * cosim+cosisq * + (-12.0 + 8.0 * cosim + 10.0 * cosisq)); + f543 = 29.53125 * sinim * (-2.0 - 8.0 * cosim+cosisq * + (12.0 + 8.0 * cosim - 10.0 * cosisq)); + xno2 = nm * nm; + ainv2 = aonv * aonv; + temp1 = 3.0 * xno2 * ainv2; + temp = temp1 * root22; + d2201 = temp * f220 * g201; + d2211 = temp * f221 * g211; + temp1 = temp1 * aonv; + temp = temp1 * root32; + d3210 = temp * f321 * g310; + d3222 = temp * f322 * g322; + temp1 = temp1 * aonv; + temp = 2.0 * temp1 * root44; + d4410 = temp * f441 * g410; + d4422 = temp * f442 * g422; + temp1 = temp1 * aonv; + temp = temp1 * root52; + d5220 = temp * f522 * g520; + d5232 = temp * f523 * g532; + temp = 2.0 * temp1 * root54; + d5421 = temp * f542 * g521; + d5433 = temp * f543 * g533; + xlamo = fmod(mo + nodeo + nodeo-theta - theta, twopi); + xfact = mdot + dmdt + 2.0 * (nodedot + dnodt - rptim) - no; + em = emo; + emsq = emsqo; + } + + /* ---------------- synchronous resonance terms -------------- */ + if (irez == 1) + { + g200 = 1.0 + emsq * (-2.5 + 0.8125 * emsq); + g310 = 1.0 + 2.0 * emsq; + g300 = 1.0 + emsq * (-6.0 + 6.60937 * emsq); + f220 = 0.75 * (1.0 + cosim) * (1.0 + cosim); + f311 = 0.9375 * sinim * sinim * (1.0 + 3.0 * cosim) - 0.75 * (1.0 + cosim); + f330 = 1.0 + cosim; + f330 = 1.875 * f330 * f330 * f330; + del1 = 3.0 * nm * nm * aonv * aonv; + del2 = 2.0 * del1 * f220 * g200 * q22; + del3 = 3.0 * del1 * f330 * g300 * q33 * aonv; + del1 = del1 * f311 * g310 * q31 * aonv; + xlamo = fmod(mo + nodeo + argpo - theta, twopi); + xfact = mdot + xpidot - rptim + dmdt + domdt + dnodt - no; + } + + /* ------------ for sgp4, initialize the integrator ---------- */ + xli = xlamo; + xni = no; + atime = 0.0; + nm = no + dndt; + } + +//#include "debug3.cpp" +} // end dsinit + +/*----------------------------------------------------------------------------- +* +* procedure dspace +* +* this procedure provides deep space contributions to mean elements for +* perturbing third body. these effects have been averaged over one +* revolution of the sun and moon. for earth resonance effects, the +* effects have been averaged over no revolutions of the satellite. +* (mean motion) +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 - +* dedt - +* del1, del2, del3 - +* didt - +* dmdt - +* dnodt - +* domdt - +* irez - flag for resonance 0-none, 1-one day, 2-half day +* argpo - argument of perigee +* argpdot - argument of perigee dot (rate) +* t - time +* tc - +* gsto - gst +* xfact - +* xlamo - +* no - mean motion +* atime - +* em - eccentricity +* ft - +* argpm - argument of perigee +* inclm - inclination +* xli - +* mm - mean anomaly +* xni - mean motion +* nodem - right ascension of ascending node +* +* outputs : +* atime - +* em - eccentricity +* argpm - argument of perigee +* inclm - inclination +* xli - +* mm - mean anomaly +* xni - +* nodem - right ascension of ascending node +* dndt - +* nm - mean motion +* +* locals : +* delt - +* ft - +* theta - +* x2li - +* x2omi - +* xl - +* xldot - +* xnddt - +* xndt - +* xomi - +* +* coupling : +* none - +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dspace + ( + int irez, + double d2201, double d2211, double d3210, double d3222, double d4410, + double d4422, double d5220, double d5232, double d5421, double d5433, + double dedt, double del1, double del2, double del3, double didt, + double dmdt, double dnodt, double domdt, double argpo, double argpdot, + double t, double tc, double gsto, double xfact, double xlamo, + double no, + double& atime, double& em, double& argpm, double& inclm, double& xli, + double& mm, double& xni, double& nodem, double& dndt, double& nm + ) +{ + const double twopi = 2.0 * pi; + int iretn , iret; + double delt, ft, theta, x2li, x2omi, xl, xldot , xnddt, xndt, xomi, g22, g32, + g44, g52, g54, fasx2, fasx4, fasx6, rptim , step2, stepn , stepp; + + ft = 0.0; + fasx2 = 0.13130908; + fasx4 = 2.8843198; + fasx6 = 0.37448087; + g22 = 5.7686396; + g32 = 0.95240898; + g44 = 1.8014998; + g52 = 1.0508330; + g54 = 4.4108898; + rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec + stepp = 720.0; + stepn = -720.0; + step2 = 259200.0; + + /* ----------- calculate deep space resonance effects ----------- */ + dndt = 0.0; + theta = fmod(gsto + tc * rptim, twopi); + em = em + dedt * t; + + inclm = inclm + didt * t; + argpm = argpm + domdt * t; + nodem = nodem + dnodt * t; + mm = mm + dmdt * t; + + // sgp4fix for negative inclinations + // the following if statement should be commented out + // if (inclm < 0.0) + // { + // inclm = -inclm; + // argpm = argpm - pi; + // nodem = nodem + pi; + // } + + /* - update resonances : numerical (euler-maclaurin) integration - */ + /* ------------------------- epoch restart ---------------------- */ + // sgp4fix for propagator problems + // the following integration works for negative time steps and periods + // the specific changes are unknown because the original code was so convoluted + + ft = 0.0; + atime = 0.0; + if (irez != 0) + { + if ((atime == 0.0) || ((t >= 0.0) && (atime < 0.0)) || + ((t < 0.0) && (atime >= 0.0))) + { + if (t >= 0.0) + delt = stepp; + else + delt = stepn; + atime = 0.0; + xni = no; + xli = xlamo; + } + iretn = 381; // added for do loop + iret = 0; // added for loop + while (iretn == 381) + { + if ((fabs(t) < fabs(atime)) || (iret == 351)) + { + if (t >= 0.0) + delt = stepn; + else + delt = stepp; + iret = 351; + iretn = 381; + } + else + { + if (t > 0.0) // error if prev if has atime:=0.0 and t:=0.0 (ge) + delt = stepp; + else + delt = stepn; + if (fabs(t - atime) >= stepp) + { + iret = 0; + iretn = 381; + } + else + { + ft = t - atime; + iretn = 0; + } + } + + /* ------------------- dot terms calculated ------------- */ + /* ----------- near - synchronous resonance terms ------- */ + if (irez != 2) + { + xndt = del1 * sin(xli - fasx2) + del2 * sin(2.0 * (xli - fasx4)) + + del3 * sin(3.0 * (xli - fasx6)); + xldot = xni + xfact; + xnddt = del1 * cos(xli - fasx2) + + 2.0 * del2 * cos(2.0 * (xli - fasx4)) + + 3.0 * del3 * cos(3.0 * (xli - fasx6)); + xnddt = xnddt * xldot; + } + else + { + /* --------- near - half-day resonance terms -------- */ + xomi = argpo + argpdot * atime; + x2omi = xomi + xomi; + x2li = xli + xli; + xndt = d2201 * sin(x2omi + xli - g22) + d2211 * sin(xli - g22) + + d3210 * sin(xomi + xli - g32) + d3222 * sin(-xomi + xli - g32)+ + d4410 * sin(x2omi + x2li - g44)+ d4422 * sin(x2li - g44) + + d5220 * sin(xomi + xli - g52) + d5232 * sin(-xomi + xli - g52)+ + d5421 * sin(xomi + x2li - g54) + d5433 * sin(-xomi + x2li - g54); + xldot = xni + xfact; + xnddt = d2201 * cos(x2omi + xli - g22) + d2211 * cos(xli - g22) + + d3210 * cos(xomi + xli - g32) + d3222 * cos(-xomi + xli - g32) + + d5220 * cos(xomi + xli - g52) + d5232 * cos(-xomi + xli - g52) + + 2.0 * (d4410 * cos(x2omi + x2li - g44) + + d4422 * cos(x2li - g44) + d5421 * cos(xomi + x2li - g54) + + d5433 * cos(-xomi + x2li - g54)); + xnddt = xnddt * xldot; + } + + /* ----------------------- integrator ------------------- */ + if (iretn == 381) + { + xli = xli + xldot * delt + xndt * step2; + xni = xni + xndt * delt + xnddt * step2; + atime = atime + delt; + } + } // while iretn = 381 + + nm = xni + xndt * ft + xnddt * ft * ft * 0.5; + xl = xli + xldot * ft + xndt * ft * ft * 0.5; + if (irez != 1) + { + mm = xl - 2.0 * nodem + 2.0 * theta; + dndt = nm - no; + } + else + { + mm = xl - nodem - argpm + theta; + dndt = nm - no; + } + nm = no + dndt; + } + +//#include "debug4.cpp" +} // end dsspace + +/*----------------------------------------------------------------------------- +* +* procedure initl +* +* this procedure initializes the spg4 propagator. all the initialization is +* consolidated here instead of having multiple loops inside other routines. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* ecco - eccentricity 0.0 - 1.0 +* epoch - epoch time in days from jan 0, 1950. 0 hr +* inclo - inclination of satellite +* no - mean motion of satellite +* satn - satellite number +* +* outputs : +* ainv - 1.0 / a +* ao - semi major axis +* con41 - +* con42 - 1.0 - 5.0 cos(i) +* cosio - cosine of inclination +* cosio2 - cosio squared +* eccsq - eccentricity squared +* method - flag for deep space 'd', 'n' +* omeosq - 1.0 - ecco * ecco +* posq - semi-parameter squared +* rp - radius of perigee +* rteosq - square root of (1.0 - ecco*ecco) +* sinio - sine of inclination +* gsto - gst at time of observation rad +* no - mean motion of satellite +* +* locals : +* ak - +* d1 - +* del - +* adel - +* po - +* +* coupling : +* getgravconst +* gstime - find greenwich sidereal time from the julian date +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void initl + ( + int satn, gravconsttype whichconst, + double ecco, double epoch, double inclo, double& no, + char& method, + double& ainv, double& ao, double& con41, double& con42, double& cosio, + double& cosio2,double& eccsq, double& omeosq, double& posq, + double& rp, double& rteosq,double& sinio , double& gsto + ) +{ + /* --------------------- local variables ------------------------ */ + double ak, d1, del, adel, po, x2o3, j2, xke, + tumin, mu, radiusearthkm, j3, j4, j3oj2; + + // sgp4fix use old way of finding gst + int ids70; + double ts70, ds70, tfrac, c1, thgr70, fk5r, c1p2p; + const double twopi = 2.0 * pi; + + /* ----------------------- earth constants ---------------------- */ + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + x2o3 = 2.0 / 3.0; + + /* ------------- calculate auxillary epoch quantities ---------- */ + eccsq = ecco * ecco; + omeosq = 1.0 - eccsq; + rteosq = sqrt(omeosq); + cosio = cos(inclo); + cosio2 = cosio * cosio; + + /* ------------------ un-kozai the mean motion ----------------- */ + ak = pow(xke / no, x2o3); + d1 = 0.75 * j2 * (3.0 * cosio2 - 1.0) / (rteosq * omeosq); + del = d1 / (ak * ak); + adel = ak * (1.0 - del * del - del * + (1.0 / 3.0 + 134.0 * del * del / 81.0)); + del = d1/(adel * adel); + no = no / (1.0 + del); + + ao = pow(xke / no, x2o3); + sinio = sin(inclo); + po = ao * omeosq; + con42 = 1.0 - 5.0 * cosio2; + con41 = -con42-cosio2-cosio2; + ainv = 1.0 / ao; + posq = po * po; + rp = ao * (1.0 - ecco); + method = 'n'; + + // sgp4fix modern approach to finding sidereal timew + // gsto = gstime(epoch + 2433281.5); + + // sgp4fix use old way of finding gst + // count integer number of days from 0 jan 1970 + ts70 = epoch - 7305.0; + ids70 = floor(ts70 + 1.0e-8); + ds70 = ids70; + tfrac = ts70 - ds70; + // find greenwich location at epoch + c1 = 1.72027916940703639e-2; + thgr70= 1.7321343856509374; + fk5r = 5.07551419432269442e-15; + c1p2p = c1 + twopi; + gsto = fmod( thgr70 + c1*ds70 + c1p2p*tfrac + ts70*ts70*fk5r, twopi); + if ( gsto < 0.0 ) + gsto = gsto + twopi; + +//#include "debug5.cpp" +} // end initl + +/*----------------------------------------------------------------------------- +* +* procedure sgp4init +* +* this procedure initializes variables for sgp4. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* satn - satellite number +* bstar - sgp4 type drag coefficient kg/m2er +* ecco - eccentricity +* epoch - epoch time in days from jan 0, 1950. 0 hr +* argpo - argument of perigee (output if ds) +* inclo - inclination +* mo - mean anomaly (output if ds) +* no - mean motion +* nodeo - right ascension of ascending node +* +* outputs : +* satrec - common values for subsequent calls +* return code - non-zero on error. +* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er +* 2 - mean motion less than 0.0 +* 3 - pert elements, ecc < 0.0 or ecc > 1.0 +* 4 - semi-latus rectum < 0.0 +* 5 - epoch elements are sub-orbital +* 6 - satellite has decayed +* +* locals : +* cnodm , snodm , cosim , sinim , cosomm , sinomm +* cc1sq , cc2 , cc3 +* coef , coef1 +* cosio4 - +* day - +* dndt - +* em - eccentricity +* emsq - eccentricity squared +* eeta - +* etasq - +* gam - +* argpm - argument of perigee +* nodem - +* inclm - inclination +* mm - mean anomaly +* nm - mean motion +* perige - perigee +* pinvsq - +* psisq - +* qzms24 - +* rtemsq - +* s1, s2, s3, s4, s5, s6, s7 - +* sfour - +* ss1, ss2, ss3, ss4, ss5, ss6, ss7 - +* sz1, sz2, sz3 +* sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33 - +* tc - +* temp - +* temp1, temp2, temp3 - +* tsi - +* xpidot - +* xhdot1 - +* z1, z2, z3 - +* z11, z12, z13, z21, z22, z23, z31, z32, z33 - +* +* coupling : +* getgravconst- +* initl - +* dscom - +* dpper - +* dsinit - +* sgp4 - +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +int sgp4init + ( + gravconsttype whichconst, const int satn, const double epoch, + const double xbstar, const double xecco, const double xargpo, + const double xinclo, const double xmo, const double xno, + const double xnodeo, elsetrec& satrec + ) +{ + /* --------------------- local variables ------------------------ */ + double ao, ainv, con42, cosio, sinio, cosio2, eccsq, + omeosq, posq, rp, rteosq, + cnodm , snodm , cosim , sinim , cosomm, sinomm, cc1sq , + cc2 , cc3 , coef , coef1 , cosio4, day , dndt , + em , emsq , eeta , etasq , gam , argpm , nodem , + inclm , mm , nm , perige, pinvsq, psisq , qzms24, + rtemsq, s1 , s2 , s3 , s4 , s5 , s6 , + s7 , sfour , ss1 = 0 , ss2 = 0 , ss3 = 0 , ss4 = 0 , ss5 = 0 , + ss6 = 0 , ss7 = 0 , sz1 = 0 , sz2 = 0 , sz3 = 0 , sz11 = 0 , sz12 = 0 , + sz13 = 0 , sz21 = 0 , sz22 = 0 , sz23 = 0 , sz31 = 0 , sz32 = 0 , sz33 = 0 , + tc , temp , temp1 , temp2 , temp3 , tsi , xpidot, + xhdot1, z1 , z2 , z3 , z11 , z12 , z13 , + z21 , z22 , z23 , z31 , z32 , z33, + qzms2t, ss, j2, j3oj2, j4, x2o3, r[3], v[3], + tumin, mu, radiusearthkm, xke, j3; + + /* ------------------------ initialization --------------------- */ + // sgp4fix divisor for divide by zero check on inclination + const double temp4 = 1.0 + cos(pi-1.0e-9); + + /* ----------- set all near earth variables to zero ------------ */ + satrec.isimp = 0; satrec.method = 'n'; satrec.aycof = 0.0; + satrec.con41 = 0.0; satrec.cc1 = 0.0; satrec.cc4 = 0.0; + satrec.cc5 = 0.0; satrec.d2 = 0.0; satrec.d3 = 0.0; + satrec.d4 = 0.0; satrec.delmo = 0.0; satrec.eta = 0.0; + satrec.argpdot = 0.0; satrec.omgcof = 0.0; satrec.sinmao = 0.0; + satrec.t = 0.0; satrec.t2cof = 0.0; satrec.t3cof = 0.0; + satrec.t4cof = 0.0; satrec.t5cof = 0.0; satrec.x1mth2 = 0.0; + satrec.x7thm1 = 0.0; satrec.mdot = 0.0; satrec.nodedot = 0.0; + satrec.xlcof = 0.0; satrec.xmcof = 0.0; satrec.nodecf = 0.0; + + /* ----------- set all deep space variables to zero ------------ */ + satrec.irez = 0; satrec.d2201 = 0.0; satrec.d2211 = 0.0; + satrec.d3210 = 0.0; satrec.d3222 = 0.0; satrec.d4410 = 0.0; + satrec.d4422 = 0.0; satrec.d5220 = 0.0; satrec.d5232 = 0.0; + satrec.d5421 = 0.0; satrec.d5433 = 0.0; satrec.dedt = 0.0; + satrec.del1 = 0.0; satrec.del2 = 0.0; satrec.del3 = 0.0; + satrec.didt = 0.0; satrec.dmdt = 0.0; satrec.dnodt = 0.0; + satrec.domdt = 0.0; satrec.e3 = 0.0; satrec.ee2 = 0.0; + satrec.peo = 0.0; satrec.pgho = 0.0; satrec.pho = 0.0; + satrec.pinco = 0.0; satrec.plo = 0.0; satrec.se2 = 0.0; + satrec.se3 = 0.0; satrec.sgh2 = 0.0; satrec.sgh3 = 0.0; + satrec.sgh4 = 0.0; satrec.sh2 = 0.0; satrec.sh3 = 0.0; + satrec.si2 = 0.0; satrec.si3 = 0.0; satrec.sl2 = 0.0; + satrec.sl3 = 0.0; satrec.sl4 = 0.0; satrec.gsto = 0.0; + satrec.xfact = 0.0; satrec.xgh2 = 0.0; satrec.xgh3 = 0.0; + satrec.xgh4 = 0.0; satrec.xh2 = 0.0; satrec.xh3 = 0.0; + satrec.xi2 = 0.0; satrec.xi3 = 0.0; satrec.xl2 = 0.0; + satrec.xl3 = 0.0; satrec.xl4 = 0.0; satrec.xlamo = 0.0; + satrec.zmol = 0.0; satrec.zmos = 0.0; satrec.atime = 0.0; + satrec.xli = 0.0; satrec.xni = 0.0; + + // sgp4fix - note the following variables are also passed directly via satrec. + // it is possible to streamline the sgp4init call by deleting the "x" + // variables, but the user would need to set the satrec.* values first. we + // include the additional assignments in case twoline2rv is not used. + satrec.bstar = xbstar; + satrec.ecco = xecco; + satrec.argpo = xargpo; + satrec.inclo = xinclo; + satrec.mo = xmo; + satrec.no = xno; + satrec.nodeo = xnodeo; + + /* ------------------------ earth constants ----------------------- */ + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + ss = 78.0 / radiusearthkm + 1.0; + qzms2t = pow(((120.0 - 78.0) / radiusearthkm), 4); + x2o3 = 2.0 / 3.0; + + satrec.init = 'y'; + satrec.t = 0.0; + + initl + ( + satn, whichconst, satrec.ecco, epoch, satrec.inclo, satrec.no, satrec.method, + ainv, ao, satrec.con41, con42, cosio, cosio2, eccsq, omeosq, + posq, rp, rteosq, sinio, satrec.gsto + ); + satrec.error = 0; + + if (rp < 1.0) + { +// printf("# *** satn%d epoch elts sub-orbital ***\n", satn); + satrec.error = 5; + } + + if ((omeosq >= 0.0 ) || ( satrec.no >= 0.0)) + { + satrec.isimp = 0; + if (rp < (220.0 / radiusearthkm + 1.0)) + satrec.isimp = 1; + sfour = ss; + qzms24 = qzms2t; + perige = (rp - 1.0) * radiusearthkm; + + /* - for perigees below 156 km, s and qoms2t are altered - */ + if (perige < 156.0) + { + sfour = perige - 78.0; + if (perige < 98.0) + sfour = 20.0; + qzms24 = pow(((120.0 - sfour) / radiusearthkm), 4.0); + sfour = sfour / radiusearthkm + 1.0; + } + pinvsq = 1.0 / posq; + + tsi = 1.0 / (ao - sfour); + satrec.eta = ao * satrec.ecco * tsi; + etasq = satrec.eta * satrec.eta; + eeta = satrec.ecco * satrec.eta; + psisq = fabs(1.0 - etasq); + coef = qzms24 * pow(tsi, 4.0); + coef1 = coef / pow(psisq, 3.5); + cc2 = coef1 * satrec.no * (ao * (1.0 + 1.5 * etasq + eeta * + (4.0 + etasq)) + 0.375 * j2 * tsi / psisq * satrec.con41 * + (8.0 + 3.0 * etasq * (8.0 + etasq))); + satrec.cc1 = satrec.bstar * cc2; + cc3 = 0.0; + if (satrec.ecco > 1.0e-4) + cc3 = -2.0 * coef * tsi * j3oj2 * satrec.no * sinio / satrec.ecco; + satrec.x1mth2 = 1.0 - cosio2; + satrec.cc4 = 2.0* satrec.no * coef1 * ao * omeosq * + (satrec.eta * (2.0 + 0.5 * etasq) + satrec.ecco * + (0.5 + 2.0 * etasq) - j2 * tsi / (ao * psisq) * + (-3.0 * satrec.con41 * (1.0 - 2.0 * eeta + etasq * + (1.5 - 0.5 * eeta)) + 0.75 * satrec.x1mth2 * + (2.0 * etasq - eeta * (1.0 + etasq)) * cos(2.0 * satrec.argpo))); + satrec.cc5 = 2.0 * coef1 * ao * omeosq * (1.0 + 2.75 * + (etasq + eeta) + eeta * etasq); + cosio4 = cosio2 * cosio2; + temp1 = 1.5 * j2 * pinvsq * satrec.no; + temp2 = 0.5 * temp1 * j2 * pinvsq; + temp3 = -0.46875 * j4 * pinvsq * pinvsq * satrec.no; + satrec.mdot = satrec.no + 0.5 * temp1 * rteosq * satrec.con41 + 0.0625 * + temp2 * rteosq * (13.0 - 78.0 * cosio2 + 137.0 * cosio4); + satrec.argpdot = -0.5 * temp1 * con42 + 0.0625 * temp2 * + (7.0 - 114.0 * cosio2 + 395.0 * cosio4) + + temp3 * (3.0 - 36.0 * cosio2 + 49.0 * cosio4); + xhdot1 = -temp1 * cosio; + satrec.nodedot = xhdot1 + (0.5 * temp2 * (4.0 - 19.0 * cosio2) + + 2.0 * temp3 * (3.0 - 7.0 * cosio2)) * cosio; + xpidot = satrec.argpdot+ satrec.nodedot; + satrec.omgcof = satrec.bstar * cc3 * cos(satrec.argpo); + satrec.xmcof = 0.0; + if (satrec.ecco > 1.0e-4) + satrec.xmcof = -x2o3 * coef * satrec.bstar / eeta; + satrec.nodecf = 3.5 * omeosq * xhdot1 * satrec.cc1; + satrec.t2cof = 1.5 * satrec.cc1; + // sgp4fix for divide by zero with xinco = 180 deg + if (fabs(cosio+1.0) > 1.5e-12) + satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / (1.0 + cosio); + else + satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / temp4; + satrec.aycof = -0.5 * j3oj2 * sinio; + satrec.delmo = pow((1.0 + satrec.eta * cos(satrec.mo)), 3); + satrec.sinmao = sin(satrec.mo); + satrec.x7thm1 = 7.0 * cosio2 - 1.0; + + /* --------------- deep space initialization ------------- */ + if ((2*pi / satrec.no) >= 225.0) + { + satrec.method = 'd'; + satrec.isimp = 1; + tc = 0.0; + inclm = satrec.inclo; + + dscom + ( + epoch, satrec.ecco, satrec.argpo, tc, satrec.inclo, satrec.nodeo, + satrec.no, snodm, cnodm, sinim, cosim,sinomm, cosomm, + day, satrec.e3, satrec.ee2, em, emsq, gam, + satrec.peo, satrec.pgho, satrec.pho, satrec.pinco, + satrec.plo, rtemsq, satrec.se2, satrec.se3, + satrec.sgh2, satrec.sgh3, satrec.sgh4, + satrec.sh2, satrec.sh3, satrec.si2, satrec.si3, + satrec.sl2, satrec.sl3, satrec.sl4, s1, s2, s3, s4, s5, + s6, s7, ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3, + sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33, + satrec.xgh2, satrec.xgh3, satrec.xgh4, satrec.xh2, + satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2, + satrec.xl3, satrec.xl4, nm, z1, z2, z3, z11, + z12, z13, z21, z22, z23, z31, z32, z33, + satrec.zmol, satrec.zmos + ); + dpper + ( + satrec.e3, satrec.ee2, satrec.peo, satrec.pgho, + satrec.pho, satrec.pinco, satrec.plo, satrec.se2, + satrec.se3, satrec.sgh2, satrec.sgh3, satrec.sgh4, + satrec.sh2, satrec.sh3, satrec.si2, satrec.si3, + satrec.sl2, satrec.sl3, satrec.sl4, satrec.t, + satrec.xgh2,satrec.xgh3,satrec.xgh4, satrec.xh2, + satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2, + satrec.xl3, satrec.xl4, satrec.zmol, satrec.zmos, inclm, satrec.init, + satrec.ecco, satrec.inclo, satrec.nodeo, satrec.argpo, satrec.mo + ); + + argpm = 0.0; + nodem = 0.0; + mm = 0.0; + + dsinit + ( + whichconst, + cosim, emsq, satrec.argpo, s1, s2, s3, s4, s5, sinim, ss1, ss2, ss3, ss4, + ss5, sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33, satrec.t, tc, + satrec.gsto, satrec.mo, satrec.mdot, satrec.no, satrec.nodeo, + satrec.nodedot, xpidot, z1, z3, z11, z13, z21, z23, z31, z33, + satrec.ecco, eccsq, em, argpm, inclm, mm, nm, nodem, + satrec.irez, satrec.atime, + satrec.d2201, satrec.d2211, satrec.d3210, satrec.d3222 , + satrec.d4410, satrec.d4422, satrec.d5220, satrec.d5232, + satrec.d5421, satrec.d5433, satrec.dedt, satrec.didt, + satrec.dmdt, dndt, satrec.dnodt, satrec.domdt , + satrec.del1, satrec.del2, satrec.del3, satrec.xfact, + satrec.xlamo, satrec.xli, satrec.xni + ); + } + + /* ----------- set variables if not deep space ----------- */ + if (satrec.isimp != 1) + { + cc1sq = satrec.cc1 * satrec.cc1; + satrec.d2 = 4.0 * ao * tsi * cc1sq; + temp = satrec.d2 * tsi * satrec.cc1 / 3.0; + satrec.d3 = (17.0 * ao + sfour) * temp; + satrec.d4 = 0.5 * temp * ao * tsi * (221.0 * ao + 31.0 * sfour) * + satrec.cc1; + satrec.t3cof = satrec.d2 + 2.0 * cc1sq; + satrec.t4cof = 0.25 * (3.0 * satrec.d3 + satrec.cc1 * + (12.0 * satrec.d2 + 10.0 * cc1sq)); + satrec.t5cof = 0.2 * (3.0 * satrec.d4 + + 12.0 * satrec.cc1 * satrec.d3 + + 6.0 * satrec.d2 * satrec.d2 + + 15.0 * cc1sq * (2.0 * satrec.d2 + cc1sq)); + } + } // if omeosq = 0 ... + + /* finally propogate to zero epoch to initialise all others. */ + if(satrec.error == 0) + sgp4(whichconst, satrec, 0.0, r, v); + + satrec.init = 'n'; + +//#include "debug6.cpp" + return satrec.error; +} // end sgp4init + +/*----------------------------------------------------------------------------- +* +* procedure sgp4 +* +* this procedure is the sgp4 prediction model from space command. this is an +* updated and combined version of sgp4 and sdp4, which were originally +* published separately in spacetrack report #3. this version follows the +* methodology from the aiaa paper (2006) describing the history and +* development of the code. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* satrec - initialised structure from sgp4init() call. +* tsince - time eince epoch (minutes) +* +* outputs : +* r - position vector km +* v - velocity km/sec +* return code - non-zero on error. +* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er +* 2 - mean motion less than 0.0 +* 3 - pert elements, ecc < 0.0 or ecc > 1.0 +* 4 - semi-latus rectum < 0.0 +* 5 - epoch elements are sub-orbital +* 6 - satellite has decayed +* +* locals : +* am - +* axnl, aynl - +* betal - +* cosim , sinim , cosomm , sinomm , cnod , snod , cos2u , +* sin2u , coseo1 , sineo1 , cosi , sini , cosip , sinip , +* cosisq , cossu , sinsu , cosu , sinu +* delm - +* delomg - +* dndt - +* eccm - +* emsq - +* ecose - +* el2 - +* eo1 - +* eccp - +* esine - +* argpm - +* argpp - +* omgadf - +* pl - +* r - +* rtemsq - +* rdotl - +* rl - +* rvdot - +* rvdotl - +* su - +* t2 , t3 , t4 , tc +* tem5, temp , temp1 , temp2 , tempa , tempe , templ +* u , ux , uy , uz , vx , vy , vz +* inclm - inclination +* mm - mean anomaly +* nm - mean motion +* nodem - right asc of ascending node +* xinc - +* xincp - +* xl - +* xlm - +* mp - +* xmdf - +* xmx - +* xmy - +* nodedf - +* xnode - +* nodep - +* np - +* +* coupling : +* getgravconst- +* dpper +* dpspace +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +int sgp4 + ( + gravconsttype whichconst, elsetrec& satrec, double tsince, + double r[3], double v[3] + ) +{ + double am , axnl , aynl , betal , cosim , cnod , + cos2u, coseo1, cosi , cosip , cosisq, cossu , cosu, + delm , delomg, em , emsq , ecose , el2 , eo1 , + ep , esine , argpm, argpp , argpdf, pl, mrt = 0.0, + mvt , rdotl , rl , rvdot , rvdotl, sinim , + sin2u, sineo1, sini , sinip , sinsu , sinu , + snod , su , t2 , t3 , t4 , tem5 , temp, + temp1, temp2 , tempa, tempe , templ , u , ux , + uy , uz , vx , vy , vz , inclm , mm , + nm , nodem, xinc , xincp , xl , xlm , mp , + xmdf , xmx , xmy , nodedf, xnode , nodep, tc , dndt, + twopi, x2o3 , j2 , j3 , tumin, j4 , xke , j3oj2, radiusearthkm, + mu, vkmpersec; + int ktr; + + /* ------------------ set mathematical constants --------------- */ + // sgp4fix divisor for divide by zero check on inclination + const double temp4 = 1.0 + cos(pi-1.0e-9); + twopi = 2.0 * pi; + x2o3 = 2.0 / 3.0; + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + vkmpersec = radiusearthkm * xke/60.0; + + /* --------------------- clear sgp4 error flag ----------------- */ + satrec.t = tsince; + satrec.error = 0; + + /* ------- update for secular gravity and atmospheric drag ----- */ + xmdf = satrec.mo + satrec.mdot * satrec.t; + argpdf = satrec.argpo + satrec.argpdot * satrec.t; + nodedf = satrec.nodeo + satrec.nodedot * satrec.t; + argpm = argpdf; + mm = xmdf; + t2 = satrec.t * satrec.t; + nodem = nodedf + satrec.nodecf * t2; + tempa = 1.0 - satrec.cc1 * satrec.t; + tempe = satrec.bstar * satrec.cc4 * satrec.t; + templ = satrec.t2cof * t2; + + if (satrec.isimp != 1) + { + delomg = satrec.omgcof * satrec.t; + delm = satrec.xmcof * + (pow((1.0 + satrec.eta * cos(xmdf)), 3) - + satrec.delmo); + temp = delomg + delm; + mm = xmdf + temp; + argpm = argpdf - temp; + t3 = t2 * satrec.t; + t4 = t3 * satrec.t; + tempa = tempa - satrec.d2 * t2 - satrec.d3 * t3 - + satrec.d4 * t4; + tempe = tempe + satrec.bstar * satrec.cc5 * (sin(mm) - + satrec.sinmao); + templ = templ + satrec.t3cof * t3 + t4 * (satrec.t4cof + + satrec.t * satrec.t5cof); + } + + nm = satrec.no; + em = satrec.ecco; + inclm = satrec.inclo; + if (satrec.method == 'd') + { + tc = satrec.t; + dspace + ( + satrec.irez, + satrec.d2201, satrec.d2211, satrec.d3210, + satrec.d3222, satrec.d4410, satrec.d4422, + satrec.d5220, satrec.d5232, satrec.d5421, + satrec.d5433, satrec.dedt, satrec.del1, + satrec.del2, satrec.del3, satrec.didt, + satrec.dmdt, satrec.dnodt, satrec.domdt, + satrec.argpo, satrec.argpdot, satrec.t, tc, + satrec.gsto, satrec.xfact, satrec.xlamo, + satrec.no, satrec.atime, + em, argpm, inclm, satrec.xli, mm, satrec.xni, + nodem, dndt, nm + ); + } // if method = d + + if (nm <= 0.0) + { +// printf("# error nm %f\n", nm); + satrec.error = 2; + } + am = pow((xke / nm),x2o3) * tempa * tempa; + nm = xke / pow(am, 1.5); + em = em - tempe; + + // fix tolerance for error recognition + if ((em >= 1.0) || (em < -0.001) || (am < 0.95)) + { +// printf("# error em %f\n", em); + satrec.error = 1; + } + if (em < 0.0) + em = 1.0e-6; + mm = mm + satrec.no * templ; + xlm = mm + argpm + nodem; + emsq = em * em; + temp = 1.0 - emsq; + + nodem = fmod(nodem, twopi); + argpm = fmod(argpm, twopi); + xlm = fmod(xlm, twopi); + mm = fmod(xlm - argpm - nodem, twopi); + + /* ----------------- compute extra mean quantities ------------- */ + sinim = sin(inclm); + cosim = cos(inclm); + + /* -------------------- add lunar-solar periodics -------------- */ + ep = em; + xincp = inclm; + argpp = argpm; + nodep = nodem; + mp = mm; + sinip = sinim; + cosip = cosim; + if (satrec.method == 'd') + { + dpper + ( + satrec.e3, satrec.ee2, satrec.peo, + satrec.pgho, satrec.pho, satrec.pinco, + satrec.plo, satrec.se2, satrec.se3, + satrec.sgh2, satrec.sgh3, satrec.sgh4, + satrec.sh2, satrec.sh3, satrec.si2, + satrec.si3, satrec.sl2, satrec.sl3, + satrec.sl4, satrec.t, satrec.xgh2, + satrec.xgh3, satrec.xgh4, satrec.xh2, + satrec.xh3, satrec.xi2, satrec.xi3, + satrec.xl2, satrec.xl3, satrec.xl4, + satrec.zmol, satrec.zmos, satrec.inclo, + 'n', ep, xincp, nodep, argpp, mp + ); + if (xincp < 0.0) + { + xincp = -xincp; + nodep = nodep + pi; + argpp = argpp - pi; + } + if ((ep < 0.0 ) || ( ep > 1.0)) + { + // printf("# error ep %f\n", ep); + satrec.error = 3; + } + } // if method = d + + /* -------------------- long period periodics ------------------ */ + if (satrec.method == 'd') + { + sinip = sin(xincp); + cosip = cos(xincp); + satrec.aycof = -0.5*j3oj2*sinip; + // sgp4fix for divide by zero for xincp = 180 deg + if (fabs(cosip+1.0) > 1.5e-12) + satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / (1.0 + cosip); + else + satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / temp4; + } + axnl = ep * cos(argpp); + temp = 1.0 / (am * (1.0 - ep * ep)); + aynl = ep* sin(argpp) + temp * satrec.aycof; + xl = mp + argpp + nodep + temp * satrec.xlcof * axnl; + + /* --------------------- solve kepler's equation --------------- */ + u = fmod(xl - nodep, twopi); + eo1 = u; + tem5 = 9999.9; + ktr = 1; + // sgp4fix for kepler iteration + // the following iteration needs better limits on corrections + while (( fabs(tem5) >= 1.0e-12) && (ktr <= 10) ) + { + sineo1 = sin(eo1); + coseo1 = cos(eo1); + tem5 = 1.0 - coseo1 * axnl - sineo1 * aynl; + tem5 = (u - aynl * coseo1 + axnl * sineo1 - eo1) / tem5; + if(fabs(tem5) >= 0.95) + tem5 = tem5 > 0.0 ? 0.95 : -0.95; + eo1 = eo1 + tem5; + ktr = ktr + 1; + } + + /* ------------- short period preliminary quantities ----------- */ + ecose = axnl*coseo1 + aynl*sineo1; + esine = axnl*sineo1 - aynl*coseo1; + el2 = axnl*axnl + aynl*aynl; + pl = am*(1.0-el2); + if (pl < 0.0) + { +// printf("# error pl %f\n", pl); + satrec.error = 4; + } + else + { + rl = am * (1.0 - ecose); + rdotl = sqrt(am) * esine/rl; + rvdotl = sqrt(pl) / rl; + betal = sqrt(1.0 - el2); + temp = esine / (1.0 + betal); + sinu = am / rl * (sineo1 - aynl - axnl * temp); + cosu = am / rl * (coseo1 - axnl + aynl * temp); + su = atan2(sinu, cosu); + sin2u = (cosu + cosu) * sinu; + cos2u = 1.0 - 2.0 * sinu * sinu; + temp = 1.0 / pl; + temp1 = 0.5 * j2 * temp; + temp2 = temp1 * temp; + + /* -------------- update for short period periodics ------------ */ + if (satrec.method == 'd') + { + cosisq = cosip * cosip; + satrec.con41 = 3.0*cosisq - 1.0; + satrec.x1mth2 = 1.0 - cosisq; + satrec.x7thm1 = 7.0*cosisq - 1.0; + } + mrt = rl * (1.0 - 1.5 * temp2 * betal * satrec.con41) + + 0.5 * temp1 * satrec.x1mth2 * cos2u; + su = su - 0.25 * temp2 * satrec.x7thm1 * sin2u; + xnode = nodep + 1.5 * temp2 * cosip * sin2u; + xinc = xincp + 1.5 * temp2 * cosip * sinip * cos2u; + mvt = rdotl - nm * temp1 * satrec.x1mth2 * sin2u / xke; + rvdot = rvdotl + nm * temp1 * (satrec.x1mth2 * cos2u + + 1.5 * satrec.con41) / xke; + + /* --------------------- orientation vectors ------------------- */ + sinsu = sin(su); + cossu = cos(su); + snod = sin(xnode); + cnod = cos(xnode); + sini = sin(xinc); + cosi = cos(xinc); + xmx = -snod * cosi; + xmy = cnod * cosi; + ux = xmx * sinsu + cnod * cossu; + uy = xmy * sinsu + snod * cossu; + uz = sini * sinsu; + vx = xmx * cossu - cnod * sinsu; + vy = xmy * cossu - snod * sinsu; + vz = sini * cossu; + + /* --------- position and velocity (in km and km/sec) ---------- */ + r[0] = (mrt * ux)* radiusearthkm; + r[1] = (mrt * uy)* radiusearthkm; + r[2] = (mrt * uz)* radiusearthkm; + v[0] = (mvt * ux + rvdot * vx) * vkmpersec; + v[1] = (mvt * uy + rvdot * vy) * vkmpersec; + v[2] = (mvt * uz + rvdot * vz) * vkmpersec; + } // if pl > 0 + + // sgp4fix for decaying satellites + if (mrt < 1.0) + { +// printf("# decay condition %11.6f \n",mrt); + satrec.error = 6; + } + + +//#include "debug7.cpp" + return satrec.error; +} // end sgp4 + + +/* ----------------------------------------------------------------------------- +* +* function gstime +* +* this function finds the greenwich sidereal time. +* +* author : david vallado 719-573-2600 1 mar 2001 +* +* inputs description range / units +* jdut1 - julian date in ut1 days from 4713 bc +* +* outputs : +* gstime - greenwich sidereal time 0 to 2pi rad +* +* locals : +* temp - temporary variable for doubles rad +* tut1 - julian centuries from the +* jan 1, 2000 12 h epoch (ut1) +* +* coupling : +* none +* +* references : +* vallado 2004, 191, eq 3-45 +* --------------------------------------------------------------------------- */ + +double gstime + ( + double jdut1 + ) + { + const double twopi = 2.0 * pi; + const double deg2rad = pi / 180.0; + double temp, tut1; + + tut1 = (jdut1 - 2451545.0) / 36525.0; + temp = -6.2e-6* tut1 * tut1 * tut1 + 0.093104 * tut1 * tut1 + + (876600.0*3600 + 8640184.812866) * tut1 + 67310.54841; // sec + temp = fmod(temp * deg2rad / 240.0, twopi); //360/86400 = 1/240, to deg, to rad + + // ------------------------ check quadrants --------------------- + if (temp < 0.0) + temp += twopi; + + return temp; + } // end gstime + +/* ----------------------------------------------------------------------------- +* +* function getgravconst +* +* this function gets constants for the propagator. note that mu is identified to +* facilitiate comparisons with newer models. the common useage is wgs72. +* +* author : david vallado 719-573-2600 21 jul 2006 +* +* inputs : +* whichconst - which set of constants to use wgs72old, wgs72, wgs84 +* +* outputs : +* tumin - minutes in one time unit +* mu - earth gravitational parameter +* radiusearthkm - radius of the earth in km +* xke - reciprocal of tumin +* j2, j3, j4 - un-normalized zonal harmonic values +* j3oj2 - j3 divided by j2 +* +* locals : +* +* coupling : +* none +* +* references : +* norad spacetrack report #3 +* vallado, crawford, hujsak, kelso 2006 + --------------------------------------------------------------------------- */ + +void getgravconst + ( + gravconsttype whichconst, + double& tumin, + double& mu, + double& radiusearthkm, + double& xke, + double& j2, + double& j3, + double& j4, + double& j3oj2 + ) + { + + switch (whichconst) + { + // -- wgs-72 low precision str#3 constants -- + case wgs72old: + mu = 398600.79964; // in km3 / s2 + radiusearthkm = 6378.135; // km + xke = 0.0743669161; + tumin = 1.0 / xke; + j2 = 0.001082616; + j3 = -0.00000253881; + j4 = -0.00000165597; + j3oj2 = j3 / j2; + break; + // ------------ wgs-72 constants ------------ + case wgs72: + mu = 398600.8; // in km3 / s2 + radiusearthkm = 6378.135; // km + xke = 60.0 / sqrt(radiusearthkm*radiusearthkm*radiusearthkm/mu); + tumin = 1.0 / xke; + j2 = 0.001082616; + j3 = -0.00000253881; + j4 = -0.00000165597; + j3oj2 = j3 / j2; + break; + case wgs84: + // ------------ wgs-84 constants ------------ + mu = 398600.5; // in km3 / s2 + radiusearthkm = 6378.137; // km + xke = 60.0 / sqrt(radiusearthkm*radiusearthkm*radiusearthkm/mu); + tumin = 1.0 / xke; + j2 = 0.00108262998905; + j3 = -0.00000253215306; + j4 = -0.00000161098761; + j3oj2 = j3 / j2; + break; + default: + fprintf(stderr,"unknown gravity option (%d)\n",whichconst); + break; + } + + } // end getgravconst + + + + + diff --git a/contrib/sgp4/sgp4unit.h b/contrib/sgp4/sgp4unit.h index f16acbd9..48c113d7 100644 --- a/contrib/sgp4/sgp4unit.h +++ b/contrib/sgp4/sgp4unit.h @@ -1,117 +1,117 @@ -#ifndef _sgp4unit_ -#define _sgp4unit_ -/* ---------------------------------------------------------------- -* -* sgp4unit.h -* -* this file contains the sgp4 procedures for analytical propagation -* of a satellite. the code was originally released in the 1980 and 1986 -* spacetrack papers. a detailed discussion of the theory and history -* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, -* and kelso. -* -* companion code for -* fundamentals of astrodynamics and applications -* 2007 -* by david vallado -* -* (w) 719-573-2600, email dvallado@agi.com -* -* current : -* 20 apr 07 david vallado -* misc fixes for constants -* changes : -* 11 aug 06 david vallado -* chg lyddane choice back to strn3, constants, misc doc -* 15 dec 05 david vallado -* misc fixes -* 26 jul 05 david vallado -* fixes for paper -* note that each fix is preceded by a -* comment with "sgp4fix" and an explanation of -* what was changed -* 10 aug 04 david vallado -* 2nd printing baseline working -* 14 may 01 david vallado -* 2nd edition baseline -* 80 norad -* original baseline -* ---------------------------------------------------------------- */ - -#include -#include - -// -------------------------- structure declarations ---------------------------- -typedef enum -{ - wgs72old, - wgs72, - wgs84 -} gravconsttype; - -typedef struct elsetrec -{ - long int satnum; - int epochyr, epochtynumrev; - int error; - char init, method; - - /* Near Earth */ - int isimp; - double aycof , con41 , cc1 , cc4 , cc5 , d2 , d3 , d4 , - delmo , eta , argpdot, omgcof , sinmao , t , t2cof, t3cof , - t4cof , t5cof , x1mth2 , x7thm1 , mdot , nodedot, xlcof , xmcof , - nodecf; - - /* Deep Space */ - int irez; - double d2201 , d2211 , d3210 , d3222 , d4410 , d4422 , d5220 , d5232 , - d5421 , d5433 , dedt , del1 , del2 , del3 , didt , dmdt , - dnodt , domdt , e3 , ee2 , peo , pgho , pho , pinco , - plo , se2 , se3 , sgh2 , sgh3 , sgh4 , sh2 , sh3 , - si2 , si3 , sl2 , sl3 , sl4 , gsto , xfact , xgh2 , - xgh3 , xgh4 , xh2 , xh3 , xi2 , xi3 , xl2 , xl3 , - xl4 , xlamo , zmol , zmos , atime , xli , xni; - - double a , altp , alta , epochdays, jdsatepoch , nddot , ndot , - bstar , rcse , inclo , nodeo , ecco , argpo , mo , - no; -} elsetrec; - -// --------------------------- function declarations ---------------------------- -int sgp4init - ( - gravconsttype whichconst, const int satn, const double epoch, - const double xbstar, const double xecco, const double xargpo, - const double xinclo, const double xmo, const double xno, - const double xnodeo, - elsetrec& satrec - ); - -int sgp4 - ( - gravconsttype whichconst, - elsetrec& satrec, double tsince, - double r[], double v[] - ); - -double gstime - ( - double - ); - -void getgravconst - ( - gravconsttype, - double&, - double&, - double&, - double&, - double&, - double&, - double&, - double& - ); - -#endif - +#ifndef _sgp4unit_ +#define _sgp4unit_ +/* ---------------------------------------------------------------- +* +* sgp4unit.h +* +* this file contains the sgp4 procedures for analytical propagation +* of a satellite. the code was originally released in the 1980 and 1986 +* spacetrack papers. a detailed discussion of the theory and history +* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, +* and kelso. +* +* companion code for +* fundamentals of astrodynamics and applications +* 2007 +* by david vallado +* +* (w) 719-573-2600, email dvallado@agi.com +* +* current : +* 20 apr 07 david vallado +* misc fixes for constants +* changes : +* 11 aug 06 david vallado +* chg lyddane choice back to strn3, constants, misc doc +* 15 dec 05 david vallado +* misc fixes +* 26 jul 05 david vallado +* fixes for paper +* note that each fix is preceded by a +* comment with "sgp4fix" and an explanation of +* what was changed +* 10 aug 04 david vallado +* 2nd printing baseline working +* 14 may 01 david vallado +* 2nd edition baseline +* 80 norad +* original baseline +* ---------------------------------------------------------------- */ + +#include +#include + +// -------------------------- structure declarations ---------------------------- +typedef enum +{ + wgs72old, + wgs72, + wgs84 +} gravconsttype; + +typedef struct elsetrec +{ + long int satnum; + int epochyr, epochtynumrev; + int error; + char init, method; + + /* Near Earth */ + int isimp; + double aycof , con41 , cc1 , cc4 , cc5 , d2 , d3 , d4 , + delmo , eta , argpdot, omgcof , sinmao , t , t2cof, t3cof , + t4cof , t5cof , x1mth2 , x7thm1 , mdot , nodedot, xlcof , xmcof , + nodecf; + + /* Deep Space */ + int irez; + double d2201 , d2211 , d3210 , d3222 , d4410 , d4422 , d5220 , d5232 , + d5421 , d5433 , dedt , del1 , del2 , del3 , didt , dmdt , + dnodt , domdt , e3 , ee2 , peo , pgho , pho , pinco , + plo , se2 , se3 , sgh2 , sgh3 , sgh4 , sh2 , sh3 , + si2 , si3 , sl2 , sl3 , sl4 , gsto , xfact , xgh2 , + xgh3 , xgh4 , xh2 , xh3 , xi2 , xi3 , xl2 , xl3 , + xl4 , xlamo , zmol , zmos , atime , xli , xni; + + double a , altp , alta , epochdays, jdsatepoch , nddot , ndot , + bstar , rcse , inclo , nodeo , ecco , argpo , mo , + no; +} elsetrec; + +// --------------------------- function declarations ---------------------------- +int sgp4init + ( + gravconsttype whichconst, const int satn, const double epoch, + const double xbstar, const double xecco, const double xargpo, + const double xinclo, const double xmo, const double xno, + const double xnodeo, + elsetrec& satrec + ); + +int sgp4 + ( + gravconsttype whichconst, + elsetrec& satrec, double tsince, + double r[], double v[] + ); + +double gstime + ( + double + ); + +void getgravconst + ( + gravconsttype, + double&, + double&, + double&, + double&, + double&, + double&, + double&, + double& + ); + +#endif + diff --git a/devicehandlers/ChildHandlerBase.cpp b/devicehandlers/ChildHandlerBase.cpp index e800cd56..f18c3812 100644 --- a/devicehandlers/ChildHandlerBase.cpp +++ b/devicehandlers/ChildHandlerBase.cpp @@ -1,45 +1,45 @@ -#include "../subsystem/SubsystemBase.h" -#include "../devicehandlers/ChildHandlerBase.h" -#include "../subsystem/SubsystemBase.h" - -ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId, - object_id_t deviceCommunication, CookieIF * cookie, - uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, - object_id_t parent, FailureIsolationBase* customFdir, - size_t cmdQueueSize) : - DeviceHandlerBase(setObjectId, deviceCommunication, cookie, - (customFdir == nullptr? &childHandlerFdir : customFdir), - cmdQueueSize), - parentId(parent), childHandlerFdir(setObjectId) { - this->setThermalStateRequestPoolIds(thermalStatePoolId, - thermalRequestPoolId); - -} - -ChildHandlerBase::~ChildHandlerBase() { -} - -ReturnValue_t ChildHandlerBase::initialize() { - ReturnValue_t result = DeviceHandlerBase::initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - - MessageQueueId_t parentQueue = 0; - - if (parentId != objects::NO_OBJECT) { - SubsystemBase *parent = objectManager->get(parentId); - if (parent == NULL) { - return RETURN_FAILED; - } - parentQueue = parent->getCommandQueue(); - - parent->registerChild(getObjectId()); - } - - healthHelper.setParentQueue(parentQueue); - - modeHelper.setParentQueue(parentQueue); - - return RETURN_OK; -} +#include "../subsystem/SubsystemBase.h" +#include "../devicehandlers/ChildHandlerBase.h" +#include "../subsystem/SubsystemBase.h" + +ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId, + object_id_t deviceCommunication, CookieIF * cookie, + uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, + object_id_t parent, FailureIsolationBase* customFdir, + size_t cmdQueueSize) : + DeviceHandlerBase(setObjectId, deviceCommunication, cookie, + (customFdir == nullptr? &childHandlerFdir : customFdir), + cmdQueueSize), + parentId(parent), childHandlerFdir(setObjectId) { + this->setThermalStateRequestPoolIds(thermalStatePoolId, + thermalRequestPoolId); + +} + +ChildHandlerBase::~ChildHandlerBase() { +} + +ReturnValue_t ChildHandlerBase::initialize() { + ReturnValue_t result = DeviceHandlerBase::initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + MessageQueueId_t parentQueue = 0; + + if (parentId != objects::NO_OBJECT) { + SubsystemBase *parent = objectManager->get(parentId); + if (parent == NULL) { + return RETURN_FAILED; + } + parentQueue = parent->getCommandQueue(); + + parent->registerChild(getObjectId()); + } + + healthHelper.setParentQueue(parentQueue); + + modeHelper.setParentQueue(parentQueue); + + return RETURN_OK; +} diff --git a/devicehandlers/ChildHandlerBase.h b/devicehandlers/ChildHandlerBase.h index f6bf318a..3e9652a3 100644 --- a/devicehandlers/ChildHandlerBase.h +++ b/devicehandlers/ChildHandlerBase.h @@ -1,26 +1,26 @@ #ifndef FSFW_DEVICES_CHILDHANDLERBASE_H_ -#define FSFW_DEVICES_CHILDHANDLERBASE_H_ - -#include "ChildHandlerFDIR.h" -#include "DeviceHandlerBase.h" - -class ChildHandlerBase: public DeviceHandlerBase { -public: - ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, - CookieIF * cookie, uint32_t thermalStatePoolId, +#define FSFW_DEVICES_CHILDHANDLERBASE_H_ + +#include "ChildHandlerFDIR.h" +#include "DeviceHandlerBase.h" + +class ChildHandlerBase: public DeviceHandlerBase { +public: + ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, + CookieIF * cookie, uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, - object_id_t parent = objects::NO_OBJECT, + object_id_t parent = objects::NO_OBJECT, FailureIsolationBase* customFdir = nullptr, - size_t cmdQueueSize = 20); - virtual ~ChildHandlerBase(); - - virtual ReturnValue_t initialize(); - -protected: - const uint32_t parentId; - ChildHandlerFDIR childHandlerFdir; - -}; - -#endif /* FSFW_DEVICES_CHILDHANDLERBASE_H_ */ + size_t cmdQueueSize = 20); + virtual ~ChildHandlerBase(); + + virtual ReturnValue_t initialize(); + +protected: + const uint32_t parentId; + ChildHandlerFDIR childHandlerFdir; + +}; + +#endif /* FSFW_DEVICES_CHILDHANDLERBASE_H_ */ diff --git a/osal/FreeRTOS/TaskManagement.cpp b/osal/FreeRTOS/TaskManagement.cpp index b77f12a9..16682d36 100644 --- a/osal/FreeRTOS/TaskManagement.cpp +++ b/osal/FreeRTOS/TaskManagement.cpp @@ -1,24 +1,24 @@ -#include "../../osal/FreeRTOS/TaskManagement.h" - -void TaskManagement::vRequestContextSwitchFromTask() { - vTaskDelay(0); -} - -void TaskManagement::requestContextSwitch( - CallContext callContext = CallContext::TASK) { - if(callContext == CallContext::ISR) { - // This function depends on the partmacro.h definition for the specific device - vRequestContextSwitchFromISR(); - } else { - vRequestContextSwitchFromTask(); - } -} - -TaskHandle_t TaskManagement::getCurrentTaskHandle() { - return xTaskGetCurrentTaskHandle(); -} - -size_t TaskManagement::getTaskStackHighWatermark( - TaskHandle_t task) { - return uxTaskGetStackHighWaterMark(task) * sizeof(StackType_t); -} +#include "../../osal/FreeRTOS/TaskManagement.h" + +void TaskManagement::vRequestContextSwitchFromTask() { + vTaskDelay(0); +} + +void TaskManagement::requestContextSwitch( + CallContext callContext = CallContext::TASK) { + if(callContext == CallContext::ISR) { + // This function depends on the partmacro.h definition for the specific device + vRequestContextSwitchFromISR(); + } else { + vRequestContextSwitchFromTask(); + } +} + +TaskHandle_t TaskManagement::getCurrentTaskHandle() { + return xTaskGetCurrentTaskHandle(); +} + +size_t TaskManagement::getTaskStackHighWatermark( + TaskHandle_t task) { + return uxTaskGetStackHighWaterMark(task) * sizeof(StackType_t); +} diff --git a/osal/FreeRTOS/TaskManagement.h b/osal/FreeRTOS/TaskManagement.h index 4b7fe3eb..43003d76 100644 --- a/osal/FreeRTOS/TaskManagement.h +++ b/osal/FreeRTOS/TaskManagement.h @@ -1,64 +1,64 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ -#define FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ - -#include "../../returnvalues/HasReturnvaluesIF.h" - -extern "C" { -#include -#include -} -#include - -/** - * Architecture dependant portmacro.h function call. - * Should be implemented in bsp. - */ -extern void vRequestContextSwitchFromISR(); - -/*! - * Used by functions to tell if they are being called from - * within an ISR or from a regular task. This is required because FreeRTOS - * has different functions for handling semaphores and messages from within - * an ISR and task. - */ -enum class CallContext { - TASK = 0x00,//!< task_context - ISR = 0xFF //!< isr_context -}; - - -class TaskManagement { -public: - /** - * @brief In this function, a function dependant on the portmacro.h header - * function calls to request a context switch can be specified. - * This can be used if sending to the queue from an ISR caused a task - * to unblock and a context switch is required. - */ - static void requestContextSwitch(CallContext callContext); - - /** - * If task preemption in FreeRTOS is disabled, a context switch - * can be requested manually by calling this function. - */ - static void vRequestContextSwitchFromTask(void); - - /** - * @return The current task handle - */ - static TaskHandle_t getCurrentTaskHandle(); - - /** - * Get returns the minimum amount of remaining stack space in words - * that was a available to the task since the task started executing. - * Please note that the actual value in bytes depends - * on the stack depth type. - * E.g. on a 32 bit machine, a value of 200 means 800 bytes. - * @return Smallest value of stack remaining since the task was started in - * words. - */ - static size_t getTaskStackHighWatermark( - TaskHandle_t task = nullptr); -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ +#define FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ + +#include "../../returnvalues/HasReturnvaluesIF.h" + +extern "C" { +#include +#include +} +#include + +/** + * Architecture dependant portmacro.h function call. + * Should be implemented in bsp. + */ +extern void vRequestContextSwitchFromISR(); + +/*! + * Used by functions to tell if they are being called from + * within an ISR or from a regular task. This is required because FreeRTOS + * has different functions for handling semaphores and messages from within + * an ISR and task. + */ +enum class CallContext { + TASK = 0x00,//!< task_context + ISR = 0xFF //!< isr_context +}; + + +class TaskManagement { +public: + /** + * @brief In this function, a function dependant on the portmacro.h header + * function calls to request a context switch can be specified. + * This can be used if sending to the queue from an ISR caused a task + * to unblock and a context switch is required. + */ + static void requestContextSwitch(CallContext callContext); + + /** + * If task preemption in FreeRTOS is disabled, a context switch + * can be requested manually by calling this function. + */ + static void vRequestContextSwitchFromTask(void); + + /** + * @return The current task handle + */ + static TaskHandle_t getCurrentTaskHandle(); + + /** + * Get returns the minimum amount of remaining stack space in words + * that was a available to the task since the task started executing. + * Please note that the actual value in bytes depends + * on the stack depth type. + * E.g. on a 32 bit machine, a value of 200 means 800 bytes. + * @return Smallest value of stack remaining since the task was started in + * words. + */ + static size_t getTaskStackHighWatermark( + TaskHandle_t task = nullptr); +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */ diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index 1c11afd4..812cd34b 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -1,129 +1,129 @@ -#include "../serialize/SerialBufferAdapter.h" -#include "../serviceinterface/ServiceInterfaceStream.h" -#include - -template -SerialBufferAdapter::SerialBufferAdapter(const uint8_t* buffer, - count_t bufferLength, bool serializeLength) : - serializeLength(serializeLength), - constBuffer(buffer), buffer(nullptr), - bufferLength(bufferLength) {} - -template -SerialBufferAdapter::SerialBufferAdapter(uint8_t* buffer, - count_t bufferLength, bool serializeLength) : - serializeLength(serializeLength), constBuffer(buffer), buffer(buffer), - bufferLength(bufferLength) {} - - -template -SerialBufferAdapter::~SerialBufferAdapter() { -} - -template -ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, - size_t* size, size_t maxSize, Endianness streamEndianness) const { - if (serializeLength) { - ReturnValue_t result = SerializeAdapter::serialize(&bufferLength, - buffer, size, maxSize, streamEndianness); - if(result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - } - - if (*size + bufferLength > maxSize) { - return BUFFER_TOO_SHORT; - } - - if (this->constBuffer != nullptr) { - std::memcpy(*buffer, this->constBuffer, bufferLength); - } - else if (this->buffer != nullptr) { - // This will propably be never reached, constBuffer should always be - // set if non-const buffer is set. - std::memcpy(*buffer, this->buffer, bufferLength); - } - else { - return HasReturnvaluesIF::RETURN_FAILED; - } - *size += bufferLength; - (*buffer) += bufferLength; - return HasReturnvaluesIF::RETURN_OK; - -} - -template -size_t SerialBufferAdapter::getSerializedSize() const { - if (serializeLength) { - return bufferLength + SerializeAdapter::getSerializedSize(&bufferLength); - } else { - return bufferLength; - } -} - -template -ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, - size_t* size, Endianness streamEndianness) { - if (this->buffer == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - - if(serializeLength){ - count_t lengthField = 0; - ReturnValue_t result = SerializeAdapter::deSerialize(&lengthField, - buffer, size, streamEndianness); - if(result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - if(lengthField > bufferLength) { - return TOO_MANY_ELEMENTS; - } - bufferLength = lengthField; - } - - if (bufferLength <= *size) { - *size -= bufferLength; - std::memcpy(this->buffer, *buffer, bufferLength); - (*buffer) += bufferLength; - return HasReturnvaluesIF::RETURN_OK; - } - else { - return STREAM_TOO_SHORT; - } -} - -template -uint8_t * SerialBufferAdapter::getBuffer() { - if(buffer == nullptr) { - sif::error << "Wrong access function for stored type !" - " Use getConstBuffer()." << std::endl; - return nullptr; - } - return buffer; -} - -template -const uint8_t * SerialBufferAdapter::getConstBuffer() { - if(constBuffer == nullptr) { - sif::error << "SerialBufferAdapter::getConstBuffer:" - " Buffers are unitialized!" << std::endl; - return nullptr; - } - return constBuffer; -} - -template -void SerialBufferAdapter::setBuffer(uint8_t* buffer, - count_t bufferLength) { - this->buffer = buffer; - this->constBuffer = buffer; - this->bufferLength = bufferLength; -} - - -//forward Template declaration for linker -template class SerialBufferAdapter; -template class SerialBufferAdapter; -template class SerialBufferAdapter; -template class SerialBufferAdapter; - +#include "../serialize/SerialBufferAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include + +template +SerialBufferAdapter::SerialBufferAdapter(const uint8_t* buffer, + count_t bufferLength, bool serializeLength) : + serializeLength(serializeLength), + constBuffer(buffer), buffer(nullptr), + bufferLength(bufferLength) {} + +template +SerialBufferAdapter::SerialBufferAdapter(uint8_t* buffer, + count_t bufferLength, bool serializeLength) : + serializeLength(serializeLength), constBuffer(buffer), buffer(buffer), + bufferLength(bufferLength) {} + + +template +SerialBufferAdapter::~SerialBufferAdapter() { +} + +template +ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, + size_t* size, size_t maxSize, Endianness streamEndianness) const { + if (serializeLength) { + ReturnValue_t result = SerializeAdapter::serialize(&bufferLength, + buffer, size, maxSize, streamEndianness); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + + if (*size + bufferLength > maxSize) { + return BUFFER_TOO_SHORT; + } + + if (this->constBuffer != nullptr) { + std::memcpy(*buffer, this->constBuffer, bufferLength); + } + else if (this->buffer != nullptr) { + // This will propably be never reached, constBuffer should always be + // set if non-const buffer is set. + std::memcpy(*buffer, this->buffer, bufferLength); + } + else { + return HasReturnvaluesIF::RETURN_FAILED; + } + *size += bufferLength; + (*buffer) += bufferLength; + return HasReturnvaluesIF::RETURN_OK; + +} + +template +size_t SerialBufferAdapter::getSerializedSize() const { + if (serializeLength) { + return bufferLength + SerializeAdapter::getSerializedSize(&bufferLength); + } else { + return bufferLength; + } +} + +template +ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, + size_t* size, Endianness streamEndianness) { + if (this->buffer == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + + if(serializeLength){ + count_t lengthField = 0; + ReturnValue_t result = SerializeAdapter::deSerialize(&lengthField, + buffer, size, streamEndianness); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + if(lengthField > bufferLength) { + return TOO_MANY_ELEMENTS; + } + bufferLength = lengthField; + } + + if (bufferLength <= *size) { + *size -= bufferLength; + std::memcpy(this->buffer, *buffer, bufferLength); + (*buffer) += bufferLength; + return HasReturnvaluesIF::RETURN_OK; + } + else { + return STREAM_TOO_SHORT; + } +} + +template +uint8_t * SerialBufferAdapter::getBuffer() { + if(buffer == nullptr) { + sif::error << "Wrong access function for stored type !" + " Use getConstBuffer()." << std::endl; + return nullptr; + } + return buffer; +} + +template +const uint8_t * SerialBufferAdapter::getConstBuffer() { + if(constBuffer == nullptr) { + sif::error << "SerialBufferAdapter::getConstBuffer:" + " Buffers are unitialized!" << std::endl; + return nullptr; + } + return constBuffer; +} + +template +void SerialBufferAdapter::setBuffer(uint8_t* buffer, + count_t bufferLength) { + this->buffer = buffer; + this->constBuffer = buffer; + this->bufferLength = bufferLength; +} + + +//forward Template declaration for linker +template class SerialBufferAdapter; +template class SerialBufferAdapter; +template class SerialBufferAdapter; +template class SerialBufferAdapter; + diff --git a/serialize/SerialBufferAdapter.h b/serialize/SerialBufferAdapter.h index 9a89e18b..c3dfcd8f 100644 --- a/serialize/SerialBufferAdapter.h +++ b/serialize/SerialBufferAdapter.h @@ -1,78 +1,78 @@ -#ifndef SERIALBUFFERADAPTER_H_ -#define SERIALBUFFERADAPTER_H_ - -#include "../serialize/SerializeIF.h" -#include "../serialize/SerializeAdapter.h" - -/** - * 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>. - * Right now, the SerialBufferAdapter must always - * be initialized with the buffer and size ! - * - * \ingroup serialize - */ -template -class SerialBufferAdapter: public SerializeIF { -public: - - /** - * Constructor for constant uint8_t buffer. Length field can be serialized optionally. - * Type of length can be supplied as template type. - * @param buffer - * @param bufferLength - * @param serializeLength - */ - SerialBufferAdapter(const uint8_t* buffer, count_t bufferLength, - bool serializeLength = false); - - /** - * Constructor for non-constant uint8_t buffer. - * Length field can be serialized optionally. - * Type of length can be supplied as template type. - * @param buffer - * @param bufferLength - * @param serializeLength Length field will be serialized with size count_t - */ - SerialBufferAdapter(uint8_t* buffer, count_t bufferLength, - bool serializeLength = false); - - virtual ~SerialBufferAdapter(); - - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, - size_t maxSize, Endianness streamEndianness) const override; - - virtual size_t getSerializedSize() const override; - - /** - * @brief This function deserializes a buffer into the member buffer. - * @details - * If a length field is present, it is ignored, as the size should have - * been set in the constructor. If the size is not known beforehand, - * consider using SerialFixedArrayListAdapter instead. - * @param buffer [out] Resulting buffer - * @param size remaining size to deserialize, should be larger than buffer - * + size field size - * @param bigEndian - * @return - */ - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) override; - - uint8_t * getBuffer(); - const uint8_t * getConstBuffer(); - void setBuffer(uint8_t* buffer, count_t bufferLength); -private: - bool serializeLength = false; - const uint8_t *constBuffer = nullptr; - uint8_t *buffer = nullptr; - count_t bufferLength = 0; -}; - -#endif /* SERIALBUFFERADAPTER_H_ */ +#ifndef SERIALBUFFERADAPTER_H_ +#define SERIALBUFFERADAPTER_H_ + +#include "../serialize/SerializeIF.h" +#include "../serialize/SerializeAdapter.h" + +/** + * 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>. + * Right now, the SerialBufferAdapter must always + * be initialized with the buffer and size ! + * + * \ingroup serialize + */ +template +class SerialBufferAdapter: public SerializeIF { +public: + + /** + * Constructor for constant uint8_t buffer. Length field can be serialized optionally. + * Type of length can be supplied as template type. + * @param buffer + * @param bufferLength + * @param serializeLength + */ + SerialBufferAdapter(const uint8_t* buffer, count_t bufferLength, + bool serializeLength = false); + + /** + * Constructor for non-constant uint8_t buffer. + * Length field can be serialized optionally. + * Type of length can be supplied as template type. + * @param buffer + * @param bufferLength + * @param serializeLength Length field will be serialized with size count_t + */ + SerialBufferAdapter(uint8_t* buffer, count_t bufferLength, + bool serializeLength = false); + + virtual ~SerialBufferAdapter(); + + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const override; + + virtual size_t getSerializedSize() const override; + + /** + * @brief This function deserializes a buffer into the member buffer. + * @details + * If a length field is present, it is ignored, as the size should have + * been set in the constructor. If the size is not known beforehand, + * consider using SerialFixedArrayListAdapter instead. + * @param buffer [out] Resulting buffer + * @param size remaining size to deserialize, should be larger than buffer + * + size field size + * @param bigEndian + * @return + */ + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; + + uint8_t * getBuffer(); + const uint8_t * getConstBuffer(); + void setBuffer(uint8_t* buffer, count_t bufferLength); +private: + bool serializeLength = false; + const uint8_t *constBuffer = nullptr; + uint8_t *buffer = nullptr; + count_t bufferLength = 0; +}; + +#endif /* SERIALBUFFERADAPTER_H_ */ From b07b19327cf1be8059e2c7635a22118ef2e1fd90 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 1 Sep 2020 11:52:18 +0200 Subject: [PATCH 284/653] renormalize CHB --- devicehandlers/ChildHandlerBase.cpp | 90 ++++++++++++++--------------- devicehandlers/ChildHandlerBase.h | 48 +++++++-------- 2 files changed, 69 insertions(+), 69 deletions(-) diff --git a/devicehandlers/ChildHandlerBase.cpp b/devicehandlers/ChildHandlerBase.cpp index f18c3812..e800cd56 100644 --- a/devicehandlers/ChildHandlerBase.cpp +++ b/devicehandlers/ChildHandlerBase.cpp @@ -1,45 +1,45 @@ -#include "../subsystem/SubsystemBase.h" -#include "../devicehandlers/ChildHandlerBase.h" -#include "../subsystem/SubsystemBase.h" - -ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId, - object_id_t deviceCommunication, CookieIF * cookie, - uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, - object_id_t parent, FailureIsolationBase* customFdir, - size_t cmdQueueSize) : - DeviceHandlerBase(setObjectId, deviceCommunication, cookie, - (customFdir == nullptr? &childHandlerFdir : customFdir), - cmdQueueSize), - parentId(parent), childHandlerFdir(setObjectId) { - this->setThermalStateRequestPoolIds(thermalStatePoolId, - thermalRequestPoolId); - -} - -ChildHandlerBase::~ChildHandlerBase() { -} - -ReturnValue_t ChildHandlerBase::initialize() { - ReturnValue_t result = DeviceHandlerBase::initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - - MessageQueueId_t parentQueue = 0; - - if (parentId != objects::NO_OBJECT) { - SubsystemBase *parent = objectManager->get(parentId); - if (parent == NULL) { - return RETURN_FAILED; - } - parentQueue = parent->getCommandQueue(); - - parent->registerChild(getObjectId()); - } - - healthHelper.setParentQueue(parentQueue); - - modeHelper.setParentQueue(parentQueue); - - return RETURN_OK; -} +#include "../subsystem/SubsystemBase.h" +#include "../devicehandlers/ChildHandlerBase.h" +#include "../subsystem/SubsystemBase.h" + +ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId, + object_id_t deviceCommunication, CookieIF * cookie, + uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, + object_id_t parent, FailureIsolationBase* customFdir, + size_t cmdQueueSize) : + DeviceHandlerBase(setObjectId, deviceCommunication, cookie, + (customFdir == nullptr? &childHandlerFdir : customFdir), + cmdQueueSize), + parentId(parent), childHandlerFdir(setObjectId) { + this->setThermalStateRequestPoolIds(thermalStatePoolId, + thermalRequestPoolId); + +} + +ChildHandlerBase::~ChildHandlerBase() { +} + +ReturnValue_t ChildHandlerBase::initialize() { + ReturnValue_t result = DeviceHandlerBase::initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + MessageQueueId_t parentQueue = 0; + + if (parentId != objects::NO_OBJECT) { + SubsystemBase *parent = objectManager->get(parentId); + if (parent == NULL) { + return RETURN_FAILED; + } + parentQueue = parent->getCommandQueue(); + + parent->registerChild(getObjectId()); + } + + healthHelper.setParentQueue(parentQueue); + + modeHelper.setParentQueue(parentQueue); + + return RETURN_OK; +} diff --git a/devicehandlers/ChildHandlerBase.h b/devicehandlers/ChildHandlerBase.h index 3e9652a3..f6bf318a 100644 --- a/devicehandlers/ChildHandlerBase.h +++ b/devicehandlers/ChildHandlerBase.h @@ -1,26 +1,26 @@ #ifndef FSFW_DEVICES_CHILDHANDLERBASE_H_ -#define FSFW_DEVICES_CHILDHANDLERBASE_H_ - -#include "ChildHandlerFDIR.h" -#include "DeviceHandlerBase.h" - -class ChildHandlerBase: public DeviceHandlerBase { -public: - ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, - CookieIF * cookie, uint32_t thermalStatePoolId, - uint32_t thermalRequestPoolId, - object_id_t parent = objects::NO_OBJECT, - FailureIsolationBase* customFdir = nullptr, - size_t cmdQueueSize = 20); - virtual ~ChildHandlerBase(); - - virtual ReturnValue_t initialize(); - -protected: - const uint32_t parentId; - ChildHandlerFDIR childHandlerFdir; - -}; - -#endif /* FSFW_DEVICES_CHILDHANDLERBASE_H_ */ +#define FSFW_DEVICES_CHILDHANDLERBASE_H_ + +#include "ChildHandlerFDIR.h" +#include "DeviceHandlerBase.h" + +class ChildHandlerBase: public DeviceHandlerBase { +public: + ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, + CookieIF * cookie, uint32_t thermalStatePoolId, + uint32_t thermalRequestPoolId, + object_id_t parent = objects::NO_OBJECT, + FailureIsolationBase* customFdir = nullptr, + size_t cmdQueueSize = 20); + virtual ~ChildHandlerBase(); + + virtual ReturnValue_t initialize(); + +protected: + const uint32_t parentId; + ChildHandlerFDIR childHandlerFdir; + +}; + +#endif /* FSFW_DEVICES_CHILDHANDLERBASE_H_ */ From 695a4e7842f367d35c532f921cea1ad5ffb41dba Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 1 Sep 2020 12:42:52 +0200 Subject: [PATCH 285/653] offset is size_t now --- parameters/ParameterWrapper.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/parameters/ParameterWrapper.cpp b/parameters/ParameterWrapper.cpp index d020da33..6adc6857 100644 --- a/parameters/ParameterWrapper.cpp +++ b/parameters/ParameterWrapper.cpp @@ -270,7 +270,8 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from, //need a type to do arithmetic uint8_t* typedData = static_cast(data); for (uint8_t fromRow = 0; fromRow < from->rows; fromRow++) { - uint8_t offset = (((startingRow + fromRow) * columns) + startingColumn) * typeSize; + size_t offset = (((startingRow + fromRow) * columns) + + startingColumn) * typeSize; std::memcpy(typedData + offset, from->readonlyData, typeSize * from->columns); } From b522b3c29c5d1490c8b8d0fd2dc4209fd92cd9b9 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 1 Sep 2020 12:53:53 +0200 Subject: [PATCH 286/653] fifo updates --- container/DynamicFIFO.h | 4 ++-- container/FIFO.h | 12 +++++++----- container/FIFOBase.h | 2 +- container/FIFOBase.tpp | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/container/DynamicFIFO.h b/container/DynamicFIFO.h index 7fa0c32c..abb53330 100644 --- a/container/DynamicFIFO.h +++ b/container/DynamicFIFO.h @@ -22,7 +22,7 @@ public: // trying to pass the pointer of the uninitialized vector // to the FIFOBase constructor directly lead to a super evil bug. // So we do it like this now. - this->setData(fifoVector.data()); + this->setContainer(fifoVector.data()); }; /** @@ -31,7 +31,7 @@ public: */ DynamicFIFO(const DynamicFIFO& other): FIFOBase(other), fifoVector(other.maxCapacity) { - this->setData(fifoVector.data()); + this->setContainer(fifoVector.data()); } diff --git a/container/FIFO.h b/container/FIFO.h index e60a4979..19f763fc 100644 --- a/container/FIFO.h +++ b/container/FIFO.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_CONTAINER_FIFO_H_ -#define FRAMEWORK_CONTAINER_FIFO_H_ +#ifndef FSFW_CONTAINER_FIFO_H_ +#define FSFW_CONTAINER_FIFO_H_ #include "FIFOBase.h" #include @@ -16,18 +16,20 @@ template class FIFO: public FIFOBase { public: - FIFO(): FIFOBase(fifoArray.data(), capacity) {}; + FIFO(): FIFOBase(nullptr, capacity) { + this->setContainer(fifoArray.data()); + }; /** * @brief Custom copy constructor to set pointer correctly. * @param other */ FIFO(const FIFO& other): FIFOBase(other) { - this->setData(fifoArray.data()); + this->setContainer(fifoArray.data()); } private: std::array fifoArray; }; -#endif /* FRAMEWORK_CONTAINERS_STATICFIFO_H_ */ +#endif /* FSFW_CONTAINER_FIFO_H_ */ diff --git a/container/FIFOBase.h b/container/FIFOBase.h index bbabd67c..b744706d 100644 --- a/container/FIFOBase.h +++ b/container/FIFOBase.h @@ -48,7 +48,7 @@ public: size_t getMaxCapacity() const; protected: - void setData(T* data); + void setContainer(T* data); size_t maxCapacity = 0; T* values; diff --git a/container/FIFOBase.tpp b/container/FIFOBase.tpp index e1287dcf..d54b3f8f 100644 --- a/container/FIFOBase.tpp +++ b/container/FIFOBase.tpp @@ -80,7 +80,7 @@ inline size_t FIFOBase::getMaxCapacity() const { template -inline void FIFOBase::setData(T *data) { +inline void FIFOBase::setContainer(T *data) { this->values = data; } From 03b2ca679d81d15d0c449e9c44b515647c6623c2 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 1 Sep 2020 12:58:29 +0200 Subject: [PATCH 287/653] include guard correction --- tmtcservices/CommandingServiceBase.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index a774e7ae..864a0614 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ -#define FRAMEWORK_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ +#ifndef FSFW_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ +#define FSFW_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ #include "../objectmanager/SystemObject.h" #include "../storagemanager/StorageManagerIF.h" @@ -345,4 +345,4 @@ private: void checkTimeout(); }; -#endif /* FRAMEWORK_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ */ +#endif /* FSFW_TMTCSERVICES_COMMANDINGSERVICEBASE_H_ */ From 5eaf6cfd1f3afa8a02f7ce30c0e84f6a648f7193 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 13:52:02 +0200 Subject: [PATCH 288/653] renormalizing pull request step1 --- osal/FreeRTOS/FixedTimeslotTask.cpp | 337 ++++++++++++++-------------- osal/FreeRTOS/FixedTimeslotTask.h | 202 ++++++++--------- 2 files changed, 272 insertions(+), 267 deletions(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index 772c4bca..309574eb 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -1,166 +1,171 @@ -#include "FixedTimeslotTask.h" - -#include "../../serviceinterface/ServiceInterfaceStream.h" - -uint32_t FixedTimeslotTask::deadlineMissedCount = 0; -const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE; - -FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod overallPeriod, - void (*setDeadlineMissedFunc)()) : - started(false), handle(nullptr), pst(overallPeriod * 1000) { - configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); - xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle); - // All additional attributes are applied to the object. - this->deadlineMissedFunc = setDeadlineMissedFunc; -} - -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)); - /* Task should not start until explicitly requested, - * but in FreeRTOS, tasks start as soon as they are created if the scheduler - * is running but not if the scheduler is not running. - * To be able to accommodate both cases we check a member which is set in - * #startTask(). If it is not set and we get here, the scheduler was started - * before #startTask() was called and we need to suspend if it is set, - * the scheduler was not running before #startTask() was called and we - * can continue */ - - if (not originalTask->started) { - vTaskSuspend(NULL); - } - - originalTask->taskFunctionality(); - sif::debug << "Polling task " << originalTask->handle - << " returned from taskFunctionality." << std::endl; -} - -void FixedTimeslotTask::missedDeadlineCounter() { - FixedTimeslotTask::deadlineMissedCount++; - if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) { - sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount - << " deadlines." << std::endl; - } -} - -ReturnValue_t FixedTimeslotTask::startTask() { - started = true; - - // We must not call resume if scheduler is not started yet - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { - vTaskResume(handle); - } - - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, - uint32_t slotTimeMs, int8_t executionStep) { - ExecutableObjectIF* handler = - objectManager->get(componentId); - if (handler != nullptr) { - pst.addSlot(componentId, slotTimeMs, executionStep, handler, this); - return HasReturnvaluesIF::RETURN_OK; - } - - sif::error << "Component " << std::hex << componentId << - " not found, not adding it to pst" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; -} - -uint32_t FixedTimeslotTask::getPeriodMs() const { - return pst.getLengthMs(); -} - -ReturnValue_t FixedTimeslotTask::checkSequence() const { - return pst.checkSequence(); -} - -void FixedTimeslotTask::taskFunctionality() { - // A local iterator for the Polling Sequence Table is created to find the - // start time for the first entry. - auto slotListIter = pst.current; - - pst.intializeSequenceAfterTaskCreation(); - - //The start time for the first entry is read. - uint32_t intervalMs = slotListIter->pollingTimeMs; - TickType_t interval = pdMS_TO_TICKS(intervalMs); - - TickType_t xLastWakeTime; - /* The xLastWakeTime variable needs to be initialized with the current tick - count. Note that this is the only time the variable is written to - explicitly. After this assignment, xLastWakeTime is updated automatically - internally within vTaskDelayUntil(). */ - xLastWakeTime = xTaskGetTickCount(); - - // wait for first entry's start time - if(interval > 0) { - vTaskDelayUntil(&xLastWakeTime, interval); - } - - /* Enter the loop that defines the task behavior. */ - for (;;) { - //The component for this slot is executed and the next one is chosen. - this->pst.executeAndAdvance(); - if (not pst.slotFollowsImmediately()) { - // Get the interval till execution of the next slot. - intervalMs = this->pst.getIntervalToPreviousSlotMs(); - interval = pdMS_TO_TICKS(intervalMs); - - checkMissedDeadline(xLastWakeTime, interval); - - // Wait for the interval. This exits immediately if a deadline was - // missed while also updating the last wake time. - vTaskDelayUntil(&xLastWakeTime, interval); - } - } -} - -void FixedTimeslotTask::checkMissedDeadline(const TickType_t xLastWakeTime, - const TickType_t interval) { - /* Check whether deadline was missed while also taking overflows - * into account. Drawing this on paper with a timeline helps to understand - * it. */ - TickType_t currentTickCount = xTaskGetTickCount(); - TickType_t timeToWake = xLastWakeTime + interval; - // Time to wake has not overflown. - if(timeToWake > xLastWakeTime) { - /* If the current time has overflown exclusively or the current - * tick count is simply larger than the time to wake, a deadline was - * missed */ - if((currentTickCount < xLastWakeTime) or (currentTickCount > timeToWake)) { - handleMissedDeadline(); - } - } - /* Time to wake has overflown. A deadline was missed if the current time - * is larger than the time to wake */ - else if((timeToWake < xLastWakeTime) and (currentTickCount > timeToWake)) { - handleMissedDeadline(); - } -} - -void FixedTimeslotTask::handleMissedDeadline() { -#ifdef DEBUG - sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) << - " missed deadline!\n" << std::flush; -#endif - if(deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); - } -} - -ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { - vTaskDelay(pdMS_TO_TICKS(ms)); - return HasReturnvaluesIF::RETURN_OK; -} - -TaskHandle_t FixedTimeslotTask::getTaskHandle() { - return handle; -} +#include "FixedTimeslotTask.h" + +#include "../../serviceinterface/ServiceInterfaceStream.h" + +uint32_t FixedTimeslotTask::deadlineMissedCount = 0; +const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE; + +FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod overallPeriod, + void (*setDeadlineMissedFunc)()) : + started(false), handle(nullptr), pst(overallPeriod * 1000) { + configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); + xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle); + // All additional attributes are applied to the object. + this->deadlineMissedFunc = setDeadlineMissedFunc; +} + +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)); + /* Task should not start until explicitly requested, + * but in FreeRTOS, tasks start as soon as they are created if the scheduler + * is running but not if the scheduler is not running. + * To be able to accommodate both cases we check a member which is set in + * #startTask(). If it is not set and we get here, the scheduler was started + * before #startTask() was called and we need to suspend if it is set, + * the scheduler was not running before #startTask() was called and we + * can continue */ + + if (not originalTask->started) { + vTaskSuspend(NULL); + } + + originalTask->taskFunctionality(); + sif::debug << "Polling task " << originalTask->handle + << " returned from taskFunctionality." << std::endl; +} + +void FixedTimeslotTask::missedDeadlineCounter() { + FixedTimeslotTask::deadlineMissedCount++; + if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) { + sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount + << " deadlines." << std::endl; + } +} + +ReturnValue_t FixedTimeslotTask::startTask() { + started = true; + + // We must not call resume if scheduler is not started yet + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + vTaskResume(handle); + } + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, + uint32_t slotTimeMs, int8_t executionStep) { + ExecutableObjectIF* handler = + objectManager->get(componentId); + if (handler != nullptr) { + pst.addSlot(componentId, slotTimeMs, executionStep, handler, this); + return HasReturnvaluesIF::RETURN_OK; + } + + sif::error << "Component " << std::hex << componentId << + " not found, not adding it to pst" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; +} + +uint32_t FixedTimeslotTask::getPeriodMs() const { + return pst.getLengthMs(); +} + +ReturnValue_t FixedTimeslotTask::checkSequence() const { + return pst.checkSequence(); +} + +void FixedTimeslotTask::taskFunctionality() { + // A local iterator for the Polling Sequence Table is created to find the + // start time for the first entry. + auto slotListIter = pst.current; + + pst.intializeSequenceAfterTaskCreation(); + + //The start time for the first entry is read. + uint32_t intervalMs = slotListIter->pollingTimeMs; + TickType_t interval = pdMS_TO_TICKS(intervalMs); + + TickType_t xLastWakeTime; + /* The xLastWakeTime variable needs to be initialized with the current tick + count. Note that this is the only time the variable is written to + explicitly. After this assignment, xLastWakeTime is updated automatically + internally within vTaskDelayUntil(). */ + xLastWakeTime = xTaskGetTickCount(); + + // wait for first entry's start time + if(interval > 0) { + vTaskDelayUntil(&xLastWakeTime, interval); + } + + /* Enter the loop that defines the task behavior. */ + for (;;) { + //The component for this slot is executed and the next one is chosen. + this->pst.executeAndAdvance(); + if (not pst.slotFollowsImmediately()) { + // Get the interval till execution of the next slot. + intervalMs = this->pst.getIntervalToPreviousSlotMs(); + interval = pdMS_TO_TICKS(intervalMs); + + checkMissedDeadline(xLastWakeTime, interval); + + // Wait for the interval. This exits immediately if a deadline was + // missed while also updating the last wake time. + vTaskDelayUntil(&xLastWakeTime, interval); + } + } +} + +void FixedTimeslotTask::checkMissedDeadline(const TickType_t xLastWakeTime, + const TickType_t interval) { + /* Check whether deadline was missed while also taking overflows + * into account. Drawing this on paper with a timeline helps to understand + * it. */ + TickType_t currentTickCount = xTaskGetTickCount(); + TickType_t timeToWake = xLastWakeTime + interval; + // Time to wake has not overflown. + if(timeToWake > xLastWakeTime) { + /* If the current time has overflown exclusively or the current + * tick count is simply larger than the time to wake, a deadline was + * missed */ + if((currentTickCount < xLastWakeTime) or (currentTickCount > timeToWake)) { + handleMissedDeadline(); + } + } + /* Time to wake has overflown. A deadline was missed if the current time + * is larger than the time to wake */ + else if((timeToWake < xLastWakeTime) and (currentTickCount > timeToWake)) { + handleMissedDeadline(); + } +} + +void FixedTimeslotTask::handleMissedDeadline() { + if(deadlineMissedFunc != nullptr) { + this->deadlineMissedFunc(); + } + +#ifdef DEBUG + object_id_t handlerId = pst.current->handlerId; + sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) << " with" + << " object ID 0x" << std::setfill('0') << std::setw(8) << std::hex + << handlerId << " missed deadline!" << std::setfill(' ') + << std::dec << std::endl; +#endif + +} + +ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { + vTaskDelay(pdMS_TO_TICKS(ms)); + return HasReturnvaluesIF::RETURN_OK; +} + +TaskHandle_t FixedTimeslotTask::getTaskHandle() { + return handle; +} diff --git a/osal/FreeRTOS/FixedTimeslotTask.h b/osal/FreeRTOS/FixedTimeslotTask.h index 42af14b8..c46de5b7 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.h +++ b/osal/FreeRTOS/FixedTimeslotTask.h @@ -1,101 +1,101 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ -#define FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ - -#include "../../osal/FreeRTOS/FreeRTOSTaskIF.h" -#include "../../tasks/FixedSlotSequence.h" -#include "../../tasks/FixedTimeslotTaskIF.h" -#include "../../tasks/Typedef.h" - -#include -#include - -class FixedTimeslotTask: public FixedTimeslotTaskIF, public FreeRTOSTaskIF { -public: - - /** - * Keep in mind that you need to call before vTaskStartScheduler()! - * A lot of task parameters are set in "FreeRTOSConfig.h". - * @param name Name of the task, lenght limited by configMAX_TASK_NAME_LEN - * @param setPriority Number of priorities specified by - * configMAX_PRIORITIES. High taskPriority_ number means high priority. - * @param setStack Stack size in words (not bytes!). - * Lower limit specified by configMINIMAL_STACK_SIZE - * @param overallPeriod Period in seconds. - * @param setDeadlineMissedFunc Callback if a deadline was missed. - * @return Pointer to the newly created task. - */ - FixedTimeslotTask(TaskName name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod overallPeriod, - void (*setDeadlineMissedFunc)()); - - /** - * @brief The destructor of the class. - * @details - * The destructor frees all heap memory that was allocated on thread - * initialization for the PST and the device handlers. This is done by - * calling the PST's destructor. - */ - virtual ~FixedTimeslotTask(void); - - ReturnValue_t startTask(void); - /** - * This static function can be used as #deadlineMissedFunc. - * It counts missedDeadlines and prints the number of missed deadlines - * every 10th time. - */ - static void missedDeadlineCounter(); - /** - * A helper variable to count missed deadlines. - */ - static uint32_t deadlineMissedCount; - - ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, - int8_t executionStep) override; - - uint32_t getPeriodMs() const override; - - ReturnValue_t checkSequence() const override; - - ReturnValue_t sleepFor(uint32_t ms) override; - - TaskHandle_t getTaskHandle() override; - -protected: - bool started; - TaskHandle_t handle; - - FixedSlotSequence pst; - - /** - * @brief This attribute holds a function pointer that is executed when - * a deadline was missed. - * @details - * Another function may be announced to determine the actions to perform - * when a deadline was missed. Currently, only one function for missing - * any deadline is allowed. If not used, it shall be declared NULL. - */ - void (*deadlineMissedFunc)(void); - /** - * @brief This is the entry point for a new task. - * @details - * This method starts the task by calling taskFunctionality(), as soon as - * all requirements (task scheduler has started and startTask() - * has been called) are met. - */ - static void taskEntryPoint(void* argument); - - /** - * @brief This function holds the main functionality of the thread. - * @details - * Core function holding the main functionality of the task - * It links the functionalities provided by FixedSlotSequence with the - * OS's System Calls to keep the timing of the periods. - */ - void taskFunctionality(void); - - void checkMissedDeadline(const TickType_t xLastWakeTime, - const TickType_t interval); - void handleMissedDeadline(); -}; - -#endif /* POLLINGTASK_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ +#define FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ + +#include "../../osal/FreeRTOS/FreeRTOSTaskIF.h" +#include "../../tasks/FixedSlotSequence.h" +#include "../../tasks/FixedTimeslotTaskIF.h" +#include "../../tasks/Typedef.h" + +#include +#include + +class FixedTimeslotTask: public FixedTimeslotTaskIF, public FreeRTOSTaskIF { +public: + + /** + * Keep in mind that you need to call before vTaskStartScheduler()! + * A lot of task parameters are set in "FreeRTOSConfig.h". + * @param name Name of the task, lenght limited by configMAX_TASK_NAME_LEN + * @param setPriority Number of priorities specified by + * configMAX_PRIORITIES. High taskPriority_ number means high priority. + * @param setStack Stack size in words (not bytes!). + * Lower limit specified by configMINIMAL_STACK_SIZE + * @param overallPeriod Period in seconds. + * @param setDeadlineMissedFunc Callback if a deadline was missed. + * @return Pointer to the newly created task. + */ + FixedTimeslotTask(TaskName name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod overallPeriod, + void (*setDeadlineMissedFunc)()); + + /** + * @brief The destructor of the class. + * @details + * The destructor frees all heap memory that was allocated on thread + * initialization for the PST and the device handlers. This is done by + * calling the PST's destructor. + */ + virtual ~FixedTimeslotTask(void); + + ReturnValue_t startTask(void); + /** + * This static function can be used as #deadlineMissedFunc. + * It counts missedDeadlines and prints the number of missed deadlines + * every 10th time. + */ + static void missedDeadlineCounter(); + /** + * A helper variable to count missed deadlines. + */ + static uint32_t deadlineMissedCount; + + ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, + int8_t executionStep) override; + + uint32_t getPeriodMs() const override; + + ReturnValue_t checkSequence() const override; + + ReturnValue_t sleepFor(uint32_t ms) override; + + TaskHandle_t getTaskHandle() override; + +protected: + bool started; + TaskHandle_t handle; + + FixedSlotSequence pst; + + /** + * @brief This attribute holds a function pointer that is executed when + * a deadline was missed. + * @details + * Another function may be announced to determine the actions to perform + * when a deadline was missed. Currently, only one function for missing + * any deadline is allowed. If not used, it shall be declared NULL. + */ + void (*deadlineMissedFunc)(void); + /** + * @brief This is the entry point for a new task. + * @details + * This method starts the task by calling taskFunctionality(), as soon as + * all requirements (task scheduler has started and startTask() + * has been called) are met. + */ + static void taskEntryPoint(void* argument); + + /** + * @brief This function holds the main functionality of the thread. + * @details + * Core function holding the main functionality of the task + * It links the functionalities provided by FixedSlotSequence with the + * OS's System Calls to keep the timing of the periods. + */ + void taskFunctionality(void); + + void checkMissedDeadline(const TickType_t xLastWakeTime, + const TickType_t interval); + void handleMissedDeadline(); +}; + +#endif /* POLLINGTASK_H_ */ From 04532b8f6b4bbd661e53ac4b19e37824c73bd2fa Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 13:52:54 +0200 Subject: [PATCH 289/653] renormalizing pull request step2 --- tasks/FixedSequenceSlot.cpp | 34 ++-- tasks/FixedSequenceSlot.h | 116 ++++++------- tasks/FixedSlotSequence.cpp | 294 ++++++++++++++++----------------- tasks/FixedSlotSequence.h | 316 ++++++++++++++++++------------------ 4 files changed, 382 insertions(+), 378 deletions(-) diff --git a/tasks/FixedSequenceSlot.cpp b/tasks/FixedSequenceSlot.cpp index 5fe49523..d7aeff0a 100644 --- a/tasks/FixedSequenceSlot.cpp +++ b/tasks/FixedSequenceSlot.cpp @@ -1,17 +1,17 @@ -#include "FixedSequenceSlot.h" -#include "../objectmanager/SystemObjectIF.h" -#include - -FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime, - int8_t setSequenceId, ExecutableObjectIF* executableObject, - PeriodicTaskIF* executingTask) : - pollingTimeMs(setTime), opcode(setSequenceId) { - if(executableObject == nullptr) { - return; - } - this->executableObject = executableObject; - this->executableObject->setTaskIF(executingTask); -} - -FixedSequenceSlot::~FixedSequenceSlot() {} - +#include "../objectmanager/SystemObjectIF.h" +#include "../tasks/FixedSequenceSlot.h" +#include + +FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime, + int8_t setSequenceId, ExecutableObjectIF* executableObject, + PeriodicTaskIF* executingTask) : handlerId(handlerId), + pollingTimeMs(setTime), opcode(setSequenceId) { + if(executableObject == nullptr) { + return; + } + this->executableObject = executableObject; + this->executableObject->setTaskIF(executingTask); +} + +FixedSequenceSlot::~FixedSequenceSlot() {} + diff --git a/tasks/FixedSequenceSlot.h b/tasks/FixedSequenceSlot.h index 9cf5894c..151173e9 100644 --- a/tasks/FixedSequenceSlot.h +++ b/tasks/FixedSequenceSlot.h @@ -1,57 +1,59 @@ -#ifndef FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_ -#define FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_ - -#include "../objectmanager/ObjectManagerIF.h" -#include "../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. - * @author baetz - */ -class FixedSequenceSlot { -public: - FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs, - int8_t setSequenceId, ExecutableObjectIF* executableObject, - PeriodicTaskIF* executingTask); - virtual ~FixedSequenceSlot(); - - /** - * @brief Handler identifies which object is executed in this slot. - */ - ExecutableObjectIF* executableObject = nullptr; - - /** - * @brief This attribute defines when a device handler object is executed. - * @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. - */ - uint32_t pollingTimeMs; - - /** - * @brief This value defines the type of device communication. - * - * @details The state of this value decides what communication routine is - * called in the PST executable or the device handler object. - */ - uint8_t opcode; - - /** - * @brief Operator overload for the comparison operator to - * allow sorting by polling time. - * @param fixedSequenceSlot - * @return - */ - bool operator <(const FixedSequenceSlot & fixedSequenceSlot) const { - return pollingTimeMs < fixedSequenceSlot.pollingTimeMs; - } -}; - - -#endif /* FIXEDSEQUENCESLOT_H_ */ +#ifndef FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_ +#define FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_ + +#include "../objectmanager/ObjectManagerIF.h" +#include "../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. + * @author baetz + */ +class FixedSequenceSlot { +public: + FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs, + int8_t setSequenceId, ExecutableObjectIF* executableObject, + PeriodicTaskIF* executingTask); + virtual ~FixedSequenceSlot(); + + object_id_t handlerId; + + /** + * @brief Handler identifies which object is executed in this slot. + */ + ExecutableObjectIF* executableObject = nullptr; + + /** + * @brief This attribute defines when a device handler object is executed. + * @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. + */ + uint32_t pollingTimeMs; + + /** + * @brief This value defines the type of device communication. + * + * @details The state of this value decides what communication routine is + * called in the PST executable or the device handler object. + */ + uint8_t opcode; + + /** + * @brief Operator overload for the comparison operator to + * allow sorting by polling time. + * @param fixedSequenceSlot + * @return + */ + bool operator <(const FixedSequenceSlot & fixedSequenceSlot) const { + return pollingTimeMs < fixedSequenceSlot.pollingTimeMs; + } +}; + + +#endif /* FIXEDSEQUENCESLOT_H_ */ diff --git a/tasks/FixedSlotSequence.cpp b/tasks/FixedSlotSequence.cpp index 78f512ca..59859ce5 100644 --- a/tasks/FixedSlotSequence.cpp +++ b/tasks/FixedSlotSequence.cpp @@ -1,147 +1,147 @@ -#include "FixedSlotSequence.h" -#include "../serviceinterface/ServiceInterfaceStream.h" -#include - -FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) : - lengthMs(setLengthMs) { - current = slotList.begin(); -} - -FixedSlotSequence::~FixedSlotSequence() { - // Call the destructor on each list entry. - slotList.clear(); -} - -void FixedSlotSequence::executeAndAdvance() { - current->executableObject->performOperation(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::getIntervalToNextSlotMs() { - uint32_t oldTime; - SlotListIter slotListIter = current; - // Get the pollingTimeMs of the current slot object. - oldTime = slotListIter->pollingTimeMs; - // Advance to the next object. - slotListIter++; - // Find the next interval which is not 0. - while (slotListIter != slotList.end()) { - if (oldTime != slotListIter->pollingTimeMs) { - return slotListIter->pollingTimeMs - oldTime; - } else { - slotListIter++; - } - } - // 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. - slotListIter = slotList.begin(); - return lengthMs - oldTime + slotListIter->pollingTimeMs; -} - -uint32_t FixedSlotSequence::getIntervalToPreviousSlotMs() { - uint32_t currentTime; - SlotListIter slotListIter = current; - // Get the pollingTimeMs of the current slot object. - currentTime = slotListIter->pollingTimeMs; - - //if it is the first slot, calculate difference to last slot - if (slotListIter == slotList.begin()){ - return lengthMs - (--slotList.end())->pollingTimeMs + currentTime; - } - // get previous slot - slotListIter--; - - return currentTime - slotListIter->pollingTimeMs; -} - -bool FixedSlotSequence::slotFollowsImmediately() { - uint32_t currentTime = current->pollingTimeMs; - SlotListIter fixedSequenceIter = this->current; - // Get the pollingTimeMs of the current slot object. - if (fixedSequenceIter == slotList.begin()) - return false; - fixedSequenceIter--; - if (fixedSequenceIter->pollingTimeMs == currentTime) { - return true; - } else { - return false; - } -} - -uint32_t FixedSlotSequence::getLengthMs() const { - return this->lengthMs; -} - -void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs, - int8_t executionStep, ExecutableObjectIF* executableObject, - PeriodicTaskIF* executingTask) { - this->slotList.insert(FixedSequenceSlot(componentId, slotTimeMs, - executionStep, executableObject, executingTask)); - this->current = slotList.begin(); -} - -ReturnValue_t FixedSlotSequence::checkSequence() const { - if(slotList.empty()) { - sif::error << "Fixed Slot Sequence: Slot list is empty!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - - uint32_t count = 0; - uint32_t time = 0; - for(const auto& slot: slotList) { - if (slot.executableObject == nullptr) { - count++; - } - else if (slot.pollingTimeMs < time) { - sif::error << "FixedSlotSequence::initialize: Time: " - << slot.pollingTimeMs << " is smaller than previous with " - << time << std::endl; - count++; - } - else { - // All ok, print slot. - //sif::info << "Current slot polling time: " << std::endl; - //sif::info << std::dec << slotIt->pollingTimeMs << std::endl; - } - time = slot.pollingTimeMs; - - } - //sif::info << "Number of elements in slot list: " - // << slotList.size() << std::endl; - if (count > 0) { - return HasReturnvaluesIF::RETURN_FAILED; - } - return HasReturnvaluesIF::RETURN_OK; -} - - -ReturnValue_t FixedSlotSequence::intializeSequenceAfterTaskCreation() const { - std::set uniqueObjects; - uint32_t count = 0; - for(const auto& slot: slotList) { - // Ensure that each unique object is initialized once. - if(uniqueObjects.find(slot.executableObject) == uniqueObjects.end()) { - ReturnValue_t result = - slot.executableObject->initializeAfterTaskCreation(); - if(result != HasReturnvaluesIF::RETURN_OK) { - count++; - } - uniqueObjects.emplace(slot.executableObject); - } - } - if (count > 0) { - sif::error << "FixedSlotSequence::intializeSequenceAfterTaskCreation:" - "Counted " << count << " failed initializations!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - return HasReturnvaluesIF::RETURN_OK; -} +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../tasks/FixedSlotSequence.h" +#include + +FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) : + lengthMs(setLengthMs) { + current = slotList.begin(); +} + +FixedSlotSequence::~FixedSlotSequence() { + // Call the destructor on each list entry. + slotList.clear(); +} + +void FixedSlotSequence::executeAndAdvance() { + current->executableObject->performOperation(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::getIntervalToNextSlotMs() { + uint32_t oldTime; + SlotListIter slotListIter = current; + // Get the pollingTimeMs of the current slot object. + oldTime = slotListIter->pollingTimeMs; + // Advance to the next object. + slotListIter++; + // Find the next interval which is not 0. + while (slotListIter != slotList.end()) { + if (oldTime != slotListIter->pollingTimeMs) { + return slotListIter->pollingTimeMs - oldTime; + } else { + slotListIter++; + } + } + // 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. + slotListIter = slotList.begin(); + return lengthMs - oldTime + slotListIter->pollingTimeMs; +} + +uint32_t FixedSlotSequence::getIntervalToPreviousSlotMs() { + uint32_t currentTime; + SlotListIter slotListIter = current; + // Get the pollingTimeMs of the current slot object. + currentTime = slotListIter->pollingTimeMs; + + //if it is the first slot, calculate difference to last slot + if (slotListIter == slotList.begin()){ + return lengthMs - (--slotList.end())->pollingTimeMs + currentTime; + } + // get previous slot + slotListIter--; + + return currentTime - slotListIter->pollingTimeMs; +} + +bool FixedSlotSequence::slotFollowsImmediately() { + uint32_t currentTime = current->pollingTimeMs; + SlotListIter fixedSequenceIter = this->current; + // Get the pollingTimeMs of the current slot object. + if (fixedSequenceIter == slotList.begin()) + return false; + fixedSequenceIter--; + if (fixedSequenceIter->pollingTimeMs == currentTime) { + return true; + } else { + return false; + } +} + +uint32_t FixedSlotSequence::getLengthMs() const { + return this->lengthMs; +} + +void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs, + int8_t executionStep, ExecutableObjectIF* executableObject, + PeriodicTaskIF* executingTask) { + this->slotList.insert(FixedSequenceSlot(componentId, slotTimeMs, + executionStep, executableObject, executingTask)); + this->current = slotList.begin(); +} + +ReturnValue_t FixedSlotSequence::checkSequence() const { + if(slotList.empty()) { + sif::error << "Fixed Slot Sequence: Slot list is empty!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + uint32_t count = 0; + uint32_t time = 0; + for(const auto& slot: slotList) { + if (slot.executableObject == nullptr) { + count++; + } + else if (slot.pollingTimeMs < time) { + sif::error << "FixedSlotSequence::initialize: Time: " + << slot.pollingTimeMs << " is smaller than previous with " + << time << std::endl; + count++; + } + else { + // All ok, print slot. + //sif::info << "Current slot polling time: " << std::endl; + //sif::info << std::dec << slotIt->pollingTimeMs << std::endl; + } + time = slot.pollingTimeMs; + + } + //sif::info << "Number of elements in slot list: " + // << slotList.size() << std::endl; + if (count > 0) { + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t FixedSlotSequence::intializeSequenceAfterTaskCreation() const { + std::set uniqueObjects; + uint32_t count = 0; + for(const auto& slot: slotList) { + // Ensure that each unique object is initialized once. + if(uniqueObjects.find(slot.executableObject) == uniqueObjects.end()) { + ReturnValue_t result = + slot.executableObject->initializeAfterTaskCreation(); + if(result != HasReturnvaluesIF::RETURN_OK) { + count++; + } + uniqueObjects.emplace(slot.executableObject); + } + } + if (count > 0) { + sif::error << "FixedSlotSequence::intializeSequenceAfterTaskCreation:" + "Counted " << count << " failed initializations!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/tasks/FixedSlotSequence.h b/tasks/FixedSlotSequence.h index 026d5a3d..1140dd25 100644 --- a/tasks/FixedSlotSequence.h +++ b/tasks/FixedSlotSequence.h @@ -1,157 +1,159 @@ -#ifndef FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_ -#define FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_ - -#include "FixedSequenceSlot.h" -#include "../objectmanager/SystemObject.h" - -#include - -/** - * @brief This class is the representation of a Polling Sequence Table in software. - * @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 thepolling 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 - * which device handler shall be executed within a given polling period. - * 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 FixedSlotSequence { -public: - using SlotList = std::multiset; - using SlotListIter = std::multiset::iterator; - - /** - * @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. - * @param Object ID of the object to add - * @param setTime Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask - * will be called inside the slot period. - * @param setSequenceId ID which can be used to distinguish - * different task operations - * @param - * @param - */ - void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId, - ExecutableObjectIF* executableObject, 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 milliseconds within - * which the handler execution shall take place. - * If the next slot has the same time as the current one, it is ignored - * until a slot with different time or the end of the PST is found. - */ - uint32_t getIntervalToNextSlotMs(); - - /** - * @brief This method returns the time difference between the current - * slot and the previous slot - * - * @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 previous - * one (or the last one, if the slot is the first one) it calculates and - * returns the interval in milliseconds that the handler execution shall - * be delayed. - */ - uint32_t getIntervalToPreviousSlotMs(); - - /** - * @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 - * PollingSlot 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. - */ - SlotListIter current; - - /** - * @brief Check and initialize slot list. - * @details - * Checks if timing is ok (must be ascending) and if all handlers were found. - * Also calls any initialization steps which are required after task - * creation. - * @return - */ - ReturnValue_t checkSequence() const; - - ReturnValue_t intializeSequenceAfterTaskCreation() const; - -protected: - - /** - * @brief This list contains all PollingSlot objects, defining order and - * execution time of the device handler objects. - * - * @details - * The slot list is a std:list object that contains all created - * PollingSlot instances. They are NOT ordered automatically, so by - * adding entries, the correct order needs to be ensured. By iterating - * through this list the polling sequence is executed. Two entries with - * identical polling times are executed immediately one after another. - */ - SlotList slotList; - - uint32_t lengthMs; -}; - -#endif /* FIXEDSLOTSEQUENCE_H_ */ +#ifndef FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_ +#define FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_ + +#include "../objectmanager/SystemObject.h" +#include "../tasks/FixedSequenceSlot.h" + +#include + +/** + * @brief This class is the representation of a Polling Sequence Table in software. + * @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 thepolling 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 + * which device handler shall be executed within a given polling period. + * 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 FixedSlotSequence { +public: + using SlotList = std::multiset; + using SlotListIter = std::multiset::iterator; + + /** + * @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. + * @param Object ID of the object to add + * @param setTime Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask + * will be called inside the slot period. + * @param setSequenceId ID which can be used to distinguish + * different task operations + * @param + * @param + */ + void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId, + ExecutableObjectIF* executableObject, 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 milliseconds within + * which the handler execution shall take place. + * If the next slot has the same time as the current one, it is ignored + * until a slot with different time or the end of the PST is found. + */ + uint32_t getIntervalToNextSlotMs(); + + /** + * @brief This method returns the time difference between the current + * slot and the previous slot + * + * @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 previous + * one (or the last one, if the slot is the first one) it calculates and + * returns the interval in milliseconds that the handler execution shall + * be delayed. + */ + uint32_t getIntervalToPreviousSlotMs(); + + /** + * @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 + * PollingSlot 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. + */ + SlotListIter current; + + /** + * @brief Check and initialize slot list. + * @details + * Checks if timing is ok (must be ascending) and if all handlers were found. + * Also calls any initialization steps which are required after task + * creation. + * @return + */ + ReturnValue_t checkSequence() const; + + ReturnValue_t intializeSequenceAfterTaskCreation() const; + +protected: + + /** + * @brief This list contains all PollingSlot objects, defining order and + * execution time of the device handler objects. + * + * @details + * The slot list is a std:list object that contains all created + * PollingSlot instances. They are NOT ordered automatically, so by + * adding entries, the correct order needs to be ensured. By iterating + * through this list the polling sequence is executed. Two entries with + * identical polling times are executed immediately one after another. + */ + SlotList slotList; + + uint32_t lengthMs; + + bool isEmpty = false; +}; + +#endif /* FIXEDSLOTSEQUENCE_H_ */ From 92c736927610847f18e1899f4e9fbf577d302bda Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 13:56:12 +0200 Subject: [PATCH 290/653] include guard fix --- osal/FreeRTOS/FixedTimeslotTask.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.h b/osal/FreeRTOS/FixedTimeslotTask.h index c46de5b7..7d2cdb70 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.h +++ b/osal/FreeRTOS/FixedTimeslotTask.h @@ -1,7 +1,7 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ -#define FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ +#ifndef FSFW_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ +#define FSFW_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ -#include "../../osal/FreeRTOS/FreeRTOSTaskIF.h" +#include "FreeRTOSTaskIF.h" #include "../../tasks/FixedSlotSequence.h" #include "../../tasks/FixedTimeslotTaskIF.h" #include "../../tasks/Typedef.h" @@ -98,4 +98,4 @@ protected: void handleMissedDeadline(); }; -#endif /* POLLINGTASK_H_ */ +#endif /* FSFW_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ */ From b8754fbc1609b05ea962133a7c5fbfbeb9e17535 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 14:11:59 +0200 Subject: [PATCH 291/653] made fixed sequence slot doc generic --- tasks/FixedSequenceSlot.cpp | 4 +- tasks/FixedSequenceSlot.h | 9 +++-- tasks/FixedSlotSequence.cpp | 2 +- tasks/FixedSlotSequence.h | 77 +++++++++++++++++++++---------------- 4 files changed, 51 insertions(+), 41 deletions(-) diff --git a/tasks/FixedSequenceSlot.cpp b/tasks/FixedSequenceSlot.cpp index d7aeff0a..f5d82178 100644 --- a/tasks/FixedSequenceSlot.cpp +++ b/tasks/FixedSequenceSlot.cpp @@ -1,5 +1,5 @@ -#include "../objectmanager/SystemObjectIF.h" -#include "../tasks/FixedSequenceSlot.h" +#include "FixedSequenceSlot.h" +#include "PeriodicTaskIF.h" #include FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime, diff --git a/tasks/FixedSequenceSlot.h b/tasks/FixedSequenceSlot.h index 151173e9..1744ec19 100644 --- a/tasks/FixedSequenceSlot.h +++ b/tasks/FixedSequenceSlot.h @@ -1,8 +1,9 @@ -#ifndef FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_ -#define FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_ +#ifndef FSFW_TASKS_FIXEDSEQUENCESLOT_H_ +#define FSFW_TASKS_FIXEDSEQUENCESLOT_H_ +#include "ExecutableObjectIF.h" #include "../objectmanager/ObjectManagerIF.h" -#include "../tasks/ExecutableObjectIF.h" + class PeriodicTaskIF; /** @@ -56,4 +57,4 @@ public: }; -#endif /* FIXEDSEQUENCESLOT_H_ */ +#endif /* FSFW_TASKS_FIXEDSEQUENCESLOT_H_ */ diff --git a/tasks/FixedSlotSequence.cpp b/tasks/FixedSlotSequence.cpp index 59859ce5..2467671b 100644 --- a/tasks/FixedSlotSequence.cpp +++ b/tasks/FixedSlotSequence.cpp @@ -1,5 +1,5 @@ +#include "FixedSlotSequence.h" #include "../serviceinterface/ServiceInterfaceStream.h" -#include "../tasks/FixedSlotSequence.h" #include FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) : diff --git a/tasks/FixedSlotSequence.h b/tasks/FixedSlotSequence.h index 1140dd25..056e0bb5 100644 --- a/tasks/FixedSlotSequence.h +++ b/tasks/FixedSlotSequence.h @@ -1,26 +1,30 @@ -#ifndef FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_ -#define FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_ +#ifndef FSFW_TASKS_FIXEDSLOTSEQUENCE_H_ +#define FSFW_TASKS_FIXEDSLOTSEQUENCE_H_ +#include "FixedSequenceSlot.h" #include "../objectmanager/SystemObject.h" -#include "../tasks/FixedSequenceSlot.h" #include /** - * @brief This class is the representation of a Polling Sequence Table in software. + * @brief This class is the representation of a + * Polling Sequence Table in software. * @details * The FixedSlotSequence object maintains the dynamic execution of - * device handler objects. + * objects with stricter timing requirements for the FixedTimeslotTask. * - * The main idea is to create a list of device handlers, to announce all - * handlers to thepolling sequence and to maintain a list of - * polling slot objects. This slot list represents the Polling Sequence Table - * in software. + * The main idea is to create a list of executable objects (for example + * 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 - * which device handler shall be executed within a given polling period. - * The sequence is then executed by iterating through this slot list. - * Handlers are invoking by calling a certain function stored in the handler list. + * which executable object shall be executed within a given polling period. + * When adding a slot, a pointer to the executing task, a pointer to the + * executable object and a step number can be passed. The step number will be + * passed to the periodic handler. + * The sequence is executed by iterating through the slot sequence and + * executing the executable object in the correct timeslot. */ class FixedSlotSequence { public: @@ -29,41 +33,44 @@ 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. + * @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. - * @param Object ID of the object to add - * @param setTime Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask - * will be called inside the slot period. - * @param setSequenceId ID which can be used to distinguish - * different task operations + * @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 handlerId ID of the object to add + * @param setTime + * Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask + * will be called inside the slot period. + * @param setSequenceId + * ID which can be used to distinguish different task operations. This + * value will be passed to the executable function. * @param * @param */ void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId, - ExecutableObjectIF* executableObject, PeriodicTaskIF* executingTask); + ExecutableObjectIF* executableObject, + 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. + * @brief Checks if the current slot shall be executed immediately + * after the one before. + * @details + * This allows to distinguish between grouped and separated handlers. * @return - @c true if the slot has the same polling time as the previous * - @c false else */ @@ -128,12 +135,16 @@ public: * @brief Check and initialize slot list. * @details * Checks if timing is ok (must be ascending) and if all handlers were found. - * Also calls any initialization steps which are required after task - * creation. * @return */ ReturnValue_t checkSequence() const; + /** + * @brief Perform any initialization steps required after the executing + * task has been created. This function should be called from the + * executing task! + * @return + */ ReturnValue_t intializeSequenceAfterTaskCreation() const; protected: @@ -152,8 +163,6 @@ protected: SlotList slotList; uint32_t lengthMs; - - bool isEmpty = false; }; -#endif /* FIXEDSLOTSEQUENCE_H_ */ +#endif /* FSFW_TASKS_FIXEDSLOTSEQUENCE_H_ */ From 4d7d48e8ca5206e384cf8bcd4241c0ac39f4104c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 14:24:34 +0200 Subject: [PATCH 292/653] added a generic way to add a custom check --- tasks/FixedSlotSequence.cpp | 27 +++++++++++++++++++++------ tasks/FixedSlotSequence.h | 4 ++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/tasks/FixedSlotSequence.cpp b/tasks/FixedSlotSequence.cpp index 2467671b..e5db4301 100644 --- a/tasks/FixedSlotSequence.cpp +++ b/tasks/FixedSlotSequence.cpp @@ -91,21 +91,31 @@ void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs, ReturnValue_t FixedSlotSequence::checkSequence() const { if(slotList.empty()) { - sif::error << "Fixed Slot Sequence: Slot list is empty!" << std::endl; + sif::error << "FixedSlotSequence::checkSequence:" + << " Slot list is empty!" << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } - uint32_t count = 0; + if(customCheckFunction != nullptr) { + ReturnValue_t result = customCheckFunction(slotList); + if(result != HasReturnvaluesIF::RETURN_OK) { + // Continue for now but print error output. + sif::error << "FixedSlotSequence::checkSequence:" + << " Custom check failed!" << std::endl; + } + } + + uint32_t errorCount = 0; uint32_t time = 0; for(const auto& slot: slotList) { if (slot.executableObject == nullptr) { - count++; + errorCount++; } else if (slot.pollingTimeMs < time) { - sif::error << "FixedSlotSequence::initialize: Time: " + sif::error << "FixedSlotSequence::checkSequence: Time: " << slot.pollingTimeMs << " is smaller than previous with " << time << std::endl; - count++; + errorCount++; } else { // All ok, print slot. @@ -117,7 +127,7 @@ ReturnValue_t FixedSlotSequence::checkSequence() const { } //sif::info << "Number of elements in slot list: " // << slotList.size() << std::endl; - if (count > 0) { + if (errorCount > 0) { return HasReturnvaluesIF::RETURN_FAILED; } return HasReturnvaluesIF::RETURN_OK; @@ -145,3 +155,8 @@ ReturnValue_t FixedSlotSequence::intializeSequenceAfterTaskCreation() const { } return HasReturnvaluesIF::RETURN_OK; } + +void FixedSlotSequence::addCustomCheck(ReturnValue_t + (*customCheckFunction)(const SlotList&)) { + this->customCheckFunction = customCheckFunction; +} diff --git a/tasks/FixedSlotSequence.h b/tasks/FixedSlotSequence.h index 056e0bb5..19a05f21 100644 --- a/tasks/FixedSlotSequence.h +++ b/tasks/FixedSlotSequence.h @@ -139,6 +139,8 @@ public: */ ReturnValue_t checkSequence() const; + void addCustomCheck(ReturnValue_t (*customCheckFunction)(const SlotList &)); + /** * @brief Perform any initialization steps required after the executing * task has been created. This function should be called from the @@ -162,6 +164,8 @@ protected: */ SlotList slotList; + ReturnValue_t (*customCheckFunction)(const SlotList&) = nullptr; + uint32_t lengthMs; }; From 0eb4c3817edb8abe0cfcf979d6fd5db9ff2a5c9d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 14:31:39 +0200 Subject: [PATCH 293/653] added initialize after taks creation for linux --- osal/linux/FixedTimeslotTask.cpp | 14 ++++++++++---- osal/linux/FixedTimeslotTask.h | 10 +++++----- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/osal/linux/FixedTimeslotTask.cpp b/osal/linux/FixedTimeslotTask.cpp index 858a39a7..247a34ed 100644 --- a/osal/linux/FixedTimeslotTask.cpp +++ b/osal/linux/FixedTimeslotTask.cpp @@ -1,5 +1,5 @@ -#include "../../serviceinterface/ServiceInterfaceStream.h" #include "FixedTimeslotTask.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" #include @@ -39,13 +39,16 @@ uint32_t FixedTimeslotTask::getPeriodMs() const { ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep) { - if (objectManager->get(componentId) != nullptr) { - pst.addSlot(componentId, slotTimeMs, executionStep, this); + ExecutableObjectIF* executableObject = + objectManager->get(componentId); + if (executableObject != nullptr) { + pst.addSlot(componentId, slotTimeMs, executionStep, + executableObject,this); return HasReturnvaluesIF::RETURN_OK; } sif::error << "Component " << std::hex << componentId << - " not found, not adding it to pst" << std::endl; + " not found, not adding it to pst" << std::dec << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } @@ -58,6 +61,9 @@ void FixedTimeslotTask::taskFunctionality() { if (!started) { suspend(); } + + pst.intializeSequenceAfterTaskCreation(); + //The start time for the first entry is read. uint64_t lastWakeTime = getCurrentMonotonicTimeMs(); uint64_t interval = pst.getIntervalToNextSlotMs(); diff --git a/osal/linux/FixedTimeslotTask.h b/osal/linux/FixedTimeslotTask.h index 42802b1d..5c5c1814 100644 --- a/osal/linux/FixedTimeslotTask.h +++ b/osal/linux/FixedTimeslotTask.h @@ -1,9 +1,9 @@ -#ifndef FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ -#define FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ +#ifndef FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ +#define FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ -#include "../../tasks/FixedTimeslotTaskIF.h" -#include "../../devicehandlers/FixedSlotSequence.h" #include "PosixThread.h" +#include "../../tasks/FixedTimeslotTaskIF.h" +#include "../../tasks/FixedSlotSequence.h" #include class FixedTimeslotTask: public FixedTimeslotTaskIF, public PosixThread { @@ -74,4 +74,4 @@ private: bool started; }; -#endif /* FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ */ +#endif /* FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ */ From 381914886dd445b9af9669af658ac1b00c035e86 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 14:43:53 +0200 Subject: [PATCH 294/653] initAfterTaskCreation added for linux --- osal/linux/PeriodicPosixTask.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/osal/linux/PeriodicPosixTask.cpp b/osal/linux/PeriodicPosixTask.cpp index df3694ef..69dbb619 100644 --- a/osal/linux/PeriodicPosixTask.cpp +++ b/osal/linux/PeriodicPosixTask.cpp @@ -46,27 +46,33 @@ ReturnValue_t PeriodicPosixTask::startTask(void){ } void PeriodicPosixTask::taskFunctionality(void){ - if(!started){ + if(not started){ suspend(); } + + for (auto const &object: objectList) { + object->initializeAfterTaskCreation(); + } + uint64_t lastWakeTime = getCurrentMonotonicTimeMs(); //The task's "infinite" inner loop is entered. while (1) { - for (ObjectList::iterator it = objectList.begin(); - it != objectList.end(); ++it) { - (*it)->performOperation(); + for (auto const &object: objectList) { + object->performOperation(); } - if(!PosixThread::delayUntil(&lastWakeTime,periodMs)){ + + if(not PosixThread::delayUntil(&lastWakeTime, periodMs)){ char name[20] = {0}; - int status = pthread_getname_np(pthread_self(),name,sizeof(name)); - if(status==0){ + int status = pthread_getname_np(pthread_self(), name, sizeof(name)); + if(status == 0) { sif::error << "PeriodicPosixTask " << name << ": Deadline " "missed." << std::endl; - }else{ + } + else { sif::error << "PeriodicPosixTask X: Deadline missed. " << status << std::endl; } - if (this->deadlineMissedFunc != NULL) { + if (this->deadlineMissedFunc != nullptr) { this->deadlineMissedFunc(); } } From 4bdac1e0179191c67f559233d8fdebcfedada654 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 14:49:59 +0200 Subject: [PATCH 295/653] changed from mueller/master taken over --- osal/linux/PeriodicPosixTask.cpp | 12 +++++++----- osal/linux/PeriodicPosixTask.h | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/osal/linux/PeriodicPosixTask.cpp b/osal/linux/PeriodicPosixTask.cpp index 69dbb619..3c1df6bb 100644 --- a/osal/linux/PeriodicPosixTask.cpp +++ b/osal/linux/PeriodicPosixTask.cpp @@ -5,8 +5,8 @@ PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, uint32_t period_, void(deadlineMissedFunc_)()): - PosixThread(name_,priority_,stackSize_),objectList(),started(false), - periodMs(period_),deadlineMissedFunc(deadlineMissedFunc_) { + PosixThread(name_, priority_, stackSize_), objectList(), started(false), + periodMs(period_), deadlineMissedFunc(deadlineMissedFunc_) { } PeriodicPosixTask::~PeriodicPosixTask() { @@ -25,6 +25,8 @@ ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object) { ExecutableObjectIF* newObject = objectManager->get( object); if (newObject == nullptr) { + sif::error << "PeriodicTask::addComponent: Invalid object. Make sure" + << " it implements ExecutableObjectIF!" << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } objectList.push_back(newObject); @@ -38,15 +40,15 @@ ReturnValue_t PeriodicPosixTask::sleepFor(uint32_t ms) { } -ReturnValue_t PeriodicPosixTask::startTask(void){ +ReturnValue_t PeriodicPosixTask::startTask(void) { started = true; //sif::info << stackSize << std::endl; PosixThread::createTask(&taskEntryPoint,this); return HasReturnvaluesIF::RETURN_OK; } -void PeriodicPosixTask::taskFunctionality(void){ - if(not started){ +void PeriodicPosixTask::taskFunctionality(void) { + if(not started) { suspend(); } diff --git a/osal/linux/PeriodicPosixTask.h b/osal/linux/PeriodicPosixTask.h index f23adf4d..ffee236b 100644 --- a/osal/linux/PeriodicPosixTask.h +++ b/osal/linux/PeriodicPosixTask.h @@ -32,7 +32,7 @@ public: * The address of the task object is passed as an argument * to the system call. */ - ReturnValue_t startTask(void); + ReturnValue_t startTask() override; /** * Adds an object to the list of objects to be executed. * The objects are executed in the order added. From 975fb9832b27372ab2e6c59af2d3642dae5dc7b1 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 14:52:17 +0200 Subject: [PATCH 296/653] added interface ID --- returnvalues/FwClassIds.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/returnvalues/FwClassIds.h b/returnvalues/FwClassIds.h index ddee539e..9ab0bfeb 100644 --- a/returnvalues/FwClassIds.h +++ b/returnvalues/FwClassIds.h @@ -63,7 +63,8 @@ enum { SEMAPHORE_IF, //SPH 57 LOCAL_POOL_OWNER_IF, //LPIF 58 POOL_VARIABLE_IF, //PVA 59 - HOUSEKEEPING_MANAGER, //HKM 60 + DLE_ENCODER, //DLEE 60 + HOUSEKEEPING_MANAGER, //HKM 61 FW_CLASS_ID_COUNT //is actually count + 1 ! }; From 91d5277a94d8bd3e962b23ce22d9ca34d989c811 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 14:54:08 +0200 Subject: [PATCH 297/653] added new returnvalues --- returnvalues/FwClassIds.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/returnvalues/FwClassIds.h b/returnvalues/FwClassIds.h index 9ab0bfeb..781320e3 100644 --- a/returnvalues/FwClassIds.h +++ b/returnvalues/FwClassIds.h @@ -63,8 +63,11 @@ enum { SEMAPHORE_IF, //SPH 57 LOCAL_POOL_OWNER_IF, //LPIF 58 POOL_VARIABLE_IF, //PVA 59 - DLE_ENCODER, //DLEE 60 - HOUSEKEEPING_MANAGER, //HKM 61 + HOUSEKEEPING_MANAGER, //HKM 60 + DLE_ENCODER, //DLEE 61 + PUS_PARSER, //PUSP 62 + SERIAL_ANALYZER, //SERA 63 + PUS_SERVICE_9, // PUS9 64 FW_CLASS_ID_COUNT //is actually count + 1 ! }; From a6b2b4dd934f3268c6867b450d8218ca8dcc6aba Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 14:58:36 +0200 Subject: [PATCH 298/653] renormalization --- ipc/CommandMessage.cpp | 222 ++++++++++++++++++++--------------------- 1 file changed, 111 insertions(+), 111 deletions(-) diff --git a/ipc/CommandMessage.cpp b/ipc/CommandMessage.cpp index 16293608..513debd3 100644 --- a/ipc/CommandMessage.cpp +++ b/ipc/CommandMessage.cpp @@ -1,111 +1,111 @@ -#include "CommandMessage.h" -#include "CommandMessageCleaner.h" -#include - -CommandMessage::CommandMessage() { - MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE); - setCommand(CMD_NONE); -} - -CommandMessage::CommandMessage(Command_t command, uint32_t parameter1, - uint32_t parameter2) { - MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE); - setCommand(command); - setParameter(parameter1); - setParameter2(parameter2); -} - -Command_t CommandMessage::getCommand() const { - Command_t command; - std::memcpy(&command, MessageQueueMessage::getData(), sizeof(Command_t)); - return command; -} - -void CommandMessage::setCommand(Command_t command) { - std::memcpy(MessageQueueMessage::getData(), &command, sizeof(Command_t)); -} - -uint8_t CommandMessage::getMessageType() const { - // first byte of command ID. - return getCommand() >> 8 & 0xff; -} - -uint32_t CommandMessage::getParameter() const { - uint32_t parameter1; - std::memcpy(¶meter1, this->getData(), sizeof(parameter1)); - return parameter1; -} - -void CommandMessage::setParameter(uint32_t parameter1) { - std::memcpy(this->getData(), ¶meter1, sizeof(parameter1)); -} - -uint32_t CommandMessage::getParameter2() const { - uint32_t parameter2; - std::memcpy(¶meter2, this->getData() + sizeof(uint32_t), - sizeof(parameter2)); - return parameter2; -} - -void CommandMessage::setParameter2(uint32_t parameter2) { - std::memcpy(this->getData() + sizeof(uint32_t), ¶meter2, - sizeof(parameter2)); -} - -uint32_t CommandMessage::getParameter3() const { - uint32_t parameter3; - std::memcpy(¶meter3, this->getData() + 2 * sizeof(uint32_t), - sizeof(parameter3)); - return parameter3; -} - -void CommandMessage::setParameter3(uint32_t parameter3) { - std::memcpy(this->getData() + 2 * sizeof(uint32_t), ¶meter3, - sizeof(parameter3)); -} - -size_t CommandMessage::getMinimumMessageSize() const { - return MINIMUM_COMMAND_MESSAGE_SIZE; -} - -void CommandMessage::clearCommandMessage() { - clear(); -} - -void CommandMessage::clear() { - CommandMessageCleaner::clearCommandMessage(this); -} - -bool CommandMessage::isClearedCommandMessage() { - return getCommand() == CMD_NONE; -} - -void CommandMessage::setToUnknownCommand() { - Command_t initialCommand = getCommand(); - this->clear(); - setReplyRejected(UNKNOWN_COMMAND, initialCommand); -} - -void CommandMessage::setReplyRejected(ReturnValue_t reason, - Command_t initialCommand) { - setCommand(REPLY_REJECTED); - setParameter(reason); - setParameter2(initialCommand); -} - -ReturnValue_t CommandMessage::getReplyRejectedReason( - Command_t *initialCommand) const { - ReturnValue_t reason = getParameter(); - if(initialCommand != nullptr) { - *initialCommand = getParameter2(); - } - return reason; -} - -uint8_t* CommandMessage::getData() { - return MessageQueueMessage::getData() + sizeof(Command_t); -} - -const uint8_t* CommandMessage::getData() const { - return MessageQueueMessage::getData() + sizeof(Command_t); -} +#include "CommandMessage.h" +#include "CommandMessageCleaner.h" +#include + +CommandMessage::CommandMessage() { + MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE); + setCommand(CMD_NONE); +} + +CommandMessage::CommandMessage(Command_t command, uint32_t parameter1, + uint32_t parameter2) { + MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE); + setCommand(command); + setParameter(parameter1); + setParameter2(parameter2); +} + +Command_t CommandMessage::getCommand() const { + Command_t command; + std::memcpy(&command, MessageQueueMessage::getData(), sizeof(Command_t)); + return command; +} + +void CommandMessage::setCommand(Command_t command) { + std::memcpy(MessageQueueMessage::getData(), &command, sizeof(Command_t)); +} + +uint8_t CommandMessage::getMessageType() const { + // first byte of command ID. + return getCommand() >> 8 & 0xff; +} + +uint32_t CommandMessage::getParameter() const { + uint32_t parameter1; + std::memcpy(¶meter1, this->getData(), sizeof(parameter1)); + return parameter1; +} + +void CommandMessage::setParameter(uint32_t parameter1) { + std::memcpy(this->getData(), ¶meter1, sizeof(parameter1)); +} + +uint32_t CommandMessage::getParameter2() const { + uint32_t parameter2; + std::memcpy(¶meter2, this->getData() + sizeof(uint32_t), + sizeof(parameter2)); + return parameter2; +} + +void CommandMessage::setParameter2(uint32_t parameter2) { + std::memcpy(this->getData() + sizeof(uint32_t), ¶meter2, + sizeof(parameter2)); +} + +uint32_t CommandMessage::getParameter3() const { + uint32_t parameter3; + std::memcpy(¶meter3, this->getData() + 2 * sizeof(uint32_t), + sizeof(parameter3)); + return parameter3; +} + +void CommandMessage::setParameter3(uint32_t parameter3) { + std::memcpy(this->getData() + 2 * sizeof(uint32_t), ¶meter3, + sizeof(parameter3)); +} + +size_t CommandMessage::getMinimumMessageSize() const { + return MINIMUM_COMMAND_MESSAGE_SIZE; +} + +void CommandMessage::clearCommandMessage() { + clear(); +} + +void CommandMessage::clear() { + CommandMessageCleaner::clearCommandMessage(this); +} + +bool CommandMessage::isClearedCommandMessage() { + return getCommand() == CMD_NONE; +} + +void CommandMessage::setToUnknownCommand() { + Command_t initialCommand = getCommand(); + this->clear(); + setReplyRejected(UNKNOWN_COMMAND, initialCommand); +} + +void CommandMessage::setReplyRejected(ReturnValue_t reason, + Command_t initialCommand) { + setCommand(REPLY_REJECTED); + setParameter(reason); + setParameter2(initialCommand); +} + +ReturnValue_t CommandMessage::getReplyRejectedReason( + Command_t *initialCommand) const { + ReturnValue_t reason = getParameter(); + if(initialCommand != nullptr) { + *initialCommand = getParameter2(); + } + return reason; +} + +uint8_t* CommandMessage::getData() { + return MessageQueueMessage::getData() + sizeof(Command_t); +} + +const uint8_t* CommandMessage::getData() const { + return MessageQueueMessage::getData() + sizeof(Command_t); +} From a53b9dc3dbfd5339c81c611123341cb3fcb63eea Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 14:59:59 +0200 Subject: [PATCH 299/653] renormalization --- ipc/CommandMessage.h | 258 ++++++++++++++--------------- ipc/CommandMessageCleaner.cpp | 90 +++++----- ipc/CommandMessageCleaner.h | 32 ++-- ipc/CommandMessageIF.h | 146 ++++++++--------- ipc/MessageQueueMessage.cpp | 168 +++++++++---------- ipc/MessageQueueMessage.h | 300 +++++++++++++++++----------------- 6 files changed, 497 insertions(+), 497 deletions(-) diff --git a/ipc/CommandMessage.h b/ipc/CommandMessage.h index 3be9a120..ca7b817f 100644 --- a/ipc/CommandMessage.h +++ b/ipc/CommandMessage.h @@ -1,129 +1,129 @@ -#ifndef FSFW_IPC_COMMANDMESSAGE_H_ -#define FSFW_IPC_COMMANDMESSAGE_H_ - -#include "CommandMessageIF.h" -#include "MessageQueueMessage.h" -#include "FwMessageTypes.h" - -/** - * @brief Default command message used to pass command messages between tasks. - * Primary message type for IPC. Contains sender, 2-byte command ID - * field, and 2 4-byte parameters. - * @details - * It operates on an external memory which is contained inside a - * class implementing MessageQueueMessageIF by taking its address. - * This allows for a more flexible designs of message implementations. - * The pointer can be passed to different message implementations without - * the need of unnecessary copying. - * - * The command message is based of the generic MessageQueueMessage which - * currently has an internal message size of 28 bytes. - * @author Bastian Baetz - */ -class CommandMessage: public MessageQueueMessage, public CommandMessageIF { -public: - /** - * Default size can accomodate 2 4-byte parameters. - */ - static constexpr size_t DEFAULT_COMMAND_MESSAGE_SIZE = - CommandMessageIF::MINIMUM_COMMAND_MESSAGE_SIZE + sizeof(uint32_t); - - /** - * @brief Default Constructor, does not initialize anything. - * @details - * This constructor should be used when receiving a Message, as the - * content is filled by the MessageQueue. - */ - CommandMessage(); - /** - * This constructor creates a new message with all message content - * initialized - * - * @param command The DeviceHandlerCommand_t that will be sent - * @param parameter1 The first parameter - * @param parameter2 The second parameter - */ - CommandMessage(Command_t command, uint32_t parameter1, uint32_t parameter2); - - /** - * @brief Default Destructor - */ - virtual ~CommandMessage() {} - - /** - * Read the DeviceHandlerCommand_t that is stored in the message, - * usually used after receiving. - * - * @return the Command stored in the Message - */ - virtual Command_t getCommand() const override; - /** - * Set the command type of the message. Default implementation also - * sets the message type, which will be the first byte of the command ID. - * @param the Command to be sent - */ - virtual void setCommand(Command_t command); - - virtual uint8_t* getData() override; - virtual const uint8_t* getData() const override; - - /** - * Get the first parameter of the message - * @return the first Parameter of the message - */ - uint32_t getParameter() const; - /** - * Set the first parameter of the message - * @param the first parameter of the message - */ - void setParameter(uint32_t parameter1); - uint32_t getParameter2() const; - void setParameter2(uint32_t parameter2); - uint32_t getParameter3() const; - void setParameter3(uint32_t parameter3); - - /** - * check if a message was cleared - * - * @return if the command is CMD_NONE - */ - bool isClearedCommandMessage(); - - /** - * Sets the command to REPLY_REJECTED with parameter UNKNOWN_COMMAND. - * Is needed quite often, so we better code it once only. - */ - void setToUnknownCommand() override; - - /** - * A command message can be rejected and needs to offer a function - * to set a rejected reply - * @param reason - * @param initialCommand - */ - void setReplyRejected(ReturnValue_t reason, - Command_t initialCommand) override; - /** - * Corrensonding getter function. - * @param initialCommand - * @return - */ - ReturnValue_t getReplyRejectedReason( - Command_t* initialCommand = nullptr) const override; - - - virtual void clear() override; - void clearCommandMessage(); - - /** - * Extract message ID, which is the first byte of the command ID for the - * default implementation. - * @return - */ - virtual uint8_t getMessageType() const override; - - /** MessageQueueMessageIF functions used for minimum size check. */ - size_t getMinimumMessageSize() const override; -}; - -#endif /* FSFW_IPC_COMMANDMESSAGE_H_ */ +#ifndef FSFW_IPC_COMMANDMESSAGE_H_ +#define FSFW_IPC_COMMANDMESSAGE_H_ + +#include "CommandMessageIF.h" +#include "MessageQueueMessage.h" +#include "FwMessageTypes.h" + +/** + * @brief Default command message used to pass command messages between tasks. + * Primary message type for IPC. Contains sender, 2-byte command ID + * field, and 2 4-byte parameters. + * @details + * It operates on an external memory which is contained inside a + * class implementing MessageQueueMessageIF by taking its address. + * This allows for a more flexible designs of message implementations. + * The pointer can be passed to different message implementations without + * the need of unnecessary copying. + * + * The command message is based of the generic MessageQueueMessage which + * currently has an internal message size of 28 bytes. + * @author Bastian Baetz + */ +class CommandMessage: public MessageQueueMessage, public CommandMessageIF { +public: + /** + * Default size can accomodate 2 4-byte parameters. + */ + static constexpr size_t DEFAULT_COMMAND_MESSAGE_SIZE = + CommandMessageIF::MINIMUM_COMMAND_MESSAGE_SIZE + sizeof(uint32_t); + + /** + * @brief Default Constructor, does not initialize anything. + * @details + * This constructor should be used when receiving a Message, as the + * content is filled by the MessageQueue. + */ + CommandMessage(); + /** + * This constructor creates a new message with all message content + * initialized + * + * @param command The DeviceHandlerCommand_t that will be sent + * @param parameter1 The first parameter + * @param parameter2 The second parameter + */ + CommandMessage(Command_t command, uint32_t parameter1, uint32_t parameter2); + + /** + * @brief Default Destructor + */ + virtual ~CommandMessage() {} + + /** + * Read the DeviceHandlerCommand_t that is stored in the message, + * usually used after receiving. + * + * @return the Command stored in the Message + */ + virtual Command_t getCommand() const override; + /** + * Set the command type of the message. Default implementation also + * sets the message type, which will be the first byte of the command ID. + * @param the Command to be sent + */ + virtual void setCommand(Command_t command); + + virtual uint8_t* getData() override; + virtual const uint8_t* getData() const override; + + /** + * Get the first parameter of the message + * @return the first Parameter of the message + */ + uint32_t getParameter() const; + /** + * Set the first parameter of the message + * @param the first parameter of the message + */ + void setParameter(uint32_t parameter1); + uint32_t getParameter2() const; + void setParameter2(uint32_t parameter2); + uint32_t getParameter3() const; + void setParameter3(uint32_t parameter3); + + /** + * check if a message was cleared + * + * @return if the command is CMD_NONE + */ + bool isClearedCommandMessage(); + + /** + * Sets the command to REPLY_REJECTED with parameter UNKNOWN_COMMAND. + * Is needed quite often, so we better code it once only. + */ + void setToUnknownCommand() override; + + /** + * A command message can be rejected and needs to offer a function + * to set a rejected reply + * @param reason + * @param initialCommand + */ + void setReplyRejected(ReturnValue_t reason, + Command_t initialCommand) override; + /** + * Corrensonding getter function. + * @param initialCommand + * @return + */ + ReturnValue_t getReplyRejectedReason( + Command_t* initialCommand = nullptr) const override; + + + virtual void clear() override; + void clearCommandMessage(); + + /** + * Extract message ID, which is the first byte of the command ID for the + * default implementation. + * @return + */ + virtual uint8_t getMessageType() const override; + + /** MessageQueueMessageIF functions used for minimum size check. */ + size_t getMinimumMessageSize() const override; +}; + +#endif /* FSFW_IPC_COMMANDMESSAGE_H_ */ diff --git a/ipc/CommandMessageCleaner.cpp b/ipc/CommandMessageCleaner.cpp index a4dec78d..6a99b4d2 100644 --- a/ipc/CommandMessageCleaner.cpp +++ b/ipc/CommandMessageCleaner.cpp @@ -1,45 +1,45 @@ -#include "../ipc/CommandMessageCleaner.h" - -#include "../devicehandlers/DeviceHandlerMessage.h" -#include "../health/HealthMessage.h" -#include "../memory/MemoryMessage.h" -#include "../modes/ModeMessage.h" -#include "../monitoring/MonitoringMessage.h" -#include "../subsystem/modes/ModeSequenceMessage.h" -#include "../tmstorage/TmStoreMessage.h" -#include "../parameters/ParameterMessage.h" - -void CommandMessageCleaner::clearCommandMessage(CommandMessage* message) { - switch(message->getMessageType()){ - case messagetypes::MODE_COMMAND: - ModeMessage::clear(message); - break; - case messagetypes::HEALTH_COMMAND: - HealthMessage::clear(message); - break; - case messagetypes::MODE_SEQUENCE: - ModeSequenceMessage::clear(message); - break; - case messagetypes::ACTION: - ActionMessage::clear(message); - break; - case messagetypes::DEVICE_HANDLER_COMMAND: - DeviceHandlerMessage::clear(message); - break; - case messagetypes::MEMORY: - MemoryMessage::clear(message); - break; - case messagetypes::MONITORING: - MonitoringMessage::clear(message); - break; - case messagetypes::TM_STORE: - TmStoreMessage::clear(message); - break; - case messagetypes::PARAMETER: - ParameterMessage::clear(message); - break; - default: - messagetypes::clearMissionMessage(message); - break; - } -} +#include "../ipc/CommandMessageCleaner.h" + +#include "../devicehandlers/DeviceHandlerMessage.h" +#include "../health/HealthMessage.h" +#include "../memory/MemoryMessage.h" +#include "../modes/ModeMessage.h" +#include "../monitoring/MonitoringMessage.h" +#include "../subsystem/modes/ModeSequenceMessage.h" +#include "../tmstorage/TmStoreMessage.h" +#include "../parameters/ParameterMessage.h" + +void CommandMessageCleaner::clearCommandMessage(CommandMessage* message) { + switch(message->getMessageType()){ + case messagetypes::MODE_COMMAND: + ModeMessage::clear(message); + break; + case messagetypes::HEALTH_COMMAND: + HealthMessage::clear(message); + break; + case messagetypes::MODE_SEQUENCE: + ModeSequenceMessage::clear(message); + break; + case messagetypes::ACTION: + ActionMessage::clear(message); + break; + case messagetypes::DEVICE_HANDLER_COMMAND: + DeviceHandlerMessage::clear(message); + break; + case messagetypes::MEMORY: + MemoryMessage::clear(message); + break; + case messagetypes::MONITORING: + MonitoringMessage::clear(message); + break; + case messagetypes::TM_STORE: + TmStoreMessage::clear(message); + break; + case messagetypes::PARAMETER: + ParameterMessage::clear(message); + break; + default: + messagetypes::clearMissionMessage(message); + break; + } +} diff --git a/ipc/CommandMessageCleaner.h b/ipc/CommandMessageCleaner.h index f17bf282..2bf4a193 100644 --- a/ipc/CommandMessageCleaner.h +++ b/ipc/CommandMessageCleaner.h @@ -1,16 +1,16 @@ -#ifndef FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ -#define FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ -#include "../ipc/CommandMessage.h" - -namespace messagetypes { -// Implemented in config. -void clearMissionMessage(CommandMessage* message); -} - -class CommandMessageCleaner { -public: - static void clearCommandMessage(CommandMessage* message); -}; - - -#endif /* FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ */ +#ifndef FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ +#define FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ +#include "../ipc/CommandMessage.h" + +namespace messagetypes { +// Implemented in config. +void clearMissionMessage(CommandMessage* message); +} + +class CommandMessageCleaner { +public: + static void clearCommandMessage(CommandMessage* message); +}; + + +#endif /* FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ */ diff --git a/ipc/CommandMessageIF.h b/ipc/CommandMessageIF.h index 68a8d956..aafa40ef 100644 --- a/ipc/CommandMessageIF.h +++ b/ipc/CommandMessageIF.h @@ -1,73 +1,73 @@ -#ifndef FSFW_IPC_COMMANDMESSAGEIF_H_ -#define FSFW_IPC_COMMANDMESSAGEIF_H_ - -#include "MessageQueueMessageIF.h" -#include "FwMessageTypes.h" -#include "../returnvalues/HasReturnvaluesIF.h" - -#define MAKE_COMMAND_ID( number ) ((MESSAGE_ID << 8) + (number)) -typedef uint16_t Command_t; - -class CommandMessageIF { -public: - /** - * Header consists of sender ID and command ID. - */ - static constexpr size_t HEADER_SIZE = MessageQueueMessageIF::HEADER_SIZE + - sizeof(Command_t); - /** - * This minimum size is derived from the interface requirement to be able - * to set a rejected reply, which contains a returnvalue and the initial - * command. - */ - static constexpr size_t MINIMUM_COMMAND_MESSAGE_SIZE = - CommandMessageIF::HEADER_SIZE + sizeof(ReturnValue_t) + - sizeof(Command_t); - - static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE; - static const ReturnValue_t UNKNOWN_COMMAND = MAKE_RETURN_CODE(0x01); - - static const uint8_t MESSAGE_ID = messagetypes::COMMAND; - //! Used internally, shall be ignored - static const Command_t CMD_NONE = MAKE_COMMAND_ID( 0 ); - static const Command_t REPLY_COMMAND_OK = MAKE_COMMAND_ID( 1 ); - //! Reply indicating that the current command was rejected, - //! par1 should contain the error code - static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID( 2 ); - - virtual ~CommandMessageIF() {}; - - /** - * A command message shall have a uint16_t command ID field. - * @return - */ - virtual Command_t getCommand() const = 0; - /** - * A command message shall have a uint8_t message type ID field. - * @return - */ - virtual uint8_t getMessageType() const = 0; - - /** - * A command message can be rejected and needs to offer a function - * to set a rejected reply - * @param reason - * @param initialCommand - */ - virtual void setReplyRejected(ReturnValue_t reason, - Command_t initialCommand) = 0; - /** - * Corrensonding getter function. - * @param initialCommand - * @return - */ - virtual ReturnValue_t getReplyRejectedReason( - Command_t* initialCommand = nullptr) const = 0; - - virtual void setToUnknownCommand() = 0; - - virtual void clear() = 0; - -}; - -#endif /* FSFW_IPC_COMMANDMESSAGEIF_H_ */ +#ifndef FSFW_IPC_COMMANDMESSAGEIF_H_ +#define FSFW_IPC_COMMANDMESSAGEIF_H_ + +#include "MessageQueueMessageIF.h" +#include "FwMessageTypes.h" +#include "../returnvalues/HasReturnvaluesIF.h" + +#define MAKE_COMMAND_ID( number ) ((MESSAGE_ID << 8) + (number)) +typedef uint16_t Command_t; + +class CommandMessageIF { +public: + /** + * Header consists of sender ID and command ID. + */ + static constexpr size_t HEADER_SIZE = MessageQueueMessageIF::HEADER_SIZE + + sizeof(Command_t); + /** + * This minimum size is derived from the interface requirement to be able + * to set a rejected reply, which contains a returnvalue and the initial + * command. + */ + static constexpr size_t MINIMUM_COMMAND_MESSAGE_SIZE = + CommandMessageIF::HEADER_SIZE + sizeof(ReturnValue_t) + + sizeof(Command_t); + + static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE; + static const ReturnValue_t UNKNOWN_COMMAND = MAKE_RETURN_CODE(0x01); + + static const uint8_t MESSAGE_ID = messagetypes::COMMAND; + //! Used internally, shall be ignored + static const Command_t CMD_NONE = MAKE_COMMAND_ID( 0 ); + static const Command_t REPLY_COMMAND_OK = MAKE_COMMAND_ID( 1 ); + //! Reply indicating that the current command was rejected, + //! par1 should contain the error code + static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID( 2 ); + + virtual ~CommandMessageIF() {}; + + /** + * A command message shall have a uint16_t command ID field. + * @return + */ + virtual Command_t getCommand() const = 0; + /** + * A command message shall have a uint8_t message type ID field. + * @return + */ + virtual uint8_t getMessageType() const = 0; + + /** + * A command message can be rejected and needs to offer a function + * to set a rejected reply + * @param reason + * @param initialCommand + */ + virtual void setReplyRejected(ReturnValue_t reason, + Command_t initialCommand) = 0; + /** + * Corrensonding getter function. + * @param initialCommand + * @return + */ + virtual ReturnValue_t getReplyRejectedReason( + Command_t* initialCommand = nullptr) const = 0; + + virtual void setToUnknownCommand() = 0; + + virtual void clear() = 0; + +}; + +#endif /* FSFW_IPC_COMMANDMESSAGEIF_H_ */ diff --git a/ipc/MessageQueueMessage.cpp b/ipc/MessageQueueMessage.cpp index 2f79cb3b..dcd4def3 100644 --- a/ipc/MessageQueueMessage.cpp +++ b/ipc/MessageQueueMessage.cpp @@ -1,84 +1,84 @@ -#include "MessageQueueMessage.h" -#include "../serviceinterface/ServiceInterfaceStream.h" -#include "../globalfunctions/arrayprinter.h" -#include - -MessageQueueMessage::MessageQueueMessage() : - messageSize(getMinimumMessageSize()) { - memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); -} - -MessageQueueMessage::MessageQueueMessage(uint8_t* data, size_t size) : - messageSize(this->HEADER_SIZE + size) { - if (size <= this->MAX_DATA_SIZE) { - memcpy(this->getData(), data, size); - this->messageSize = this->HEADER_SIZE + size; - } - else { - sif::warning << "MessageQueueMessage: Passed size larger than maximum" - "allowed size! Setting content to 0" << std::endl; - memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); - this->messageSize = this->HEADER_SIZE; - } -} - -MessageQueueMessage::~MessageQueueMessage() { -} - -const uint8_t* MessageQueueMessage::getBuffer() const { - return this->internalBuffer; -} - -uint8_t* MessageQueueMessage::getBuffer() { - return this->internalBuffer; -} - -const uint8_t* MessageQueueMessage::getData() const { - return this->internalBuffer + this->HEADER_SIZE; -} - -uint8_t* MessageQueueMessage::getData() { - return this->internalBuffer + this->HEADER_SIZE; -} - -MessageQueueId_t MessageQueueMessage::getSender() const { - MessageQueueId_t temp_id; - memcpy(&temp_id, this->internalBuffer, sizeof(MessageQueueId_t)); - return temp_id; -} - -void MessageQueueMessage::setSender(MessageQueueId_t setId) { - memcpy(this->internalBuffer, &setId, sizeof(MessageQueueId_t)); -} - -void MessageQueueMessage::print(bool printWholeMessage) { - sif::debug << "MessageQueueMessage content: " << std::endl; - if(printWholeMessage) { - arrayprinter::print(getData(), getMaximumMessageSize()); - } - else { - arrayprinter::print(getData(), getMessageSize()); - } - -} - -void MessageQueueMessage::clear() { - memset(this->getBuffer(), 0, this->MAX_MESSAGE_SIZE); -} - -size_t MessageQueueMessage::getMessageSize() const { - return this->messageSize; -} - -void MessageQueueMessage::setMessageSize(size_t messageSize) { - this->messageSize = messageSize; -} - -size_t MessageQueueMessage::getMinimumMessageSize() const { - return this->MIN_MESSAGE_SIZE; -} - -size_t MessageQueueMessage::getMaximumMessageSize() const { - return this->MAX_MESSAGE_SIZE; -} - +#include "MessageQueueMessage.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../globalfunctions/arrayprinter.h" +#include + +MessageQueueMessage::MessageQueueMessage() : + messageSize(getMinimumMessageSize()) { + memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); +} + +MessageQueueMessage::MessageQueueMessage(uint8_t* data, size_t size) : + messageSize(this->HEADER_SIZE + size) { + if (size <= this->MAX_DATA_SIZE) { + memcpy(this->getData(), data, size); + this->messageSize = this->HEADER_SIZE + size; + } + else { + sif::warning << "MessageQueueMessage: Passed size larger than maximum" + "allowed size! Setting content to 0" << std::endl; + memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); + this->messageSize = this->HEADER_SIZE; + } +} + +MessageQueueMessage::~MessageQueueMessage() { +} + +const uint8_t* MessageQueueMessage::getBuffer() const { + return this->internalBuffer; +} + +uint8_t* MessageQueueMessage::getBuffer() { + return this->internalBuffer; +} + +const uint8_t* MessageQueueMessage::getData() const { + return this->internalBuffer + this->HEADER_SIZE; +} + +uint8_t* MessageQueueMessage::getData() { + return this->internalBuffer + this->HEADER_SIZE; +} + +MessageQueueId_t MessageQueueMessage::getSender() const { + MessageQueueId_t temp_id; + memcpy(&temp_id, this->internalBuffer, sizeof(MessageQueueId_t)); + return temp_id; +} + +void MessageQueueMessage::setSender(MessageQueueId_t setId) { + memcpy(this->internalBuffer, &setId, sizeof(MessageQueueId_t)); +} + +void MessageQueueMessage::print(bool printWholeMessage) { + sif::debug << "MessageQueueMessage content: " << std::endl; + if(printWholeMessage) { + arrayprinter::print(getData(), getMaximumMessageSize()); + } + else { + arrayprinter::print(getData(), getMessageSize()); + } + +} + +void MessageQueueMessage::clear() { + memset(this->getBuffer(), 0, this->MAX_MESSAGE_SIZE); +} + +size_t MessageQueueMessage::getMessageSize() const { + return this->messageSize; +} + +void MessageQueueMessage::setMessageSize(size_t messageSize) { + this->messageSize = messageSize; +} + +size_t MessageQueueMessage::getMinimumMessageSize() const { + return this->MIN_MESSAGE_SIZE; +} + +size_t MessageQueueMessage::getMaximumMessageSize() const { + return this->MAX_MESSAGE_SIZE; +} + diff --git a/ipc/MessageQueueMessage.h b/ipc/MessageQueueMessage.h index da5c78cb..f68e9b9f 100644 --- a/ipc/MessageQueueMessage.h +++ b/ipc/MessageQueueMessage.h @@ -1,150 +1,150 @@ -#ifndef FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ -#define FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ - -#include "../ipc/MessageQueueMessageIF.h" -#include "../ipc/MessageQueueSenderIF.h" -#include - -/** - * @brief This class is the representation and data organizer - * for interprocess messages. - * @details - * To facilitate and standardize interprocess communication, this class was - * created to handle a lightweight "interprocess message protocol". - * - * It adds a header with the sender's queue id to every sent message and - * defines the maximum total message size. Specialized messages, such as - * device commanding messages, can be created by inheriting from this class - * and filling the buffer provided by getData with additional content. - * - * If larger amounts of data must be sent between processes, the data shall - * be stored in the IPC Store object and only the storage id is passed in a - * queue message.The class is used both to generate and send messages and to - * receive messages from other tasks. - * @ingroup message_queue - */ -class MessageQueueMessage: public MessageQueueMessageIF { -public: - /** - * @brief The class is initialized empty with this constructor. - * @details - * The messageSize attribute is set to the header's size and the whole - * content is set to zero. - */ - MessageQueueMessage(); - /** - * @brief With this constructor the class is initialized with - * the given content. - * @details - * If the passed message size fits into the buffer, the passed data is - * copied to the internal buffer and the messageSize information is set. - * Otherwise, messageSize is set to the header's size and the whole - * content is set to zero. - * @param data The data to be put in the message. - * @param size Size of the data to be copied. Must be smaller than - * MAX_MESSAGE_SIZE and larger than MIN_MESSAGE_SIZE. - */ - MessageQueueMessage(uint8_t* data, size_t size); - - /** - * @brief As no memory is allocated in this class, - * the destructor is empty. - */ - virtual ~MessageQueueMessage(); - - /** - * @brief The size information of each message is stored in - * this attribute. - * @details - * It is public to simplify usage and to allow for passing the size - * address as a pointer. Care must be taken when inheriting from this class, - * as every child class is responsible for managing the size information by - * itself. When using the class to receive a message, the size information - * is updated automatically. - * - * Please note that the minimum size is limited by the size of the header - * while the maximum size is limited by the maximum allowed message size. - */ - size_t messageSize; - /** - * @brief This constant defines the maximum size of the data content, - * excluding the header. - * @details - * It may be changed if necessary, but in general should be kept - * as small as possible. - */ - static const size_t MAX_DATA_SIZE = 24; - - /** - * @brief This constant defines the maximum total size in bytes - * of a sent message. - * @details - * It is the sum of the maximum data and the header size. Be aware that - * this constant is used to define the buffer sizes for every message - * queue in the system. So, a change here may have significant impact on - * the required resources. - */ - static constexpr size_t MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE; - /** - * @brief Defines the minimum size of a message where only the - * header is included - */ - static constexpr size_t MIN_MESSAGE_SIZE = HEADER_SIZE; -private: - /** - * @brief This is the internal buffer that contains the - * actual message data. - */ - uint8_t internalBuffer[MAX_MESSAGE_SIZE]; -public: - /** - * @brief This method is used to get the complete data of the message. - */ - const uint8_t* getBuffer() const override; - /** - * @brief This method is used to get the complete data of the message. - */ - uint8_t* getBuffer() override; - /** - * @brief This method is used to fetch the data content of the message. - * @details - * It shall be used by child classes to add data at the right position. - */ - const uint8_t* getData() const override; - /** - * @brief This method is used to fetch the data content of the message. - * @details - * It shall be used by child classes to add data at the right position. - */ - uint8_t* getData() override; - /** - * @brief This method is used to extract the sender's message - * queue id information from a received message. - */ - MessageQueueId_t getSender() const override; - /** - * @brief With this method, the whole content - * and the message size is set to zero. - */ - void clear() override; - - /** - * @brief This method is used to set the sender's message queue id - * information prior to ing the message. - * @param setId - * The message queue id that identifies the sending message queue. - */ - void setSender(MessageQueueId_t setId) override; - - virtual size_t getMessageSize() const override; - virtual void setMessageSize(size_t messageSize) override; - virtual size_t getMinimumMessageSize() const override; - virtual size_t getMaximumMessageSize() const override; - - /** - * @brief This is a debug method that prints the content. - */ - void print(bool printWholeMessage); -}; - -#endif /* FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ */ +#ifndef FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ +#define FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ + +#include "../ipc/MessageQueueMessageIF.h" +#include "../ipc/MessageQueueSenderIF.h" +#include + +/** + * @brief This class is the representation and data organizer + * for interprocess messages. + * @details + * To facilitate and standardize interprocess communication, this class was + * created to handle a lightweight "interprocess message protocol". + * + * It adds a header with the sender's queue id to every sent message and + * defines the maximum total message size. Specialized messages, such as + * device commanding messages, can be created by inheriting from this class + * and filling the buffer provided by getData with additional content. + * + * If larger amounts of data must be sent between processes, the data shall + * be stored in the IPC Store object and only the storage id is passed in a + * queue message.The class is used both to generate and send messages and to + * receive messages from other tasks. + * @ingroup message_queue + */ +class MessageQueueMessage: public MessageQueueMessageIF { +public: + /** + * @brief The class is initialized empty with this constructor. + * @details + * The messageSize attribute is set to the header's size and the whole + * content is set to zero. + */ + MessageQueueMessage(); + /** + * @brief With this constructor the class is initialized with + * the given content. + * @details + * If the passed message size fits into the buffer, the passed data is + * copied to the internal buffer and the messageSize information is set. + * Otherwise, messageSize is set to the header's size and the whole + * content is set to zero. + * @param data The data to be put in the message. + * @param size Size of the data to be copied. Must be smaller than + * MAX_MESSAGE_SIZE and larger than MIN_MESSAGE_SIZE. + */ + MessageQueueMessage(uint8_t* data, size_t size); + + /** + * @brief As no memory is allocated in this class, + * the destructor is empty. + */ + virtual ~MessageQueueMessage(); + + /** + * @brief The size information of each message is stored in + * this attribute. + * @details + * It is public to simplify usage and to allow for passing the size + * address as a pointer. Care must be taken when inheriting from this class, + * as every child class is responsible for managing the size information by + * itself. When using the class to receive a message, the size information + * is updated automatically. + * + * Please note that the minimum size is limited by the size of the header + * while the maximum size is limited by the maximum allowed message size. + */ + size_t messageSize; + /** + * @brief This constant defines the maximum size of the data content, + * excluding the header. + * @details + * It may be changed if necessary, but in general should be kept + * as small as possible. + */ + static const size_t MAX_DATA_SIZE = 24; + + /** + * @brief This constant defines the maximum total size in bytes + * of a sent message. + * @details + * It is the sum of the maximum data and the header size. Be aware that + * this constant is used to define the buffer sizes for every message + * queue in the system. So, a change here may have significant impact on + * the required resources. + */ + static constexpr size_t MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE; + /** + * @brief Defines the minimum size of a message where only the + * header is included + */ + static constexpr size_t MIN_MESSAGE_SIZE = HEADER_SIZE; +private: + /** + * @brief This is the internal buffer that contains the + * actual message data. + */ + uint8_t internalBuffer[MAX_MESSAGE_SIZE]; +public: + /** + * @brief This method is used to get the complete data of the message. + */ + const uint8_t* getBuffer() const override; + /** + * @brief This method is used to get the complete data of the message. + */ + uint8_t* getBuffer() override; + /** + * @brief This method is used to fetch the data content of the message. + * @details + * It shall be used by child classes to add data at the right position. + */ + const uint8_t* getData() const override; + /** + * @brief This method is used to fetch the data content of the message. + * @details + * It shall be used by child classes to add data at the right position. + */ + uint8_t* getData() override; + /** + * @brief This method is used to extract the sender's message + * queue id information from a received message. + */ + MessageQueueId_t getSender() const override; + /** + * @brief With this method, the whole content + * and the message size is set to zero. + */ + void clear() override; + + /** + * @brief This method is used to set the sender's message queue id + * information prior to ing the message. + * @param setId + * The message queue id that identifies the sending message queue. + */ + void setSender(MessageQueueId_t setId) override; + + virtual size_t getMessageSize() const override; + virtual void setMessageSize(size_t messageSize) override; + virtual size_t getMinimumMessageSize() const override; + virtual size_t getMaximumMessageSize() const override; + + /** + * @brief This is a debug method that prints the content. + */ + void print(bool printWholeMessage); +}; + +#endif /* FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ */ From d885dddee8c8f053207c5c652f5acc81d66efff8 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 15:04:53 +0200 Subject: [PATCH 300/653] renormalize files --- container/SimpleRingBuffer.cpp | 270 ++++++++++++++++----------------- container/SimpleRingBuffer.h | 256 +++++++++++++++---------------- 2 files changed, 263 insertions(+), 263 deletions(-) diff --git a/container/SimpleRingBuffer.cpp b/container/SimpleRingBuffer.cpp index 2a19d619..d6b6f5af 100644 --- a/container/SimpleRingBuffer.cpp +++ b/container/SimpleRingBuffer.cpp @@ -1,135 +1,135 @@ -#include "../container/SimpleRingBuffer.h" -#include - -SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld, - size_t maxExcessBytes) : - RingBufferBase<>(0, size, overwriteOld), - maxExcessBytes(maxExcessBytes) { - if(maxExcessBytes > size) { - this->maxExcessBytes = size; - } - else { - this->maxExcessBytes = maxExcessBytes; - } - buffer = new uint8_t[size + maxExcessBytes]; -} - -SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size, - bool overwriteOld, size_t maxExcessBytes): - RingBufferBase<>(0, size, overwriteOld), buffer(buffer) { - if(maxExcessBytes > size) { - this->maxExcessBytes = size; - } - else { - this->maxExcessBytes = maxExcessBytes; - } -} - - -SimpleRingBuffer::~SimpleRingBuffer() { - delete[] buffer; -} - - -ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer, - size_t amount) { - if ((availableWriteSpace() >= amount) or overwriteOld) { - size_t amountTillWrap = writeTillWrap(); - if (amountTillWrap < amount) { - if((amount - amountTillWrap + excessBytes) > maxExcessBytes) { - return HasReturnvaluesIF::RETURN_FAILED; - } - excessBytes = amount - amountTillWrap; - } - *writePointer = &buffer[write]; - return HasReturnvaluesIF::RETURN_OK; - } - else { - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -void SimpleRingBuffer::confirmBytesWritten(size_t amount) { - if(getExcessBytes() > 0) { - moveExcessBytesToStart(); - } - incrementWrite(amount); - -} - -ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, - size_t amount) { - if ((availableWriteSpace() >= amount) or overwriteOld) { - size_t amountTillWrap = writeTillWrap(); - if (amountTillWrap >= amount) { - // remaining size in buffer is sufficient to fit full 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, size_t amount, - bool incrementReadPtr, bool readRemaining, size_t* trueAmount) { - size_t availableData = getAvailableReadData(READ_PTR); - size_t amountTillWrap = readTillWrap(READ_PTR); - if (availableData < amount) { - if (readRemaining) { - // more data available than amount specified. - amount = availableData; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } - } - if (trueAmount != nullptr) { - *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); - } - - if(incrementReadPtr) { - deleteData(amount, readRemaining); - } - return HasReturnvaluesIF::RETURN_OK; -} - -size_t SimpleRingBuffer::getExcessBytes() const { - return excessBytes; -} - -void SimpleRingBuffer::moveExcessBytesToStart() { - if(excessBytes > 0) { - std::memcpy(buffer, &buffer[size], excessBytes); - excessBytes = 0; - } -} - -ReturnValue_t SimpleRingBuffer::deleteData(size_t amount, - bool deleteRemaining, size_t* trueAmount) { - size_t availableData = getAvailableReadData(READ_PTR); - if (availableData < amount) { - if (deleteRemaining) { - amount = availableData; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } - } - if (trueAmount != nullptr) { - *trueAmount = amount; - } - incrementRead(amount, READ_PTR); - return HasReturnvaluesIF::RETURN_OK; -} - - +#include "../container/SimpleRingBuffer.h" +#include + +SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld, + size_t maxExcessBytes) : + RingBufferBase<>(0, size, overwriteOld), + maxExcessBytes(maxExcessBytes) { + if(maxExcessBytes > size) { + this->maxExcessBytes = size; + } + else { + this->maxExcessBytes = maxExcessBytes; + } + buffer = new uint8_t[size + maxExcessBytes]; +} + +SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size, + bool overwriteOld, size_t maxExcessBytes): + RingBufferBase<>(0, size, overwriteOld), buffer(buffer) { + if(maxExcessBytes > size) { + this->maxExcessBytes = size; + } + else { + this->maxExcessBytes = maxExcessBytes; + } +} + + +SimpleRingBuffer::~SimpleRingBuffer() { + delete[] buffer; +} + + +ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer, + size_t amount) { + if (availableWriteSpace() >= amount or overwriteOld) { + size_t amountTillWrap = writeTillWrap(); + if (amountTillWrap < amount) { + if((amount - amountTillWrap + excessBytes) > maxExcessBytes) { + return HasReturnvaluesIF::RETURN_FAILED; + } + excessBytes = amount - amountTillWrap; + } + *writePointer = &buffer[write]; + return HasReturnvaluesIF::RETURN_OK; + } + else { + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +void SimpleRingBuffer::confirmBytesWritten(size_t amount) { + if(getExcessBytes() > 0) { + moveExcessBytesToStart(); + } + incrementWrite(amount); + +} + +ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, + size_t amount) { + if (availableWriteSpace() >= amount or overwriteOld) { + size_t amountTillWrap = writeTillWrap(); + if (amountTillWrap >= amount) { + // remaining size in buffer is sufficient to fit full 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, size_t amount, + bool incrementReadPtr, bool readRemaining, size_t* trueAmount) { + size_t availableData = getAvailableReadData(READ_PTR); + size_t amountTillWrap = readTillWrap(READ_PTR); + if (availableData < amount) { + if (readRemaining) { + // more data available than amount specified. + amount = availableData; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + if (trueAmount != nullptr) { + *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); + } + + if(incrementReadPtr) { + deleteData(amount, readRemaining); + } + return HasReturnvaluesIF::RETURN_OK; +} + +size_t SimpleRingBuffer::getExcessBytes() const { + return excessBytes; +} + +void SimpleRingBuffer::moveExcessBytesToStart() { + if(excessBytes > 0) { + std::memcpy(buffer, &buffer[size], excessBytes); + excessBytes = 0; + } +} + +ReturnValue_t SimpleRingBuffer::deleteData(size_t amount, + bool deleteRemaining, size_t* trueAmount) { + size_t availableData = getAvailableReadData(READ_PTR); + if (availableData < amount) { + if (deleteRemaining) { + amount = availableData; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + if (trueAmount != nullptr) { + *trueAmount = amount; + } + incrementRead(amount, READ_PTR); + return HasReturnvaluesIF::RETURN_OK; +} + + diff --git a/container/SimpleRingBuffer.h b/container/SimpleRingBuffer.h index b13e9f2a..dcf2684b 100644 --- a/container/SimpleRingBuffer.h +++ b/container/SimpleRingBuffer.h @@ -1,128 +1,128 @@ -#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ -#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ - -#include "../container/RingBufferBase.h" -#include - -/** - * @brief Circular buffer implementation, useful for buffering - * into data streams. - * @details - * Note that the deleteData() has to be called to increment the read pointer. - * This class allocated dynamically, so - * @ingroup containers - */ -class SimpleRingBuffer: public RingBufferBase<> { -public: - /** - * This constructor allocates a new internal buffer with the supplied size. - * - * @param size - * @param overwriteOld If the ring buffer is overflowing at a write - * operation, the oldest data will be overwritten. - * @param maxExcessBytes These additional bytes will be allocated in addtion - * to the specified size to accomodate contiguous write operations - * with getFreeElement. - * - */ - SimpleRingBuffer(const size_t size, bool overwriteOld, - size_t maxExcessBytes = 0); - /** - * This constructor takes an external buffer with the specified size. - * @param buffer - * @param size - * @param overwriteOld - * If the ring buffer is overflowing at a write operartion, the oldest data - * will be overwritten. - * @param maxExcessBytes - * If the buffer can accomodate additional bytes for contigous write - * operations with getFreeElement, this is the maximum allowed additional - * size - */ - SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld, - size_t maxExcessBytes = 0); - - virtual ~SimpleRingBuffer(); - - /** - * Write to circular buffer and increment write pointer by amount. - * @param data - * @param amount - * @return -@c RETURN_OK if write operation was successfull - * -@c RETURN_FAILED if - */ - ReturnValue_t writeData(const uint8_t* data, size_t amount); - - /** - * Returns a pointer to a free element. If the remaining buffer is - * not large enough, the data will be written past the actual size - * and the amount of excess bytes will be cached. This function - * does not increment the write pointer! - * @param writePointer Pointer to a pointer which can be used to write - * contiguous blocks into the ring buffer - * @param amount - * @return - */ - ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount); - - /** - * This increments the write pointer and also copies the excess bytes - * to the beginning. It should be called if the write operation - * conducted after calling getFreeElement() was performed. - * @return - */ - void confirmBytesWritten(size_t amount); - - virtual size_t getExcessBytes() const; - /** - * Helper functions which moves any excess bytes to the start - * of the ring buffer. - * @return - */ - virtual void moveExcessBytesToStart(); - - /** - * Read from circular buffer at read pointer. - * @param data - * @param amount - * @param incrementReadPtr - * If this is set to true, the read pointer will be incremented. - * If readRemaining is set to true, the read pointer will be incremented - * accordingly. - * @param readRemaining - * If this is set to true, the data will be read even if the amount - * specified exceeds the read data available. - * @param trueAmount [out] - * If readRemaining was set to true, the true amount read will be assigned - * to the passed value. - * @return - * - @c RETURN_OK if data was read successfully - * - @c RETURN_FAILED if not enough data was available and readRemaining - * was set to false. - */ - ReturnValue_t readData(uint8_t* data, size_t amount, - bool incrementReadPtr = false, bool readRemaining = false, - size_t* trueAmount = nullptr); - - /** - * Delete data by incrementing read pointer. - * @param amount - * @param deleteRemaining - * If the amount specified is larger than the remaing size to read and this - * is set to true, the remaining amount will be deleted as well - * @param trueAmount [out] - * If deleteRemaining was set to true, the amount deleted will be assigned - * to the passed value. - * @return - */ - ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false, - size_t* trueAmount = nullptr); -private: - static const uint8_t READ_PTR = 0; - uint8_t* buffer = nullptr; - size_t maxExcessBytes; - size_t excessBytes = 0; -}; - -#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */ - +#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ +#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ + +#include "../container/RingBufferBase.h" +#include + +/** + * @brief Circular buffer implementation, useful for buffering + * into data streams. + * @details + * Note that the deleteData() has to be called to increment the read pointer. + * This class allocated dynamically, so + * @ingroup containers + */ +class SimpleRingBuffer: public RingBufferBase<> { +public: + /** + * This constructor allocates a new internal buffer with the supplied size. + * + * @param size + * @param overwriteOld If the ring buffer is overflowing at a write + * operation, the oldest data will be overwritten. + * @param maxExcessBytes These additional bytes will be allocated in addtion + * to the specified size to accomodate contiguous write operations + * with getFreeElement. + * + */ + SimpleRingBuffer(const size_t size, bool overwriteOld, + size_t maxExcessBytes = 0); + /** + * This constructor takes an external buffer with the specified size. + * @param buffer + * @param size + * @param overwriteOld + * If the ring buffer is overflowing at a write operartion, the oldest data + * will be overwritten. + * @param maxExcessBytes + * If the buffer can accomodate additional bytes for contigous write + * operations with getFreeElement, this is the maximum allowed additional + * size + */ + SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld, + size_t maxExcessBytes = 0); + + virtual ~SimpleRingBuffer(); + + /** + * Write to circular buffer and increment write pointer by amount. + * @param data + * @param amount + * @return -@c RETURN_OK if write operation was successfull + * -@c RETURN_FAILED if + */ + ReturnValue_t writeData(const uint8_t* data, size_t amount); + + /** + * Returns a pointer to a free element. If the remaining buffer is + * not large enough, the data will be written past the actual size + * and the amount of excess bytes will be cached. This function + * does not increment the write pointer! + * @param writePointer Pointer to a pointer which can be used to write + * contiguous blocks into the ring buffer + * @param amount + * @return + */ + ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount); + + /** + * This increments the write pointer and also copies the excess bytes + * to the beginning. It should be called if the write operation + * conducted after calling getFreeElement() was performed. + * @return + */ + void confirmBytesWritten(size_t amount); + + virtual size_t getExcessBytes() const; + /** + * Helper functions which moves any excess bytes to the start + * of the ring buffer. + * @return + */ + virtual void moveExcessBytesToStart(); + + /** + * Read from circular buffer at read pointer. + * @param data + * @param amount + * @param incrementReadPtr + * If this is set to true, the read pointer will be incremented. + * If readRemaining is set to true, the read pointer will be incremented + * accordingly. + * @param readRemaining + * If this is set to true, the data will be read even if the amount + * specified exceeds the read data available. + * @param trueAmount [out] + * If readRemaining was set to true, the true amount read will be assigned + * to the passed value. + * @return + * - @c RETURN_OK if data was read successfully + * - @c RETURN_FAILED if not enough data was available and readRemaining + * was set to false. + */ + ReturnValue_t readData(uint8_t* data, size_t amount, + bool incrementReadPtr = false, bool readRemaining = false, + size_t* trueAmount = nullptr); + + /** + * Delete data by incrementing read pointer. + * @param amount + * @param deleteRemaining + * If the amount specified is larger than the remaing size to read and this + * is set to true, the remaining amount will be deleted as well + * @param trueAmount [out] + * If deleteRemaining was set to true, the amount deleted will be assigned + * to the passed value. + * @return + */ + ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false, + size_t* trueAmount = nullptr); +private: + static const uint8_t READ_PTR = 0; + uint8_t* buffer = nullptr; + size_t maxExcessBytes; + size_t excessBytes = 0; +}; + +#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */ + From e105be229a075bb83e867cf00baa9f392d9d5468 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 15:06:48 +0200 Subject: [PATCH 301/653] include guards fand include improvements --- container/SimpleRingBuffer.cpp | 2 +- container/SimpleRingBuffer.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/container/SimpleRingBuffer.cpp b/container/SimpleRingBuffer.cpp index d6b6f5af..01c22463 100644 --- a/container/SimpleRingBuffer.cpp +++ b/container/SimpleRingBuffer.cpp @@ -1,4 +1,4 @@ -#include "../container/SimpleRingBuffer.h" +#include "SimpleRingBuffer.h" #include SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld, diff --git a/container/SimpleRingBuffer.h b/container/SimpleRingBuffer.h index dcf2684b..a790712f 100644 --- a/container/SimpleRingBuffer.h +++ b/container/SimpleRingBuffer.h @@ -1,7 +1,7 @@ -#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ -#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ +#ifndef FSFW_CONTAINER_SIMPLERINGBUFFER_H_ +#define FSFW_CONTAINER_SIMPLERINGBUFFER_H_ -#include "../container/RingBufferBase.h" +#include "RingBufferBase.h" #include /** @@ -124,5 +124,5 @@ private: size_t excessBytes = 0; }; -#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */ +#endif /* FSFW_CONTAINER_SIMPLERINGBUFFER_H_ */ From 3e67701933e6e64ac998691cd4e2e043e7786427 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 15:09:24 +0200 Subject: [PATCH 302/653] taken over ring buffer base changes --- container/RingBufferBase.h | 125 +++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 54 deletions(-) diff --git a/container/RingBufferBase.h b/container/RingBufferBase.h index e3a87d9d..886b9fab 100644 --- a/container/RingBufferBase.h +++ b/container/RingBufferBase.h @@ -1,96 +1,113 @@ -#ifndef FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ -#define FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ +#ifndef FSFW_CONTAINER_RINGBUFFERBASE_H_ +#define FSFW_CONTAINER_RINGBUFFERBASE_H_ #include "../returnvalues/HasReturnvaluesIF.h" +#include template class RingBufferBase { public: - RingBufferBase(uint32_t startAddress, uint32_t size, bool overwriteOld) : - start(startAddress), write(startAddress), size(size), overwriteOld(overwriteOld) { + RingBufferBase(size_t startAddress, const size_t size, bool overwriteOld) : + start(startAddress), write(startAddress), size(size), + overwriteOld(overwriteOld) { for (uint8_t count = 0; count < N_READ_PTRS; count++) { read[count] = startAddress; } } - ReturnValue_t readData(uint32_t amount, uint8_t n = 0) { - if (availableReadData(n) >= amount) { - incrementRead(amount, n); - return HasReturnvaluesIF::RETURN_OK; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } - } - ReturnValue_t writeData(uint32_t amount) { - if (availableWriteSpace() >= amount || overwriteOld) { - incrementWrite(amount); - return HasReturnvaluesIF::RETURN_OK; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } - } - uint32_t availableReadData(uint8_t n = 0) const { - return ((write + size) - read[n]) % size; - } - uint32_t availableWriteSpace(uint8_t n = 0) const { - //One less to avoid ambiguous full/empty problem. - return (((read[n] + size) - write - 1) % size); - } + + virtual ~RingBufferBase() {} + bool isFull(uint8_t n = 0) { return (availableWriteSpace(n) == 0); } bool isEmpty(uint8_t n = 0) { - return (availableReadData(n) == 0); + return (getAvailableReadData(n) == 0); } - virtual ~RingBufferBase() { + size_t getAvailableReadData(uint8_t n = 0) const { + return ((write + size) - read[n]) % size; } - uint32_t getRead(uint8_t n = 0) const { - return read[n]; + size_t availableWriteSpace(uint8_t n = 0) const { + //One less to avoid ambiguous full/empty problem. + return (((read[n] + size) - write - 1) % size); } - void setRead(uint32_t read, uint8_t n = 0) { - if (read >= start && read < (start+size)) { - this->read[n] = read; - } + + bool overwritesOld() const { + return overwriteOld; } - uint32_t getWrite() const { - return write; - } - void setWrite(uint32_t write) { - this->write = write; + + size_t getMaxSize() const { + return size - 1; } + void clear() { write = start; for (uint8_t count = 0; count < N_READ_PTRS; count++) { read[count] = start; } } - uint32_t writeTillWrap() { + + size_t writeTillWrap() { return (start + size) - write; } - uint32_t readTillWrap(uint8_t n = 0) { + + size_t readTillWrap(uint8_t n = 0) { return (start + size) - read[n]; } - uint32_t getStart() const { + + size_t getStart() const { return start; } - bool overwritesOld() const { - return overwriteOld; - } - uint32_t maxSize() const { - return size - 1; - } + protected: - const uint32_t start; - uint32_t write; - uint32_t read[N_READ_PTRS]; - const uint32_t size; + const size_t start; + size_t write; + size_t read[N_READ_PTRS]; + const size_t size; const bool overwriteOld; + void incrementWrite(uint32_t amount) { write = ((write + amount - start) % size) + start; } void incrementRead(uint32_t amount, uint8_t n = 0) { read[n] = ((read[n] + amount - start) % size) + start; } + + ReturnValue_t readData(uint32_t amount, uint8_t n = 0) { + if (getAvailableReadData(n) >= amount) { + incrementRead(amount, n); + return HasReturnvaluesIF::RETURN_OK; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + + ReturnValue_t writeData(uint32_t amount) { + if (availableWriteSpace() >= amount or overwriteOld) { + incrementWrite(amount); + return HasReturnvaluesIF::RETURN_OK; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + + size_t getRead(uint8_t n = 0) const { + return read[n]; + } + + void setRead(uint32_t read, uint8_t n = 0) { + if (read >= start && read < (start+size)) { + this->read[n] = read; + } + } + + uint32_t getWrite() const { + return write; + } + + void setWrite(uint32_t write) { + this->write = write; + } }; -#endif /* FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ */ +#endif /* FSFW_CONTAINER_RINGBUFFERBASE_H_ */ From 06400fa7bbd89792bc1e508aa6ecf424981ab453 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 15:10:44 +0200 Subject: [PATCH 303/653] share dring buffer update --- container/SharedRingBuffer.cpp | 6 +++--- container/SharedRingBuffer.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/container/SharedRingBuffer.cpp b/container/SharedRingBuffer.cpp index 001a21ed..490988e5 100644 --- a/container/SharedRingBuffer.cpp +++ b/container/SharedRingBuffer.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "../container/SharedRingBuffer.h" +#include "../ipc/MutexFactory.h" +#include "../ipc/MutexHelper.h" SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size, bool overwriteOld, size_t maxExcessBytes): diff --git a/container/SharedRingBuffer.h b/container/SharedRingBuffer.h index 0b5be052..394dcaaa 100644 --- a/container/SharedRingBuffer.h +++ b/container/SharedRingBuffer.h @@ -1,10 +1,10 @@ #ifndef FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ #define FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ -#include -#include -#include -#include +#include "../container/SimpleRingBuffer.h" +#include "../ipc/MutexIF.h" +#include "../objectmanager/SystemObject.h" +#include "../timemanager/Clock.h" /** * @brief Ring buffer which can be shared among multiple objects From dbac6e139b6e7991d5f0997d7b2a9f7daebbbe44 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 15:11:53 +0200 Subject: [PATCH 304/653] shared ring buffer update --- container/SharedRingBuffer.cpp | 2 +- container/SharedRingBuffer.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/container/SharedRingBuffer.cpp b/container/SharedRingBuffer.cpp index 490988e5..800e75d3 100644 --- a/container/SharedRingBuffer.cpp +++ b/container/SharedRingBuffer.cpp @@ -1,4 +1,4 @@ -#include "../container/SharedRingBuffer.h" +#include "SharedRingBuffer.h" #include "../ipc/MutexFactory.h" #include "../ipc/MutexHelper.h" diff --git a/container/SharedRingBuffer.h b/container/SharedRingBuffer.h index 394dcaaa..80c068b3 100644 --- a/container/SharedRingBuffer.h +++ b/container/SharedRingBuffer.h @@ -1,7 +1,7 @@ -#ifndef FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ -#define FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ +#ifndef FSFW_CONTAINER_SHAREDRINGBUFFER_H_ +#define FSFW_CONTAINER_SHAREDRINGBUFFER_H_ -#include "../container/SimpleRingBuffer.h" +#include "SimpleRingBuffer.h" #include "../ipc/MutexIF.h" #include "../objectmanager/SystemObject.h" #include "../timemanager/Clock.h" @@ -65,4 +65,4 @@ private: -#endif /* FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ */ +#endif /* FSFW_CONTAINER_SHAREDRINGBUFFER_H_ */ From 62eb327df6f86c8e5232cad04b3193bf22759a4b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 15:19:33 +0200 Subject: [PATCH 305/653] health helper update --- health/HealthHelper.cpp | 47 ++++++++++++++++++++++++----------------- health/HealthHelper.h | 20 ++++++++++-------- 2 files changed, 39 insertions(+), 28 deletions(-) diff --git a/health/HealthHelper.cpp b/health/HealthHelper.cpp index 1cc7d858..cced11d9 100644 --- a/health/HealthHelper.cpp +++ b/health/HealthHelper.cpp @@ -1,9 +1,8 @@ #include "HealthHelper.h" -#include "../ipc/MessageQueueSenderIF.h" #include "../serviceinterface/ServiceInterfaceStream.h" + HealthHelper::HealthHelper(HasHealthIF* owner, object_id_t objectId) : - healthTable(NULL), eventSender(NULL), objectId(objectId), parentQueue( - 0), owner(owner) { + objectId(objectId), owner(owner) { } HealthHelper::~HealthHelper() { @@ -40,9 +39,19 @@ void HealthHelper::setParentQueue(MessageQueueId_t parentQueue) { ReturnValue_t HealthHelper::initialize() { healthTable = objectManager->get(objects::HEALTH_TABLE); eventSender = objectManager->get(objectId); - if ((healthTable == NULL) || eventSender == NULL) { - return HasReturnvaluesIF::RETURN_FAILED; + + if (healthTable == nullptr) { + sif::error << "HealthHelper::initialize: Health table object needs" + "to be created in factory." << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; } + + if(eventSender == nullptr) { + sif::error << "HealthHelper::initialize: Owner has to implement " + "ReportingProxyIF." << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + ReturnValue_t result = healthTable->registerObject(objectId, HasHealthIF::HEALTHY); if (result != HasReturnvaluesIF::RETURN_OK) { @@ -62,22 +71,22 @@ void HealthHelper::setHealth(HasHealthIF::HealthState health) { void HealthHelper::informParent(HasHealthIF::HealthState health, HasHealthIF::HealthState oldHealth) { - if (parentQueue == 0) { + if (parentQueue == MessageQueueMessageIF::NO_QUEUE) { return; } - CommandMessage message; - HealthMessage::setHealthMessage(&message, HealthMessage::HEALTH_INFO, + CommandMessage information; + HealthMessage::setHealthMessage(&information, HealthMessage::HEALTH_INFO, health, oldHealth); - if (MessageQueueSenderIF::sendMessage(parentQueue, &message, - owner->getCommandQueue()) != HasReturnvaluesIF::RETURN_OK) { + if (MessageQueueSenderIF::sendMessage(parentQueue, &information, + owner->getCommandQueue()) != HasReturnvaluesIF::RETURN_OK) { sif::debug << "HealthHelper::informParent: sending health reply failed." << std::endl; } } -void HealthHelper::handleSetHealthCommand(CommandMessage* message) { - ReturnValue_t result = owner->setHealth(HealthMessage::getHealth(message)); - if (message->getSender() == 0) { +void HealthHelper::handleSetHealthCommand(CommandMessage* command) { + ReturnValue_t result = owner->setHealth(HealthMessage::getHealth(command)); + if (command->getSender() == MessageQueueMessageIF::NO_QUEUE) { return; } CommandMessage reply; @@ -85,12 +94,12 @@ void HealthHelper::handleSetHealthCommand(CommandMessage* message) { HealthMessage::setHealthMessage(&reply, HealthMessage::REPLY_HEALTH_SET); } else { - reply.setReplyRejected(result, message->getCommand()); + reply.setReplyRejected(result, command->getCommand()); } - if (MessageQueueSenderIF::sendMessage(message->getSender(), &reply, - owner->getCommandQueue()) != HasReturnvaluesIF::RETURN_OK) { - sif::debug - << "HealthHelper::handleHealthCommand: sending health reply failed." - << std::endl; + if (MessageQueueSenderIF::sendMessage(command->getSender(), &reply, + owner->getCommandQueue()) != HasReturnvaluesIF::RETURN_OK) { + sif::debug << "HealthHelper::handleHealthCommand: sending health " + "reply failed." << std::endl; + } } diff --git a/health/HealthHelper.h b/health/HealthHelper.h index 90155ad4..d1f1945c 100644 --- a/health/HealthHelper.h +++ b/health/HealthHelper.h @@ -1,11 +1,13 @@ -#ifndef HEALTHHELPER_H_ -#define HEALTHHELPER_H_ +#ifndef FSFW_HEALTH_HEALTHHELPER_H_ +#define FSFW_HEALTH_HEALTHHELPER_H_ -#include "../events/EventManagerIF.h" -#include "../events/EventReportingProxyIF.h" #include "HasHealthIF.h" #include "HealthMessage.h" #include "HealthTableIF.h" + +#include "../events/EventManagerIF.h" +#include "../events/EventReportingProxyIF.h" +#include "../ipc/MessageQueueIF.h" #include "../objectmanager/ObjectManagerIF.h" #include "../returnvalues/HasReturnvaluesIF.h" @@ -27,8 +29,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); @@ -39,12 +41,12 @@ public: * * only valid after initialize() has been called */ - HealthTableIF *healthTable; + HealthTableIF *healthTable = nullptr; /** * Proxy to forward events. */ - EventReportingProxyIF* eventSender; + EventReportingProxyIF* eventSender = nullptr; /** * Try to handle the message. @@ -100,7 +102,7 @@ private: /** * The Queue of the parent */ - MessageQueueId_t parentQueue; + MessageQueueId_t parentQueue = MessageQueueIF::NO_QUEUE; /** * The one using the healthHelper. @@ -117,4 +119,4 @@ private: void handleSetHealthCommand(CommandMessage *message); }; -#endif /* HEALTHHELPER_H_ */ +#endif /* FSFW_HEALTH_HEALTHHELPER_H_ */ From e83de8248129398c1c0ed6ed1e7a500ef41ac4cc Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 15:40:42 +0200 Subject: [PATCH 306/653] gathering remaining differences.. --- serialize/EndianConverter.h | 10 ++++------ serialize/SerializeIF.h | 7 +++++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/serialize/EndianConverter.h b/serialize/EndianConverter.h index 7461576d..c888a905 100644 --- a/serialize/EndianConverter.h +++ b/serialize/EndianConverter.h @@ -1,5 +1,5 @@ -#ifndef ENDIANSWAPPER_H_ -#define ENDIANSWAPPER_H_ +#ifndef FSFW_SERIALIZE_ENDIANCONVERTER_H_ +#define FSFW_SERIALIZE_ENDIANCONVERTER_H_ #include "../osal/Endiness.h" #include @@ -35,9 +35,7 @@ */ class EndianConverter { private: - EndianConverter() { - } - ; + EndianConverter() {}; public: /** * Convert a typed variable between big endian and machine endian. @@ -123,4 +121,4 @@ public: } }; -#endif /* ENDIANSWAPPER_H_ */ +#endif /* FSFW_SERIALIZE_ENDIANCONVERTER_H_ */ diff --git a/serialize/SerializeIF.h b/serialize/SerializeIF.h index 7f9ea9df..3c0540f9 100644 --- a/serialize/SerializeIF.h +++ b/serialize/SerializeIF.h @@ -2,7 +2,7 @@ #define FSFW_SERIALIZE_SERIALIZEIF_H_ #include "../returnvalues/HasReturnvaluesIF.h" -#include +#include /** * @defgroup serialize Serialization @@ -10,7 +10,10 @@ */ /** - * Translation of objects into data streams and from data streams. + * @brief Translation of objects into data streams and from data streams. + * @details + * Also provides options to convert from/to data with different endianness. + * variables. * @ingroup serialize */ class SerializeIF { From d4d96a128e07f9158a202f2667bb265b25886cd6 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 15:47:08 +0200 Subject: [PATCH 307/653] adapted doc --- serialize/SerialFixedArrayListAdapter.h | 70 +++++++++++++++++-------- 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/serialize/SerialFixedArrayListAdapter.h b/serialize/SerialFixedArrayListAdapter.h index 38e0d438..70ca987a 100644 --- a/serialize/SerialFixedArrayListAdapter.h +++ b/serialize/SerialFixedArrayListAdapter.h @@ -1,31 +1,57 @@ -#ifndef SERIALFIXEDARRAYLISTADAPTER_H_ -#define SERIALFIXEDARRAYLISTADAPTER_H_ +#ifndef FSFW_SERIALIZE_SERIALFIXEDARRAYLISTADAPTER_H_ +#define FSFW_SERIALIZE_SERIALFIXEDARRAYLISTADAPTER_H_ -#include "../container/FixedArrayList.h" #include "SerialArrayListAdapter.h" +#include "../container/FixedArrayList.h" /** - * \ingroup serialize + * @brief This adapter provides an interface for SerializeIF to serialize and + * deserialize buffers with a header containing the buffer length. + * @details + * Can be used by SerialLinkedListAdapter by declaring + * as a linked element with SerializeElement>. + * The sequence of objects is defined in the constructor by + * using the setStart and setNext functions. + * + * @tparam BUFFER_TYPE: Specifies the data type of the buffer + * @tparam MAX_SIZE: Specifies the maximum allowed number of elements + * (not bytes!) + * @tparam count_t: specifies the type/size of the length field which defaults + * to one byte. + * @ingroup serialize */ -template -class SerialFixedArrayListAdapter : public FixedArrayList, public SerializeIF { +template +class SerialFixedArrayListAdapter : + public FixedArrayList, + public SerializeIF { public: + /** + * Constructor arguments are forwarded to FixedArrayList constructor. + * Refer to the fixed array list constructors for different options. + * @param args + */ template - SerialFixedArrayListAdapter(Args... args) : FixedArrayList(std::forward(args)...) { - } - ReturnValue_t serialize(uint8_t** buffer, size_t* size, - size_t maxSize, Endianness streamEndianness) const { - return SerialArrayListAdapter::serialize(this, buffer, size, maxSize, streamEndianness); - } - size_t getSerializedSize() const { - return SerialArrayListAdapter::getSerializedSize(this); - } - ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) { - return SerialArrayListAdapter::deSerialize(this, buffer, size, streamEndianness); - } + SerialFixedArrayListAdapter(Args... args) : + FixedArrayList( + std::forward(args)...){} + + ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { + return SerialArrayListAdapter::serialize(this, + buffer, size, maxSize, streamEndianness); + } + + size_t getSerializedSize() const { + return SerialArrayListAdapter:: + getSerializedSize(this); + } + + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) { + return SerialArrayListAdapter::deSerialize(this, + buffer, size, streamEndianness); + } + }; - - -#endif /* SERIALFIXEDARRAYLISTADAPTER_H_ */ +#endif /* FSFW_SERIALIZE_SERIALFIXEDARRAYLISTADAPTER_H_ */ From 84308c74d91b2082e458c4d39aa054060e6a2b06 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 15:56:08 +0200 Subject: [PATCH 308/653] taken over some changes --- serialize/SerializeAdapter.h | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/serialize/SerializeAdapter.h b/serialize/SerializeAdapter.h index af5ec116..24f6111e 100644 --- a/serialize/SerializeAdapter.h +++ b/serialize/SerializeAdapter.h @@ -1,16 +1,24 @@ -#ifndef SERIALIZEADAPTER_H_ -#define SERIALIZEADAPTER_H_ +#ifndef FSFW_SERIALIZE_SERIALIZEADAPTER_H_ +#define FSFW_SERIALIZE_SERIALIZEADAPTER_H_ + +#include "EndianConverter.h" +#include "SerializeIF.h" #include "../container/IsDerivedFrom.h" #include "../returnvalues/HasReturnvaluesIF.h" -#include "EndianConverter.h" -#include "SerializeIF.h" -#include +#include -/** - * \ingroup serialize + /** + * @brief These adapters 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 and vice-versa. + * @details + * The correct serialization or deserialization function is chosen at + * compile time with template type deduction. + * + * @ingroup serialize */ - class SerializeAdapter { public: template @@ -36,9 +44,10 @@ private: class InternalSerializeAdapter { public: static ReturnValue_t serialize(const T *object, uint8_t **buffer, - size_t *size, size_t max_size, SerializeIF::Endianness streamEndianness) { + size_t *size, size_t max_size, + SerializeIF::Endianness streamEndianness) { size_t ignoredSize = 0; - if (size == NULL) { + if (size == nullptr) { size = &ignoredSize; } //TODO check integer overflow of *size @@ -56,7 +65,7 @@ private: tmp = *object; break; } - memcpy(*buffer, &tmp, sizeof(T)); + std::memcpy(*buffer, &tmp, sizeof(T)); *size += sizeof(T); (*buffer) += sizeof(T); return HasReturnvaluesIF::RETURN_OK; @@ -70,7 +79,7 @@ private: T tmp; if (*size >= sizeof(T)) { *size -= sizeof(T); - memcpy(&tmp, *buffer, sizeof(T)); + std::memcpy(&tmp, *buffer, sizeof(T)); switch (streamEndianness) { case SerializeIF::Endianness::BIG: *object = EndianConverter::convertBigEndian(tmp); @@ -104,7 +113,7 @@ private: size_t *size, size_t max_size, SerializeIF::Endianness streamEndianness) const { size_t ignoredSize = 0; - if (size == NULL) { + if (size == nullptr) { size = &ignoredSize; } return object->serialize(buffer, size, max_size, streamEndianness); From ed21ec6c78bc722538ae16f5b3fb8a078c97300d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 16:00:45 +0200 Subject: [PATCH 309/653] changes taken over for serial linked list adapter --- serialize/SerialLinkedListAdapter.h | 67 +++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/serialize/SerialLinkedListAdapter.h b/serialize/SerialLinkedListAdapter.h index 5de8c242..430a21ac 100644 --- a/serialize/SerialLinkedListAdapter.h +++ b/serialize/SerialLinkedListAdapter.h @@ -1,32 +1,52 @@ -/** - * @file SerialLinkedListAdapter.h - * @brief This file defines the SerialLinkedListAdapter class. - * @date 22.07.2014 - * @author baetz - */ -#ifndef SERIALLINKEDLISTADAPTER_H_ -#define SERIALLINKEDLISTADAPTER_H_ +#ifndef FSFW_SERIALIZE_SERIALLINKEDLISTADAPTER_H_ +#define FSFW_SERIALIZE_SERIALLINKEDLISTADAPTER_H_ #include "../container/SinglyLinkedList.h" #include "SerializeAdapter.h" #include "SerializeElement.h" #include "SerializeIF.h" -//This is where we need the SerializeAdapter! -/** - * \ingroup serialize + /** + * @brief Implement the conversion of object data to data streams + * or vice-versa, using linked lists. + * @details + * An alternative to the AutoSerializeAdapter functions + * - All object members with a datatype are declared as + * SerializeElement members inside the class + * implementing this adapter. + * - The element type can also be a SerialBufferAdapter to + * de-/serialize buffers. + * - The element type can also be a SerialFixedArrayListAdapter to + * de-/serialize buffers with a size header, which is scanned automatically. + * + * The sequence of objects is defined in the constructor by using + * the setStart and setNext functions. + * + * 1. The serialization process is done by instantiating the class and + * calling serialize after all SerializeElement entries have been set by + * using the constructor or setter functions. An additional size variable + * can be supplied which is calculated/incremented automatically. + * 2. The deserialization process is done by instantiating the class and + * supplying a buffer with the data which is converted into an object. + * The size of data to serialize can be supplied and is + * decremented in the function. Range checking is done internally. + * @author baetz + * @ingroup serialize */ template class SerialLinkedListAdapter: public SinglyLinkedList, public SerializeIF { public: + SerialLinkedListAdapter(typename LinkedElement::Iterator start, bool printCount = false) : SinglyLinkedList(start), printCount(printCount) { } + SerialLinkedListAdapter(LinkedElement* first, bool printCount = false) : SinglyLinkedList(first), printCount(printCount) { } + SerialLinkedListAdapter(bool printCount = false) : SinglyLinkedList(), printCount(printCount) { } @@ -49,13 +69,14 @@ public: uint8_t** buffer, size_t* size, size_t maxSize, Endianness streamEndianness) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - while ((result == HasReturnvaluesIF::RETURN_OK) && (element != NULL)) { + while ((result == HasReturnvaluesIF::RETURN_OK) and (element != nullptr)) { result = element->value->serialize(buffer, size, maxSize, streamEndianness); element = element->getNext(); } return result; } + virtual size_t getSerializedSize() const override { if (printCount) { return SerialLinkedListAdapter::getSerializedSize() @@ -64,32 +85,44 @@ public: return getSerializedSize(SinglyLinkedList::start); } } + static size_t getSerializedSize(const LinkedElement *element) { size_t size = 0; - while (element != NULL) { + while (element != nullptr) { size += element->value->getSerializedSize(); element = element->getNext(); } return size; } + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, Endianness streamEndianness) override { - return deSerialize(SinglyLinkedList::start, buffer, size, streamEndianness); + return deSerialize(SinglyLinkedList::start, buffer, size, + streamEndianness); } static ReturnValue_t deSerialize(LinkedElement* element, const uint8_t** buffer, size_t* size, Endianness streamEndianness) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - while ((result == HasReturnvaluesIF::RETURN_OK) && (element != NULL)) { + while ((result == HasReturnvaluesIF::RETURN_OK) and (element != nullptr)) { result = element->value->deSerialize(buffer, size, streamEndianness); element = element->getNext(); } return result; } - bool printCount; + /** + * Copying is forbidden by deleting the copy constructor and the copy + * assignment operator because of the pointers to the linked list members. + * Unless the child class implements an own copy constructor or + * copy assignment operator, these operation will throw a compiler error. + * @param + */ + SerialLinkedListAdapter(const SerialLinkedListAdapter &) = delete; + SerialLinkedListAdapter& operator=(const SerialLinkedListAdapter&) = delete; + bool printCount; }; -#endif /* SERIALLINKEDLISTADAPTER_H_ */ +#endif /* FSFW_SERIALIZE_SERIALLINKEDLISTADAPTER_H_ */ From 328c1b71957eedb0277a3815da8880c3a60391e3 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 16:03:36 +0200 Subject: [PATCH 310/653] takne over serialize element changes --- serialize/SerializeElement.h | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/serialize/SerializeElement.h b/serialize/SerializeElement.h index ffedeff9..47080292 100644 --- a/serialize/SerializeElement.h +++ b/serialize/SerializeElement.h @@ -1,12 +1,20 @@ -#ifndef SERIALIZEELEMENT_H_ -#define SERIALIZEELEMENT_H_ +#ifndef FSFW_SERIALIZE_SERIALIZEELEMENT_H_ +#define FSFW_SERIALIZE_SERIALIZEELEMENT_H_ -#include "../container/SinglyLinkedList.h" #include "SerializeAdapter.h" +#include "../container/SinglyLinkedList.h" #include /** - * \ingroup serialize + * @brief This class is used to mark datatypes for serialization with the + * SerialLinkedListAdapter + * @details + * Used by declaring any arbitrary datatype with SerializeElement myVariable, + * inside a SerialLinkedListAdapter implementation and setting the sequence + * of objects with setNext() and setStart(). + * Serialization and Deserialization is then performed automatically in + * specified sequence order. + * @ingroup serialize */ template class SerializeElement: public SerializeIF, public LinkedElement { @@ -19,7 +27,7 @@ public: SerializeElement() : LinkedElement(this) { } - T entry; + ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, Endianness streamEndianness) const override { return SerializeAdapter::serialize(&entry, buffer, size, maxSize, @@ -35,6 +43,7 @@ public: return SerializeAdapter::deSerialize(&entry, buffer, size, streamEndianness); } + operator T() { return entry; } @@ -43,9 +52,12 @@ public: entry = newValue; return *this; } + T* operator->() { return &entry; } + + T entry; }; -#endif /* SERIALIZEELEMENT_H_ */ +#endif /* FSFW_SERIALIZE_SERIALIZEELEMENT_H_ */ From 1a62158f330d0d5dc21df9a14c6c3a791a40cd7a Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 16:07:11 +0200 Subject: [PATCH 311/653] took over serial array list adapter changes --- serialize/SerialArrayListAdapter.h | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/serialize/SerialArrayListAdapter.h b/serialize/SerialArrayListAdapter.h index 7576505a..daa3fe7f 100644 --- a/serialize/SerialArrayListAdapter.h +++ b/serialize/SerialArrayListAdapter.h @@ -1,13 +1,14 @@ -#ifndef FRAMEWORK_SERIALIZE_SERIALARRAYLISTADAPTER_H_ -#define FRAMEWORK_SERIALIZE_SERIALARRAYLISTADAPTER_H_ +#ifndef FSFW_SERIALIZE_SERIALARRAYLISTADAPTER_H_ +#define FSFW_SERIALIZE_SERIALARRAYLISTADAPTER_H_ -#include "../container/ArrayList.h" #include "SerializeIF.h" +#include "../container/ArrayList.h" #include /** + * Also serializes length field ! + * @author baetz * @ingroup serialize - * @author baetz */ template class SerialArrayListAdapter : public SerializeIF { @@ -21,14 +22,14 @@ public: } static ReturnValue_t serialize(const ArrayList* list, - uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) { + uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) { ReturnValue_t result = SerializeAdapter::serialize(&list->size, buffer, size, maxSize, streamEndianness); count_t i = 0; while ((result == HasReturnvaluesIF::RETURN_OK) && (i < list->size)) { - result = SerializeAdapter::serialize(&list->entries[i], buffer, - size, maxSize, streamEndianness); + result = SerializeAdapter::serialize(&list->entries[i], buffer, size, + maxSize, streamEndianness); ++i; } return result; @@ -55,17 +56,18 @@ public: } static ReturnValue_t deSerialize(ArrayList* list, - const uint8_t** buffer, size_t* size, + const uint8_t** buffer, size_t* size, Endianness streamEndianness) { count_t tempSize = 0; ReturnValue_t result = SerializeAdapter::deSerialize(&tempSize, buffer, size, streamEndianness); if(result != HasReturnvaluesIF::RETURN_OK) { - return result; + return result; } if (tempSize > list->maxSize()) { return SerializeIF::TOO_MANY_ELEMENTS; } + list->size = tempSize; count_t i = 0; while ((result == HasReturnvaluesIF::RETURN_OK) && (i < list->size)) { @@ -76,10 +78,9 @@ public: } return result; } + private: ArrayList *adaptee; }; - - -#endif /* FRAMEWORK_SERIALIZE_SERIALARRAYLISTADAPTER_H_ */ +#endif /* FSFW_SERIALIZE_SERIALARRAYLISTADAPTER_H_ */ From a1155686c5dbb1b844c13ee078ff13579e4de4fb Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 5 Sep 2020 20:18:52 +0200 Subject: [PATCH 312/653] updated host osal --- osal/host/Clock.cpp | 454 +++++++++++++++---------------- osal/host/FixedTimeslotTask.cpp | 382 +++++++++++++------------- osal/host/FixedTimeslotTask.h | 260 +++++++++--------- osal/host/MessageQueue.cpp | 310 ++++++++++----------- osal/host/MessageQueue.h | 460 ++++++++++++++++---------------- osal/host/Mutex.cpp | 80 +++--- osal/host/Mutex.h | 56 ++-- osal/host/MutexFactory.cpp | 56 ++-- osal/host/PeriodicTask.cpp | 352 ++++++++++++------------ osal/host/PeriodicTask.h | 246 ++++++++--------- osal/host/QueueFactory.cpp | 82 +++--- osal/host/QueueMapManager.cpp | 102 +++---- osal/host/QueueMapManager.h | 94 +++---- osal/host/SemaphoreFactory.cpp | 84 +++--- osal/host/TaskFactory.cpp | 110 ++++---- 15 files changed, 1564 insertions(+), 1564 deletions(-) diff --git a/osal/host/Clock.cpp b/osal/host/Clock.cpp index 52d0d5f0..41321eeb 100644 --- a/osal/host/Clock.cpp +++ b/osal/host/Clock.cpp @@ -1,227 +1,227 @@ -#include "../../serviceinterface/ServiceInterfaceStream.h" -#include "../../timemanager/Clock.h" - -#include -#if defined(WIN32) -#include -#elif defined(LINUX) -#include -#endif - -uint16_t Clock::leapSeconds = 0; -MutexIF* Clock::timeMutex = NULL; - -using SystemClock = std::chrono::system_clock; - -uint32_t Clock::getTicksPerSecond(void){ - sif::warning << "Clock::getTicksPerSecond: not implemented yet" << std::endl; - return 0; - //return CLOCKS_PER_SEC; - //uint32_t ticks = sysconf(_SC_CLK_TCK); - //return ticks; -} - -ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { - // do some magic with chrono - sif::warning << "Clock::setClock: not implemented yet" << std::endl; - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t Clock::setClock(const timeval* time) { - // do some magic with chrono -#if defined(WIN32) - return HasReturnvaluesIF::RETURN_OK; -#elif defined(LINUX) - return HasReturnvaluesIF::RETURN_OK; -#else - -#endif - sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; -} - -ReturnValue_t Clock::getClock_timeval(timeval* time) { -#if defined(WIN32) - auto now = std::chrono::system_clock::now(); - auto secondsChrono = std::chrono::time_point_cast(now); - auto epoch = now.time_since_epoch(); - time->tv_sec = std::chrono::duration_cast(epoch).count(); - auto fraction = now - secondsChrono; - time->tv_usec = std::chrono::duration_cast( - fraction).count(); - return HasReturnvaluesIF::RETURN_OK; -#elif defined(LINUX) - timespec timeUnix; - int status = clock_gettime(CLOCK_REALTIME,&timeUnix); - if(status!=0){ - return HasReturnvaluesIF::RETURN_FAILED; - } - time->tv_sec = timeUnix.tv_sec; - time->tv_usec = timeUnix.tv_nsec / 1000.0; - return HasReturnvaluesIF::RETURN_OK; -#else - sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; -#endif - -} - -ReturnValue_t Clock::getClock_usecs(uint64_t* time) { - // do some magic with chrono - sif::warning << "Clock::gerClock_usecs: not implemented yet" << std::endl; - return HasReturnvaluesIF::RETURN_OK; -} - -timeval Clock::getUptime() { - timeval timeval; -#if defined(WIN32) - auto uptime = std::chrono::milliseconds(GetTickCount64()); - auto secondsChrono = std::chrono::duration_cast(uptime); - timeval.tv_sec = secondsChrono.count(); - auto fraction = uptime - secondsChrono; - timeval.tv_usec = std::chrono::duration_cast( - fraction).count(); -#elif defined(LINUX) - double uptimeSeconds; - if (std::ifstream("/proc/uptime", std::ios::in) >> uptimeSeconds) - { - // value is rounded down automatically - timeval.tv_sec = uptimeSeconds; - timeval.tv_usec = uptimeSeconds *(double) 1e6 - (timeval.tv_sec *1e6); - } -#else - sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; -#endif - return timeval; -} - -ReturnValue_t Clock::getUptime(timeval* uptime) { - *uptime = getUptime(); - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) { - timeval uptime = getUptime(); - *uptimeMs = uptime.tv_sec * 1000 + uptime.tv_usec / 1000; - return HasReturnvaluesIF::RETURN_OK; -} - - -ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { - // do some magic with chrono (C++20!) - // Right now, the library doesn't have the new features yet. - // so we work around that for now. - auto now = SystemClock::now(); - auto seconds = std::chrono::time_point_cast(now); - auto fraction = now - seconds; - time_t tt = SystemClock::to_time_t(now); - struct tm* timeInfo; - timeInfo = gmtime(&tt); - time->year = timeInfo->tm_year + 1900; - time->month = timeInfo->tm_mon+1; - time->day = timeInfo->tm_mday; - time->hour = timeInfo->tm_hour; - time->minute = timeInfo->tm_min; - time->second = timeInfo->tm_sec; - auto usecond = std::chrono::duration_cast(fraction); - time->usecond = usecond.count(); - - //sif::warning << "Clock::getDateAndTime: not implemented yet" << std::endl; - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, - timeval* to) { - struct tm time_tm; - - time_tm.tm_year = from->year - 1900; - time_tm.tm_mon = from->month - 1; - time_tm.tm_mday = from->day; - - time_tm.tm_hour = from->hour; - time_tm.tm_min = from->minute; - time_tm.tm_sec = from->second; - - time_t seconds = mktime(&time_tm); - - to->tv_sec = seconds; - to->tv_usec = from->usecond; - //Fails in 2038.. - return HasReturnvaluesIF::RETURN_OK; - sif::warning << "Clock::convertTimeBla: not implemented yet" << std::endl; - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) { - *JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. - / 3600.; - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) { - //SHOULDDO: works not for dates in the past (might have less leap seconds) - if (timeMutex == NULL) { - return HasReturnvaluesIF::RETURN_FAILED; - } - - uint16_t leapSeconds; - ReturnValue_t result = getLeapSeconds(&leapSeconds); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - timeval leapSeconds_timeval = { 0, 0 }; - leapSeconds_timeval.tv_sec = leapSeconds; - - //initial offset between UTC and TAI - timeval UTCtoTAI1972 = { 10, 0 }; - - timeval TAItoTT = { 32, 184000 }; - - *tt = utc + leapSeconds_timeval + UTCtoTAI1972 + TAItoTT; - - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) { - if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){ - return HasReturnvaluesIF::RETURN_FAILED; - } - ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - - leapSeconds = leapSeconds_; - - result = timeMutex->unlockMutex(); - return result; -} - -ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) { - if(timeMutex == nullptr){ - return HasReturnvaluesIF::RETURN_FAILED; - } - ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - - *leapSeconds_ = leapSeconds; - - result = timeMutex->unlockMutex(); - return result; -} - -ReturnValue_t Clock::checkOrCreateClockMutex(){ - if(timeMutex == nullptr){ - MutexFactory* mutexFactory = MutexFactory::instance(); - if (mutexFactory == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - timeMutex = mutexFactory->createMutex(); - if (timeMutex == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - } - return HasReturnvaluesIF::RETURN_OK; -} +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../timemanager/Clock.h" + +#include +#if defined(WIN32) +#include +#elif defined(LINUX) +#include +#endif + +uint16_t Clock::leapSeconds = 0; +MutexIF* Clock::timeMutex = NULL; + +using SystemClock = std::chrono::system_clock; + +uint32_t Clock::getTicksPerSecond(void){ + sif::warning << "Clock::getTicksPerSecond: not implemented yet" << std::endl; + return 0; + //return CLOCKS_PER_SEC; + //uint32_t ticks = sysconf(_SC_CLK_TCK); + //return ticks; +} + +ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { + // do some magic with chrono + sif::warning << "Clock::setClock: not implemented yet" << std::endl; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::setClock(const timeval* time) { + // do some magic with chrono +#if defined(WIN32) + return HasReturnvaluesIF::RETURN_OK; +#elif defined(LINUX) + return HasReturnvaluesIF::RETURN_OK; +#else + +#endif + sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; +} + +ReturnValue_t Clock::getClock_timeval(timeval* time) { +#if defined(WIN32) + auto now = std::chrono::system_clock::now(); + auto secondsChrono = std::chrono::time_point_cast(now); + auto epoch = now.time_since_epoch(); + time->tv_sec = std::chrono::duration_cast(epoch).count(); + auto fraction = now - secondsChrono; + time->tv_usec = std::chrono::duration_cast( + fraction).count(); + return HasReturnvaluesIF::RETURN_OK; +#elif defined(LINUX) + timespec timeUnix; + int status = clock_gettime(CLOCK_REALTIME,&timeUnix); + if(status!=0){ + return HasReturnvaluesIF::RETURN_FAILED; + } + time->tv_sec = timeUnix.tv_sec; + time->tv_usec = timeUnix.tv_nsec / 1000.0; + return HasReturnvaluesIF::RETURN_OK; +#else + sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; +#endif + +} + +ReturnValue_t Clock::getClock_usecs(uint64_t* time) { + // do some magic with chrono + sif::warning << "Clock::gerClock_usecs: not implemented yet" << std::endl; + return HasReturnvaluesIF::RETURN_OK; +} + +timeval Clock::getUptime() { + timeval timeval; +#if defined(WIN32) + auto uptime = std::chrono::milliseconds(GetTickCount64()); + auto secondsChrono = std::chrono::duration_cast(uptime); + timeval.tv_sec = secondsChrono.count(); + auto fraction = uptime - secondsChrono; + timeval.tv_usec = std::chrono::duration_cast( + fraction).count(); +#elif defined(LINUX) + double uptimeSeconds; + if (std::ifstream("/proc/uptime", std::ios::in) >> uptimeSeconds) + { + // value is rounded down automatically + timeval.tv_sec = uptimeSeconds; + timeval.tv_usec = uptimeSeconds *(double) 1e6 - (timeval.tv_sec *1e6); + } +#else + sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; +#endif + return timeval; +} + +ReturnValue_t Clock::getUptime(timeval* uptime) { + *uptime = getUptime(); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) { + timeval uptime = getUptime(); + *uptimeMs = uptime.tv_sec * 1000 + uptime.tv_usec / 1000; + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { + // do some magic with chrono (C++20!) + // Right now, the library doesn't have the new features yet. + // so we work around that for now. + auto now = SystemClock::now(); + auto seconds = std::chrono::time_point_cast(now); + auto fraction = now - seconds; + time_t tt = SystemClock::to_time_t(now); + struct tm* timeInfo; + timeInfo = gmtime(&tt); + time->year = timeInfo->tm_year + 1900; + time->month = timeInfo->tm_mon+1; + time->day = timeInfo->tm_mday; + time->hour = timeInfo->tm_hour; + time->minute = timeInfo->tm_min; + time->second = timeInfo->tm_sec; + auto usecond = std::chrono::duration_cast(fraction); + time->usecond = usecond.count(); + + //sif::warning << "Clock::getDateAndTime: not implemented yet" << std::endl; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, + timeval* to) { + struct tm time_tm; + + time_tm.tm_year = from->year - 1900; + time_tm.tm_mon = from->month - 1; + time_tm.tm_mday = from->day; + + time_tm.tm_hour = from->hour; + time_tm.tm_min = from->minute; + time_tm.tm_sec = from->second; + + time_t seconds = mktime(&time_tm); + + to->tv_sec = seconds; + to->tv_usec = from->usecond; + //Fails in 2038.. + return HasReturnvaluesIF::RETURN_OK; + sif::warning << "Clock::convertTimeBla: not implemented yet" << std::endl; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) { + *JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. + / 3600.; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) { + //SHOULDDO: works not for dates in the past (might have less leap seconds) + if (timeMutex == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } + + uint16_t leapSeconds; + ReturnValue_t result = getLeapSeconds(&leapSeconds); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + timeval leapSeconds_timeval = { 0, 0 }; + leapSeconds_timeval.tv_sec = leapSeconds; + + //initial offset between UTC and TAI + timeval UTCtoTAI1972 = { 10, 0 }; + + timeval TAItoTT = { 32, 184000 }; + + *tt = utc + leapSeconds_timeval + UTCtoTAI1972 + TAItoTT; + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) { + if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){ + return HasReturnvaluesIF::RETURN_FAILED; + } + ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + leapSeconds = leapSeconds_; + + result = timeMutex->unlockMutex(); + return result; +} + +ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) { + if(timeMutex == nullptr){ + return HasReturnvaluesIF::RETURN_FAILED; + } + ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + *leapSeconds_ = leapSeconds; + + result = timeMutex->unlockMutex(); + return result; +} + +ReturnValue_t Clock::checkOrCreateClockMutex(){ + if(timeMutex == nullptr){ + MutexFactory* mutexFactory = MutexFactory::instance(); + if (mutexFactory == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + timeMutex = mutexFactory->createMutex(); + if (timeMutex == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/osal/host/FixedTimeslotTask.cpp b/osal/host/FixedTimeslotTask.cpp index 1999c9e6..1139badb 100644 --- a/osal/host/FixedTimeslotTask.cpp +++ b/osal/host/FixedTimeslotTask.cpp @@ -1,191 +1,191 @@ -#include "../../osal/host/FixedTimeslotTask.h" - -#include "../../ipc/MutexFactory.h" -#include "../../osal/host/Mutex.h" -#include "../../osal/host/FixedTimeslotTask.h" - -#include "../../serviceinterface/ServiceInterfaceStream.h" -#include "../../tasks/ExecutableObjectIF.h" - -#include -#include - -#if defined(WIN32) -#include -#elif defined(LINUX) -#include -#endif - -FixedTimeslotTask::FixedTimeslotTask(const char *name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod setPeriod, - void (*setDeadlineMissedFunc)()) : - started(false), pollingSeqTable(setPeriod*1000), taskName(name), - period(setPeriod), deadlineMissedFunc(setDeadlineMissedFunc) { - // It is propably possible to set task priorities by using the native - // task handles for Windows / Linux - mainThread = std::thread(&FixedTimeslotTask::taskEntryPoint, this, this); -#if defined(WIN32) - /* List of possible priority classes: - * https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ - * nf-processthreadsapi-setpriorityclass - * And respective thread priority numbers: - * https://docs.microsoft.com/en-us/windows/ - * win32/procthread/scheduling-priorities */ - int result = SetPriorityClass( - reinterpret_cast(mainThread.native_handle()), - ABOVE_NORMAL_PRIORITY_CLASS); - if(result != 0) { - sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with code " - << GetLastError() << std::endl; - } - result = SetThreadPriority( - reinterpret_cast(mainThread.native_handle()), - THREAD_PRIORITY_NORMAL); - if(result != 0) { - sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with code " - << GetLastError() << std::endl; - } -#elif defined(LINUX) - // we can just copy and paste the code from linux here. -#endif -} - -FixedTimeslotTask::~FixedTimeslotTask(void) { - //Do not delete objects, we were responsible for ptrs only. - terminateThread = true; - if(mainThread.joinable()) { - mainThread.join(); - } - delete this; -} - -void FixedTimeslotTask::taskEntryPoint(void* argument) { - FixedTimeslotTask *originalTask(reinterpret_cast(argument)); - - if (not originalTask->started) { - // we have to suspend/block here until the task is started. - // if semaphores are implemented, use them here. - std::unique_lock lock(initMutex); - initCondition.wait(lock); - } - - this->taskFunctionality(); - sif::debug << "FixedTimeslotTask::taskEntryPoint: " - "Returned from taskFunctionality." << std::endl; -} - -ReturnValue_t FixedTimeslotTask::startTask() { - started = true; - - // Notify task to start. - std::lock_guard lock(initMutex); - initCondition.notify_one(); - - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { - std::this_thread::sleep_for(std::chrono::milliseconds(ms)); - return HasReturnvaluesIF::RETURN_OK; -} - -void FixedTimeslotTask::taskFunctionality() { - // A local iterator for the Polling Sequence Table is created to - // find the start time for the first entry. - FixedSlotSequence::SlotListIter slotListIter = pollingSeqTable.current; - // Get start time for first entry. - chron_ms interval(slotListIter->pollingTimeMs); - auto currentStartTime { - std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()) - }; - if(interval.count() > 0) { - delayForInterval(¤tStartTime, interval); - } - - /* Enter the loop that defines the task behavior. */ - for (;;) { - if(terminateThread.load()) { - break; - } - //The component for this slot is executed and the next one is chosen. - this->pollingSeqTable.executeAndAdvance(); - if (not pollingSeqTable.slotFollowsImmediately()) { - // we need to wait before executing the current slot - //this gives us the time to wait: - interval = chron_ms(this->pollingSeqTable.getIntervalToPreviousSlotMs()); - delayForInterval(¤tStartTime, interval); - //TODO deadline missed check - } - } -} - -ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, - uint32_t slotTimeMs, int8_t executionStep) { - if (objectManager->get(componentId) != nullptr) { - pollingSeqTable.addSlot(componentId, slotTimeMs, executionStep, this); - return HasReturnvaluesIF::RETURN_OK; - } - - sif::error << "Component " << std::hex << componentId << - " not found, not adding it to pst" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; -} - -ReturnValue_t FixedTimeslotTask::checkSequence() const { - return pollingSeqTable.checkSequence(); -} - -uint32_t FixedTimeslotTask::getPeriodMs() const { - return period * 1000; -} - -bool FixedTimeslotTask::delayForInterval(chron_ms * previousWakeTimeMs, - const chron_ms interval) { - bool shouldDelay = false; - //Get current wakeup time - auto currentStartTime = - std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()); - /* Generate the tick time at which the task wants to wake. */ - auto nextTimeToWake_ms = (*previousWakeTimeMs) + interval; - - if (currentStartTime < *previousWakeTimeMs) { - /* The tick count has overflowed since this function was - lasted called. In this case the only time we should ever - actually delay is if the wake time has also overflowed, - and the wake time is greater than the tick time. When this - is the case it is as if neither time had overflowed. */ - if ((nextTimeToWake_ms < *previousWakeTimeMs) - && (nextTimeToWake_ms > currentStartTime)) { - shouldDelay = true; - } - } else { - /* The tick time has not overflowed. In this case we will - delay if either the wake time has overflowed, and/or the - tick time is less than the wake time. */ - if ((nextTimeToWake_ms < *previousWakeTimeMs) - || (nextTimeToWake_ms > currentStartTime)) { - shouldDelay = true; - } - } - - /* Update the wake time ready for the next call. */ - - (*previousWakeTimeMs) = nextTimeToWake_ms; - - if (shouldDelay) { - auto sleepTime = std::chrono::duration_cast( - nextTimeToWake_ms - currentStartTime); - std::this_thread::sleep_for(sleepTime); - return true; - } - //We are shifting the time in case the deadline was missed like rtems - (*previousWakeTimeMs) = currentStartTime; - return false; - -} - - - - +#include "../../osal/host/FixedTimeslotTask.h" + +#include "../../ipc/MutexFactory.h" +#include "../../osal/host/Mutex.h" +#include "../../osal/host/FixedTimeslotTask.h" + +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../tasks/ExecutableObjectIF.h" + +#include +#include + +#if defined(WIN32) +#include +#elif defined(LINUX) +#include +#endif + +FixedTimeslotTask::FixedTimeslotTask(const char *name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod setPeriod, + void (*setDeadlineMissedFunc)()) : + started(false), pollingSeqTable(setPeriod*1000), taskName(name), + period(setPeriod), deadlineMissedFunc(setDeadlineMissedFunc) { + // It is propably possible to set task priorities by using the native + // task handles for Windows / Linux + mainThread = std::thread(&FixedTimeslotTask::taskEntryPoint, this, this); +#if defined(WIN32) + /* List of possible priority classes: + * https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ + * nf-processthreadsapi-setpriorityclass + * And respective thread priority numbers: + * https://docs.microsoft.com/en-us/windows/ + * win32/procthread/scheduling-priorities */ + int result = SetPriorityClass( + reinterpret_cast(mainThread.native_handle()), + ABOVE_NORMAL_PRIORITY_CLASS); + if(result != 0) { + sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with code " + << GetLastError() << std::endl; + } + result = SetThreadPriority( + reinterpret_cast(mainThread.native_handle()), + THREAD_PRIORITY_NORMAL); + if(result != 0) { + sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with code " + << GetLastError() << std::endl; + } +#elif defined(LINUX) + // we can just copy and paste the code from linux here. +#endif +} + +FixedTimeslotTask::~FixedTimeslotTask(void) { + //Do not delete objects, we were responsible for ptrs only. + terminateThread = true; + if(mainThread.joinable()) { + mainThread.join(); + } + delete this; +} + +void FixedTimeslotTask::taskEntryPoint(void* argument) { + FixedTimeslotTask *originalTask(reinterpret_cast(argument)); + + if (not originalTask->started) { + // we have to suspend/block here until the task is started. + // if semaphores are implemented, use them here. + std::unique_lock lock(initMutex); + initCondition.wait(lock); + } + + this->taskFunctionality(); + sif::debug << "FixedTimeslotTask::taskEntryPoint: " + "Returned from taskFunctionality." << std::endl; +} + +ReturnValue_t FixedTimeslotTask::startTask() { + started = true; + + // Notify task to start. + std::lock_guard lock(initMutex); + initCondition.notify_one(); + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); + return HasReturnvaluesIF::RETURN_OK; +} + +void FixedTimeslotTask::taskFunctionality() { + // A local iterator for the Polling Sequence Table is created to + // find the start time for the first entry. + FixedSlotSequence::SlotListIter slotListIter = pollingSeqTable.current; + // Get start time for first entry. + chron_ms interval(slotListIter->pollingTimeMs); + auto currentStartTime { + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + }; + if(interval.count() > 0) { + delayForInterval(¤tStartTime, interval); + } + + /* Enter the loop that defines the task behavior. */ + for (;;) { + if(terminateThread.load()) { + break; + } + //The component for this slot is executed and the next one is chosen. + this->pollingSeqTable.executeAndAdvance(); + if (not pollingSeqTable.slotFollowsImmediately()) { + // we need to wait before executing the current slot + //this gives us the time to wait: + interval = chron_ms(this->pollingSeqTable.getIntervalToPreviousSlotMs()); + delayForInterval(¤tStartTime, interval); + //TODO deadline missed check + } + } +} + +ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, + uint32_t slotTimeMs, int8_t executionStep) { + if (objectManager->get(componentId) != nullptr) { + pollingSeqTable.addSlot(componentId, slotTimeMs, executionStep, this); + return HasReturnvaluesIF::RETURN_OK; + } + + sif::error << "Component " << std::hex << componentId << + " not found, not adding it to pst" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; +} + +ReturnValue_t FixedTimeslotTask::checkAndInitializeSequence() const { + return pollingSeqTable.checkSequence(); +} + +uint32_t FixedTimeslotTask::getPeriodMs() const { + return period * 1000; +} + +bool FixedTimeslotTask::delayForInterval(chron_ms * previousWakeTimeMs, + const chron_ms interval) { + bool shouldDelay = false; + //Get current wakeup time + auto currentStartTime = + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()); + /* Generate the tick time at which the task wants to wake. */ + auto nextTimeToWake_ms = (*previousWakeTimeMs) + interval; + + if (currentStartTime < *previousWakeTimeMs) { + /* The tick count has overflowed since this function was + lasted called. In this case the only time we should ever + actually delay is if the wake time has also overflowed, + and the wake time is greater than the tick time. When this + is the case it is as if neither time had overflowed. */ + if ((nextTimeToWake_ms < *previousWakeTimeMs) + && (nextTimeToWake_ms > currentStartTime)) { + shouldDelay = true; + } + } else { + /* The tick time has not overflowed. In this case we will + delay if either the wake time has overflowed, and/or the + tick time is less than the wake time. */ + if ((nextTimeToWake_ms < *previousWakeTimeMs) + || (nextTimeToWake_ms > currentStartTime)) { + shouldDelay = true; + } + } + + /* Update the wake time ready for the next call. */ + + (*previousWakeTimeMs) = nextTimeToWake_ms; + + if (shouldDelay) { + auto sleepTime = std::chrono::duration_cast( + nextTimeToWake_ms - currentStartTime); + std::this_thread::sleep_for(sleepTime); + return true; + } + //We are shifting the time in case the deadline was missed like rtems + (*previousWakeTimeMs) = currentStartTime; + return false; + +} + + + + diff --git a/osal/host/FixedTimeslotTask.h b/osal/host/FixedTimeslotTask.h index bbee94a6..3ea97b97 100644 --- a/osal/host/FixedTimeslotTask.h +++ b/osal/host/FixedTimeslotTask.h @@ -1,130 +1,130 @@ -#ifndef FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ -#define FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ - -#include "../../objectmanager/ObjectManagerIF.h" -#include "../../tasks/FixedSlotSequence.h" -#include "../../tasks/FixedTimeslotTaskIF.h" -#include "../../tasks/Typedef.h" - -#include -#include -#include -#include - -class ExecutableObjectIF; - -/** - * @brief This class represents a task for periodic activities with multiple - * steps and strict timeslot requirements for these steps. - * @details - * @ingroup task_handling - */ -class FixedTimeslotTask: public FixedTimeslotTaskIF { -public: - /** - * @brief Standard constructor of the class. - * @details - * The class is initialized without allocated objects. These need to be - * added with #addComponent. - * @param priority - * @param stack_size - * @param setPeriod - * @param setDeadlineMissedFunc - * The function pointer to the deadline missed function that shall be - * assigned. - */ - FixedTimeslotTask(const char *name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod setPeriod, - void (*setDeadlineMissedFunc)()); - /** - * @brief Currently, the executed object's lifetime is not coupled with - * the task object's lifetime, so the destructor is empty. - */ - virtual ~FixedTimeslotTask(void); - - /** - * @brief The method to start the task. - * @details The method starts the task with the respective system call. - * Entry point is the taskEntryPoint method described below. - * The address of the task object is passed as an argument - * to the system call. - */ - ReturnValue_t startTask(void); - - /** - * Add timeslot to the polling sequence table. - * @param componentId - * @param slotTimeMs - * @param executionStep - * @return - */ - ReturnValue_t addSlot(object_id_t componentId, - uint32_t slotTimeMs, int8_t executionStep); - - ReturnValue_t checkSequence() const; - - uint32_t getPeriodMs() const; - - ReturnValue_t sleepFor(uint32_t ms); - -protected: - using chron_ms = std::chrono::milliseconds; - - bool started; - //!< Typedef for the List of objects. - typedef std::vector ObjectList; - std::thread mainThread; - std::atomic terminateThread = false; - - //! Polling sequence table which contains the object to execute - //! and information like the timeslots and the passed execution step. - FixedSlotSequence pollingSeqTable; - - std::condition_variable initCondition; - std::mutex initMutex; - std::string taskName; - /** - * @brief The period of the task. - * @details - * The period determines the frequency of the task's execution. - * It is expressed in clock ticks. - */ - TaskPeriod period; - - /** - * @brief The pointer to the deadline-missed function. - * @details - * This pointer stores the function that is executed if the task's deadline - * is missed. So, each may react individually on a timing failure. - * The pointer may be NULL, then nothing happens on missing the deadline. - * The deadline is equal to the next execution of the periodic task. - */ - void (*deadlineMissedFunc)(void); - /** - * @brief This is the function executed in the new task's context. - * @details - * It converts the argument back to the thread object type and copies the - * class instance to the task context. - * The taskFunctionality method is called afterwards. - * @param A pointer to the task object itself is passed as argument. - */ - - void taskEntryPoint(void* argument); - /** - * @brief The function containing the actual functionality of the task. - * @details - * The method sets and starts the task's period, then enters a loop that is - * repeated as long as the isRunning attribute is true. Within the loop, - * all performOperation methods of the added objects are called. Afterwards - * the checkAndRestartPeriod system call blocks the task until the next - * period. On missing the deadline, the deadlineMissedFunction is executed. - */ - void taskFunctionality(void); - - bool delayForInterval(chron_ms * previousWakeTimeMs, - const chron_ms interval); -}; - - - -#endif /* FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ */ +#ifndef FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ +#define FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ + +#include "../../objectmanager/ObjectManagerIF.h" +#include "../../tasks/FixedSlotSequence.h" +#include "../../tasks/FixedTimeslotTaskIF.h" +#include "../../tasks/Typedef.h" + +#include +#include +#include +#include + +class ExecutableObjectIF; + +/** + * @brief This class represents a task for periodic activities with multiple + * steps and strict timeslot requirements for these steps. + * @details + * @ingroup task_handling + */ +class FixedTimeslotTask: public FixedTimeslotTaskIF { +public: + /** + * @brief Standard constructor of the class. + * @details + * The class is initialized without allocated objects. These need to be + * added with #addComponent. + * @param priority + * @param stack_size + * @param setPeriod + * @param setDeadlineMissedFunc + * The function pointer to the deadline missed function that shall be + * assigned. + */ + FixedTimeslotTask(const char *name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod setPeriod, + void (*setDeadlineMissedFunc)()); + /** + * @brief Currently, the executed object's lifetime is not coupled with + * the task object's lifetime, so the destructor is empty. + */ + virtual ~FixedTimeslotTask(void); + + /** + * @brief The method to start the task. + * @details The method starts the task with the respective system call. + * Entry point is the taskEntryPoint method described below. + * The address of the task object is passed as an argument + * to the system call. + */ + ReturnValue_t startTask(void); + + /** + * Add timeslot to the polling sequence table. + * @param componentId + * @param slotTimeMs + * @param executionStep + * @return + */ + ReturnValue_t addSlot(object_id_t componentId, + uint32_t slotTimeMs, int8_t executionStep); + + ReturnValue_t checkAndInitializeSequence() const; + + uint32_t getPeriodMs() const; + + ReturnValue_t sleepFor(uint32_t ms); + +protected: + using chron_ms = std::chrono::milliseconds; + + bool started; + //!< Typedef for the List of objects. + typedef std::vector ObjectList; + std::thread mainThread; + std::atomic terminateThread = false; + + //! Polling sequence table which contains the object to execute + //! and information like the timeslots and the passed execution step. + FixedSlotSequence pollingSeqTable; + + std::condition_variable initCondition; + std::mutex initMutex; + std::string taskName; + /** + * @brief The period of the task. + * @details + * The period determines the frequency of the task's execution. + * It is expressed in clock ticks. + */ + TaskPeriod period; + + /** + * @brief The pointer to the deadline-missed function. + * @details + * This pointer stores the function that is executed if the task's deadline + * is missed. So, each may react individually on a timing failure. + * The pointer may be NULL, then nothing happens on missing the deadline. + * The deadline is equal to the next execution of the periodic task. + */ + void (*deadlineMissedFunc)(void); + /** + * @brief This is the function executed in the new task's context. + * @details + * It converts the argument back to the thread object type and copies the + * class instance to the task context. + * The taskFunctionality method is called afterwards. + * @param A pointer to the task object itself is passed as argument. + */ + + void taskEntryPoint(void* argument); + /** + * @brief The function containing the actual functionality of the task. + * @details + * The method sets and starts the task's period, then enters a loop that is + * repeated as long as the isRunning attribute is true. Within the loop, + * all performOperation methods of the added objects are called. Afterwards + * the checkAndRestartPeriod system call blocks the task until the next + * period. On missing the deadline, the deadlineMissedFunction is executed. + */ + void taskFunctionality(void); + + bool delayForInterval(chron_ms * previousWakeTimeMs, + const chron_ms interval); +}; + + + +#endif /* FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ */ diff --git a/osal/host/MessageQueue.cpp b/osal/host/MessageQueue.cpp index 6fd42849..8a34282c 100644 --- a/osal/host/MessageQueue.cpp +++ b/osal/host/MessageQueue.cpp @@ -1,155 +1,155 @@ -#include "../../osal/host/MessageQueue.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" -#include "../../osal/host/QueueMapManager.h" -#include "../../ipc/MutexFactory.h" -#include "../../ipc/MutexHelper.h" - -MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize): - messageSize(maxMessageSize), messageDepth(messageDepth) { - queueLock = MutexFactory::instance()->createMutex(); - auto result = QueueMapManager::instance()->addMessageQueue(this, &mqId); - if(result != HasReturnvaluesIF::RETURN_OK) { - sif::error << "MessageQueue: Could not be created" << std::endl; - } -} - -MessageQueue::~MessageQueue() { - MutexFactory::instance()->deleteMutex(queueLock); -} - -ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessageIF* message, bool ignoreFault) { - return sendMessageFrom(sendTo, message, this->getId(), ignoreFault); -} - -ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) { - return sendToDefaultFrom(message, this->getId()); -} - -ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message, - MessageQueueId_t sentFrom, bool ignoreFault) { - return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault); -} - -ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) { - if (this->lastPartner != 0) { - return sendMessageFrom(this->lastPartner, message, this->getId()); - } else { - return MessageQueueIF::NO_REPLY_PARTNER; - } -} - -ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, - MessageQueueMessageIF* message, MessageQueueId_t sentFrom, - bool ignoreFault) { - return sendMessageFromMessageQueue(sendTo, message, sentFrom, - ignoreFault); -} - -ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message, - MessageQueueId_t* receivedFrom) { - ReturnValue_t status = this->receiveMessage(message); - if(status == HasReturnvaluesIF::RETURN_OK) { - *receivedFrom = this->lastPartner; - } - return status; -} - -ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { - if(messageQueue.empty()) { - return MessageQueueIF::EMPTY; - } - // not sure this will work.. - //*message = std::move(messageQueue.front()); - MutexHelper mutexLock(queueLock, 20); - MessageQueueMessage* currentMessage = &messageQueue.front(); - std::copy(currentMessage->getBuffer(), - currentMessage->getBuffer() + messageSize, message->getBuffer()); - messageQueue.pop(); - // The last partner is the first uint32_t field in the message - this->lastPartner = message->getSender(); - return HasReturnvaluesIF::RETURN_OK; -} - -MessageQueueId_t MessageQueue::getLastPartner() const { - return lastPartner; -} - -ReturnValue_t MessageQueue::flush(uint32_t* count) { - *count = messageQueue.size(); - // Clears the queue. - messageQueue = std::queue(); - return HasReturnvaluesIF::RETURN_OK; -} - -MessageQueueId_t MessageQueue::getId() const { - return mqId; -} - -void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) { - defaultDestinationSet = true; - this->defaultDestination = defaultDestination; -} - -MessageQueueId_t MessageQueue::getDefaultDestination() const { - return defaultDestination; -} - -bool MessageQueue::isDefaultDestinationSet() const { - return defaultDestinationSet; -} - - -// static core function to send messages. -ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, - MessageQueueMessageIF* message, MessageQueueId_t sentFrom, - bool ignoreFault) { - if(message->getMessageSize() > message->getMaximumMessageSize()) { - // Actually, this should never happen or an error will be emitted - // in MessageQueueMessage. - // But I will still return a failure here. - return HasReturnvaluesIF::RETURN_FAILED; - } - MessageQueue* targetQueue = dynamic_cast( - QueueMapManager::instance()->getMessageQueue(sendTo)); - if(targetQueue == nullptr) { - if(not ignoreFault) { - InternalErrorReporterIF* internalErrorReporter = - objectManager->get( - objects::INTERNAL_ERROR_REPORTER); - if (internalErrorReporter != nullptr) { - internalErrorReporter->queueMessageNotSent(); - } - } - // TODO: Better returnvalue - return HasReturnvaluesIF::RETURN_FAILED; - } - - if(targetQueue->messageQueue.size() < targetQueue->messageDepth) { - MutexHelper mutexLock(targetQueue->queueLock, 20); - // not ideal, works for now though. - MessageQueueMessage* mqmMessage = - dynamic_cast(message); - if(message != nullptr) { - targetQueue->messageQueue.push(*mqmMessage); - } - else { - sif::error << "MessageQueue::sendMessageFromMessageQueue: Message" - "is not MessageQueueMessage!" << std::endl; - } - - } - else { - return MessageQueueIF::FULL; - } - message->setSender(sentFrom); - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t MessageQueue::lockQueue(dur_millis_t lockTimeout) { - return queueLock->lockMutex(lockTimeout); -} - -ReturnValue_t MessageQueue::unlockQueue() { - return queueLock->unlockMutex(); -} +#include "../../osal/host/MessageQueue.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../osal/host/QueueMapManager.h" +#include "../../ipc/MutexFactory.h" +#include "../../ipc/MutexHelper.h" + +MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize): + messageSize(maxMessageSize), messageDepth(messageDepth) { + queueLock = MutexFactory::instance()->createMutex(); + auto result = QueueMapManager::instance()->addMessageQueue(this, &mqId); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "MessageQueue: Could not be created" << std::endl; + } +} + +MessageQueue::~MessageQueue() { + MutexFactory::instance()->deleteMutex(queueLock); +} + +ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, bool ignoreFault) { + return sendMessageFrom(sendTo, message, this->getId(), ignoreFault); +} + +ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) { + return sendToDefaultFrom(message, this->getId()); +} + +ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message, + MessageQueueId_t sentFrom, bool ignoreFault) { + return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault); +} + +ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) { + if (this->lastPartner != 0) { + return sendMessageFrom(this->lastPartner, message, this->getId()); + } else { + return MessageQueueIF::NO_REPLY_PARTNER; + } +} + +ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + return sendMessageFromMessageQueue(sendTo, message, sentFrom, + ignoreFault); +} + +ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message, + MessageQueueId_t* receivedFrom) { + ReturnValue_t status = this->receiveMessage(message); + if(status == HasReturnvaluesIF::RETURN_OK) { + *receivedFrom = this->lastPartner; + } + return status; +} + +ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { + if(messageQueue.empty()) { + return MessageQueueIF::EMPTY; + } + // not sure this will work.. + //*message = std::move(messageQueue.front()); + MutexHelper mutexLock(queueLock, 20); + MessageQueueMessage* currentMessage = &messageQueue.front(); + std::copy(currentMessage->getBuffer(), + currentMessage->getBuffer() + messageSize, message->getBuffer()); + messageQueue.pop(); + // The last partner is the first uint32_t field in the message + this->lastPartner = message->getSender(); + return HasReturnvaluesIF::RETURN_OK; +} + +MessageQueueId_t MessageQueue::getLastPartner() const { + return lastPartner; +} + +ReturnValue_t MessageQueue::flush(uint32_t* count) { + *count = messageQueue.size(); + // Clears the queue. + messageQueue = std::queue(); + return HasReturnvaluesIF::RETURN_OK; +} + +MessageQueueId_t MessageQueue::getId() const { + return mqId; +} + +void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) { + defaultDestinationSet = true; + this->defaultDestination = defaultDestination; +} + +MessageQueueId_t MessageQueue::getDefaultDestination() const { + return defaultDestination; +} + +bool MessageQueue::isDefaultDestinationSet() const { + return defaultDestinationSet; +} + + +// static core function to send messages. +ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + if(message->getMessageSize() > message->getMaximumMessageSize()) { + // Actually, this should never happen or an error will be emitted + // in MessageQueueMessage. + // But I will still return a failure here. + return HasReturnvaluesIF::RETURN_FAILED; + } + MessageQueue* targetQueue = dynamic_cast( + QueueMapManager::instance()->getMessageQueue(sendTo)); + if(targetQueue == nullptr) { + if(not ignoreFault) { + InternalErrorReporterIF* internalErrorReporter = + objectManager->get( + objects::INTERNAL_ERROR_REPORTER); + if (internalErrorReporter != nullptr) { + internalErrorReporter->queueMessageNotSent(); + } + } + // TODO: Better returnvalue + return HasReturnvaluesIF::RETURN_FAILED; + } + + if(targetQueue->messageQueue.size() < targetQueue->messageDepth) { + MutexHelper mutexLock(targetQueue->queueLock, 20); + // not ideal, works for now though. + MessageQueueMessage* mqmMessage = + dynamic_cast(message); + if(message != nullptr) { + targetQueue->messageQueue.push(*mqmMessage); + } + else { + sif::error << "MessageQueue::sendMessageFromMessageQueue: Message" + "is not MessageQueueMessage!" << std::endl; + } + + } + else { + return MessageQueueIF::FULL; + } + message->setSender(sentFrom); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t MessageQueue::lockQueue(dur_millis_t lockTimeout) { + return queueLock->lockMutex(lockTimeout); +} + +ReturnValue_t MessageQueue::unlockQueue() { + return queueLock->unlockMutex(); +} diff --git a/osal/host/MessageQueue.h b/osal/host/MessageQueue.h index d2da2402..21a01663 100644 --- a/osal/host/MessageQueue.h +++ b/osal/host/MessageQueue.h @@ -1,230 +1,230 @@ -#ifndef FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ -#define FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ - -#include "../../internalError/InternalErrorReporterIF.h" -#include "../../ipc/MessageQueueIF.h" -#include "../../ipc/MessageQueueMessage.h" -#include "../../ipc/MutexIF.h" -#include "../../timemanager/Clock.h" - -#include -#include - -/** - * @brief This class manages sending and receiving of - * message queue messages. - * @details - * Message queues are used to pass asynchronous messages between processes. - * They work like post boxes, where all incoming messages are stored in FIFO - * order. This class creates a new receiving queue and provides methods to fetch - * received messages. Being a child of MessageQueueSender, this class also - * provides methods to send a message to a user-defined or a default destination. - * In addition it also provides a reply method to answer to the queue it - * received its last message from. - * - * The MessageQueue should be used as "post box" for a single owning object. - * So all message queue communication is "n-to-one". - * For creating the queue, as well as sending and receiving messages, the class - * makes use of the operating system calls provided. - * - * Please keep in mind that FreeRTOS offers different calls for message queue - * operations if called from an ISR. - * For now, the system context needs to be switched manually. - * @ingroup osal - * @ingroup message_queue - */ -class MessageQueue : public MessageQueueIF { - friend class MessageQueueSenderIF; -public: - /** - * @brief The constructor initializes and configures the message queue. - * @details - * By making use of the according operating system call, a message queue is - * created and initialized. The message depth - the maximum number of - * messages to be buffered - may be set with the help of a parameter, - * whereas the message size is automatically set to the maximum message - * queue message size. The operating system sets the message queue id, or - * in case of failure, it is set to zero. - * @param message_depth - * The number of messages to be buffered before passing an error to the - * sender. Default is three. - * @param max_message_size - * With this parameter, the maximum message size can be adjusted. - * This should be left default. - */ - MessageQueue(size_t messageDepth = 3, - size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE); - - /** Copying message queues forbidden */ - MessageQueue(const MessageQueue&) = delete; - MessageQueue& operator=(const MessageQueue&) = delete; - - /** - * @brief The destructor deletes the formerly created message queue. - * @details This is accomplished by using the delete call provided - * by the operating system. - */ - virtual ~MessageQueue(); - - /** - * @brief This operation sends a message to the given destination. - * @details It directly uses the sendMessage call of the MessageQueueSender - * parent, but passes its queue id as "sentFrom" parameter. - * @param sendTo This parameter specifies the message queue id of the - * destination message queue. - * @param message A pointer to a previously created message, which is sent. - * @param ignoreFault If set to true, the internal software fault counter - * is not incremented if queue is full. - */ - ReturnValue_t sendMessage(MessageQueueId_t sendTo, - MessageQueueMessageIF* message, bool ignoreFault = false) override; - /** - * @brief This operation sends a message to the default destination. - * @details As in the sendMessage method, this function uses the - * sendToDefault call of the MessageQueueSender parent class and adds its - * queue id as "sentFrom" information. - * @param message A pointer to a previously created message, which is sent. - */ - ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override; - /** - * @brief This operation sends a message to the last communication partner. - * @details This operation simplifies answering an incoming message by using - * the stored lastPartner information as destination. If there was no - * message received yet (i.e. lastPartner is zero), an error code is returned. - * @param message A pointer to a previously created message, which is sent. - */ - ReturnValue_t reply(MessageQueueMessageIF* message) override; - - /** - * @brief With the sendMessage call, a queue message is sent to a - * receiving queue. - * @details - * This method takes the message provided, adds the sentFrom information and - * passes it on to the destination provided with an operating system call. - * The OS's return value is returned. - * @param sendTo This parameter specifies the message queue id to send - * the message to. - * @param message This is a pointer to a previously created message, - * which is sent. - * @param sentFrom The sentFrom information can be set to inject the - * sender's queue id into the message. This variable is set to zero by - * default. - * @param ignoreFault If set to true, the internal software fault counter - * is not incremented if queue is full. - */ - virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, - MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE, - bool ignoreFault = false) override; - - /** - * @brief The sendToDefault method sends a queue message to the default - * destination. - * @details - * In all other aspects, it works identical to the sendMessage method. - * @param message This is a pointer to a previously created message, - * which is sent. - * @param sentFrom The sentFrom information can be set to inject the - * sender's queue id into the message. This variable is set to zero by - * default. - */ - virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message, - MessageQueueId_t sentFrom = NO_QUEUE, - bool ignoreFault = false) override; - - /** - * @brief This function reads available messages from the message queue - * and returns the sender. - * @details - * It works identically to the other receiveMessage call, but in addition - * returns the sender's queue id. - * @param message A pointer to a message in which the received data is stored. - * @param receivedFrom A pointer to a queue id in which the sender's id is stored. - */ - ReturnValue_t receiveMessage(MessageQueueMessageIF* message, - MessageQueueId_t *receivedFrom) override; - - /** - * @brief This function reads available messages from the message queue. - * @details - * If data is available it is stored in the passed message pointer. - * The message's original content is overwritten and the sendFrom - * information is stored in the lastPartner attribute. Else, the lastPartner - * information remains untouched, the message's content is cleared and the - * function returns immediately. - * @param message A pointer to a message in which the received data is stored. - */ - ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override; - /** - * Deletes all pending messages in the queue. - * @param count The number of flushed messages. - * @return RETURN_OK on success. - */ - ReturnValue_t flush(uint32_t* count) override; - /** - * @brief This method returns the message queue id of the last - * communication partner. - */ - MessageQueueId_t getLastPartner() const override; - /** - * @brief This method returns the message queue id of this class's - * message queue. - */ - MessageQueueId_t getId() const override; - - /** - * @brief This method is a simple setter for the default destination. - */ - void setDefaultDestination(MessageQueueId_t defaultDestination) override; - /** - * @brief This method is a simple getter for the default destination. - */ - MessageQueueId_t getDefaultDestination() const override; - - bool isDefaultDestinationSet() const override; - - ReturnValue_t lockQueue(dur_millis_t lockTimeout); - ReturnValue_t unlockQueue(); -protected: - /** - * @brief Implementation to be called from any send Call within - * MessageQueue and MessageQueueSenderIF. - * @details - * This method takes the message provided, adds the sentFrom information and - * passes it on to the destination provided with an operating system call. - * The OS's return value is returned. - * @param sendTo - * This parameter specifies the message queue id to send the message to. - * @param message - * This is a pointer to a previously created message, which is sent. - * @param sentFrom - * The sentFrom information can be set to inject the sender's queue id into - * the message. This variable is set to zero by default. - * @param ignoreFault - * If set to true, the internal software fault counter is not incremented - * if queue is full. - * @param context Specify whether call is made from task or from an ISR. - */ - static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo, - MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE, - bool ignoreFault=false); - - //static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault); - -private: - std::queue messageQueue; - /** - * @brief The class stores the queue id it got assigned. - * If initialization fails, the queue id is set to zero. - */ - MessageQueueId_t mqId = 0; - size_t messageSize = 0; - size_t messageDepth = 0; - - MutexIF* queueLock; - - bool defaultDestinationSet = false; - MessageQueueId_t defaultDestination = 0; - MessageQueueId_t lastPartner = 0; -}; - -#endif /* FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ */ +#ifndef FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ +#define FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ + +#include "../../internalError/InternalErrorReporterIF.h" +#include "../../ipc/MessageQueueIF.h" +#include "../../ipc/MessageQueueMessage.h" +#include "../../ipc/MutexIF.h" +#include "../../timemanager/Clock.h" + +#include +#include + +/** + * @brief This class manages sending and receiving of + * message queue messages. + * @details + * Message queues are used to pass asynchronous messages between processes. + * They work like post boxes, where all incoming messages are stored in FIFO + * order. This class creates a new receiving queue and provides methods to fetch + * received messages. Being a child of MessageQueueSender, this class also + * provides methods to send a message to a user-defined or a default destination. + * In addition it also provides a reply method to answer to the queue it + * received its last message from. + * + * The MessageQueue should be used as "post box" for a single owning object. + * So all message queue communication is "n-to-one". + * For creating the queue, as well as sending and receiving messages, the class + * makes use of the operating system calls provided. + * + * Please keep in mind that FreeRTOS offers different calls for message queue + * operations if called from an ISR. + * For now, the system context needs to be switched manually. + * @ingroup osal + * @ingroup message_queue + */ +class MessageQueue : public MessageQueueIF { + friend class MessageQueueSenderIF; +public: + /** + * @brief The constructor initializes and configures the message queue. + * @details + * By making use of the according operating system call, a message queue is + * created and initialized. The message depth - the maximum number of + * messages to be buffered - may be set with the help of a parameter, + * whereas the message size is automatically set to the maximum message + * queue message size. The operating system sets the message queue id, or + * in case of failure, it is set to zero. + * @param message_depth + * The number of messages to be buffered before passing an error to the + * sender. Default is three. + * @param max_message_size + * With this parameter, the maximum message size can be adjusted. + * This should be left default. + */ + MessageQueue(size_t messageDepth = 3, + size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE); + + /** Copying message queues forbidden */ + MessageQueue(const MessageQueue&) = delete; + MessageQueue& operator=(const MessageQueue&) = delete; + + /** + * @brief The destructor deletes the formerly created message queue. + * @details This is accomplished by using the delete call provided + * by the operating system. + */ + virtual ~MessageQueue(); + + /** + * @brief This operation sends a message to the given destination. + * @details It directly uses the sendMessage call of the MessageQueueSender + * parent, but passes its queue id as "sentFrom" parameter. + * @param sendTo This parameter specifies the message queue id of the + * destination message queue. + * @param message A pointer to a previously created message, which is sent. + * @param ignoreFault If set to true, the internal software fault counter + * is not incremented if queue is full. + */ + ReturnValue_t sendMessage(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, bool ignoreFault = false) override; + /** + * @brief This operation sends a message to the default destination. + * @details As in the sendMessage method, this function uses the + * sendToDefault call of the MessageQueueSender parent class and adds its + * queue id as "sentFrom" information. + * @param message A pointer to a previously created message, which is sent. + */ + ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override; + /** + * @brief This operation sends a message to the last communication partner. + * @details This operation simplifies answering an incoming message by using + * the stored lastPartner information as destination. If there was no + * message received yet (i.e. lastPartner is zero), an error code is returned. + * @param message A pointer to a previously created message, which is sent. + */ + ReturnValue_t reply(MessageQueueMessageIF* message) override; + + /** + * @brief With the sendMessage call, a queue message is sent to a + * receiving queue. + * @details + * This method takes the message provided, adds the sentFrom information and + * passes it on to the destination provided with an operating system call. + * The OS's return value is returned. + * @param sendTo This parameter specifies the message queue id to send + * the message to. + * @param message This is a pointer to a previously created message, + * which is sent. + * @param sentFrom The sentFrom information can be set to inject the + * sender's queue id into the message. This variable is set to zero by + * default. + * @param ignoreFault If set to true, the internal software fault counter + * is not incremented if queue is full. + */ + virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE, + bool ignoreFault = false) override; + + /** + * @brief The sendToDefault method sends a queue message to the default + * destination. + * @details + * In all other aspects, it works identical to the sendMessage method. + * @param message This is a pointer to a previously created message, + * which is sent. + * @param sentFrom The sentFrom information can be set to inject the + * sender's queue id into the message. This variable is set to zero by + * default. + */ + virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message, + MessageQueueId_t sentFrom = NO_QUEUE, + bool ignoreFault = false) override; + + /** + * @brief This function reads available messages from the message queue + * and returns the sender. + * @details + * It works identically to the other receiveMessage call, but in addition + * returns the sender's queue id. + * @param message A pointer to a message in which the received data is stored. + * @param receivedFrom A pointer to a queue id in which the sender's id is stored. + */ + ReturnValue_t receiveMessage(MessageQueueMessageIF* message, + MessageQueueId_t *receivedFrom) override; + + /** + * @brief This function reads available messages from the message queue. + * @details + * If data is available it is stored in the passed message pointer. + * The message's original content is overwritten and the sendFrom + * information is stored in the lastPartner attribute. Else, the lastPartner + * information remains untouched, the message's content is cleared and the + * function returns immediately. + * @param message A pointer to a message in which the received data is stored. + */ + ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override; + /** + * Deletes all pending messages in the queue. + * @param count The number of flushed messages. + * @return RETURN_OK on success. + */ + ReturnValue_t flush(uint32_t* count) override; + /** + * @brief This method returns the message queue id of the last + * communication partner. + */ + MessageQueueId_t getLastPartner() const override; + /** + * @brief This method returns the message queue id of this class's + * message queue. + */ + MessageQueueId_t getId() const override; + + /** + * @brief This method is a simple setter for the default destination. + */ + void setDefaultDestination(MessageQueueId_t defaultDestination) override; + /** + * @brief This method is a simple getter for the default destination. + */ + MessageQueueId_t getDefaultDestination() const override; + + bool isDefaultDestinationSet() const override; + + ReturnValue_t lockQueue(dur_millis_t lockTimeout); + ReturnValue_t unlockQueue(); +protected: + /** + * @brief Implementation to be called from any send Call within + * MessageQueue and MessageQueueSenderIF. + * @details + * This method takes the message provided, adds the sentFrom information and + * passes it on to the destination provided with an operating system call. + * The OS's return value is returned. + * @param sendTo + * This parameter specifies the message queue id to send the message to. + * @param message + * This is a pointer to a previously created message, which is sent. + * @param sentFrom + * The sentFrom information can be set to inject the sender's queue id into + * the message. This variable is set to zero by default. + * @param ignoreFault + * If set to true, the internal software fault counter is not incremented + * if queue is full. + * @param context Specify whether call is made from task or from an ISR. + */ + static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE, + bool ignoreFault=false); + + //static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault); + +private: + std::queue messageQueue; + /** + * @brief The class stores the queue id it got assigned. + * If initialization fails, the queue id is set to zero. + */ + MessageQueueId_t mqId = 0; + size_t messageSize = 0; + size_t messageDepth = 0; + + MutexIF* queueLock; + + bool defaultDestinationSet = false; + MessageQueueId_t defaultDestination = 0; + MessageQueueId_t lastPartner = 0; +}; + +#endif /* FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ */ diff --git a/osal/host/Mutex.cpp b/osal/host/Mutex.cpp index 28768507..2718f2b9 100644 --- a/osal/host/Mutex.cpp +++ b/osal/host/Mutex.cpp @@ -1,40 +1,40 @@ -#include "../../osal/host/Mutex.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" - -const uint32_t MutexIF::POLLING = 0; -const uint32_t MutexIF::BLOCKING = 0xffffffff; - -ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { - if(timeoutMs == MutexIF::BLOCKING) { - mutex.lock(); - locked = true; - return HasReturnvaluesIF::RETURN_OK; - } - else if(timeoutMs == MutexIF::POLLING) { - if(mutex.try_lock()) { - locked = true; - return HasReturnvaluesIF::RETURN_OK; - } - } - else if(timeoutMs > MutexIF::POLLING){ - auto chronoMs = std::chrono::milliseconds(timeoutMs); - if(mutex.try_lock_for(chronoMs)) { - locked = true; - return HasReturnvaluesIF::RETURN_OK; - } - } - return MutexIF::MUTEX_TIMEOUT; -} - -ReturnValue_t Mutex::unlockMutex() { - if(not locked) { - return MutexIF::CURR_THREAD_DOES_NOT_OWN_MUTEX; - } - mutex.unlock(); - locked = false; - return HasReturnvaluesIF::RETURN_OK; -} - -std::timed_mutex* Mutex::getMutexHandle() { - return &mutex; -} +#include "../../osal/host/Mutex.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +const uint32_t MutexIF::POLLING = 0; +const uint32_t MutexIF::BLOCKING = 0xffffffff; + +ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { + if(timeoutMs == MutexIF::BLOCKING) { + mutex.lock(); + locked = true; + return HasReturnvaluesIF::RETURN_OK; + } + else if(timeoutMs == MutexIF::POLLING) { + if(mutex.try_lock()) { + locked = true; + return HasReturnvaluesIF::RETURN_OK; + } + } + else if(timeoutMs > MutexIF::POLLING){ + auto chronoMs = std::chrono::milliseconds(timeoutMs); + if(mutex.try_lock_for(chronoMs)) { + locked = true; + return HasReturnvaluesIF::RETURN_OK; + } + } + return MutexIF::MUTEX_TIMEOUT; +} + +ReturnValue_t Mutex::unlockMutex() { + if(not locked) { + return MutexIF::CURR_THREAD_DOES_NOT_OWN_MUTEX; + } + mutex.unlock(); + locked = false; + return HasReturnvaluesIF::RETURN_OK; +} + +std::timed_mutex* Mutex::getMutexHandle() { + return &mutex; +} diff --git a/osal/host/Mutex.h b/osal/host/Mutex.h index 4d49bac7..4461e5f2 100644 --- a/osal/host/Mutex.h +++ b/osal/host/Mutex.h @@ -1,28 +1,28 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_MUTEX_H_ -#define FRAMEWORK_OSAL_FREERTOS_MUTEX_H_ - -#include "../../ipc/MutexIF.h" - -#include - -/** - * @brief OS component to implement MUTual EXclusion - * - * @details - * Mutexes are binary semaphores which include a priority inheritance mechanism. - * Documentation: https://www.freertos.org/Real-time-embedded-RTOS-mutexes.html - * @ingroup osal - */ -class Mutex : public MutexIF { -public: - Mutex() = default; - ReturnValue_t lockMutex(uint32_t timeoutMs = MutexIF::BLOCKING) override; - ReturnValue_t unlockMutex() override; - - std::timed_mutex* getMutexHandle(); -private: - bool locked = false; - std::timed_mutex mutex; -}; - -#endif /* FRAMEWORK_FREERTOS_MUTEX_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_MUTEX_H_ +#define FRAMEWORK_OSAL_FREERTOS_MUTEX_H_ + +#include "../../ipc/MutexIF.h" + +#include + +/** + * @brief OS component to implement MUTual EXclusion + * + * @details + * Mutexes are binary semaphores which include a priority inheritance mechanism. + * Documentation: https://www.freertos.org/Real-time-embedded-RTOS-mutexes.html + * @ingroup osal + */ +class Mutex : public MutexIF { +public: + Mutex() = default; + ReturnValue_t lockMutex(uint32_t timeoutMs = MutexIF::BLOCKING) override; + ReturnValue_t unlockMutex() override; + + std::timed_mutex* getMutexHandle(); +private: + bool locked = false; + std::timed_mutex mutex; +}; + +#endif /* FRAMEWORK_FREERTOS_MUTEX_H_ */ diff --git a/osal/host/MutexFactory.cpp b/osal/host/MutexFactory.cpp index 284ce59f..bf7707d1 100644 --- a/osal/host/MutexFactory.cpp +++ b/osal/host/MutexFactory.cpp @@ -1,28 +1,28 @@ -#include "../../ipc/MutexFactory.h" -#include "../../osal/host/Mutex.h" - -//TODO: Different variant than the lazy loading in QueueFactory. -//What's better and why? -> one is on heap the other on bss/data -//MutexFactory* MutexFactory::factoryInstance = new MutexFactory(); -MutexFactory* MutexFactory::factoryInstance = nullptr; - -MutexFactory::MutexFactory() { -} - -MutexFactory::~MutexFactory() { -} - -MutexFactory* MutexFactory::instance() { - if (factoryInstance == nullptr){ - factoryInstance = new MutexFactory(); - } - return MutexFactory::factoryInstance; -} - -MutexIF* MutexFactory::createMutex() { - return new Mutex(); -} - -void MutexFactory::deleteMutex(MutexIF* mutex) { - delete mutex; -} +#include "../../ipc/MutexFactory.h" +#include "../../osal/host/Mutex.h" + +//TODO: Different variant than the lazy loading in QueueFactory. +//What's better and why? -> one is on heap the other on bss/data +//MutexFactory* MutexFactory::factoryInstance = new MutexFactory(); +MutexFactory* MutexFactory::factoryInstance = nullptr; + +MutexFactory::MutexFactory() { +} + +MutexFactory::~MutexFactory() { +} + +MutexFactory* MutexFactory::instance() { + if (factoryInstance == nullptr){ + factoryInstance = new MutexFactory(); + } + return MutexFactory::factoryInstance; +} + +MutexIF* MutexFactory::createMutex() { + return new Mutex(); +} + +void MutexFactory::deleteMutex(MutexIF* mutex) { + delete mutex; +} diff --git a/osal/host/PeriodicTask.cpp b/osal/host/PeriodicTask.cpp index c4cf9f56..0b5f8bbe 100644 --- a/osal/host/PeriodicTask.cpp +++ b/osal/host/PeriodicTask.cpp @@ -1,176 +1,176 @@ -#include "../../ipc/MutexFactory.h" -#include "../../osal/host/Mutex.h" -#include "../../osal/host/PeriodicTask.h" - -#include "../../serviceinterface/ServiceInterfaceStream.h" -#include "../../tasks/ExecutableObjectIF.h" - -#include -#include - -#if defined(WIN32) -#include -#elif defined(LINUX) -#include -#endif - -PeriodicTask::PeriodicTask(const char *name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod setPeriod, - void (*setDeadlineMissedFunc)()) : - started(false), taskName(name), period(setPeriod), - deadlineMissedFunc(setDeadlineMissedFunc) { - // It is propably possible to set task priorities by using the native - // task handles for Windows / Linux - mainThread = std::thread(&PeriodicTask::taskEntryPoint, this, this); -#if defined(WIN32) - /* List of possible priority classes: - * https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ - * nf-processthreadsapi-setpriorityclass - * And respective thread priority numbers: - * https://docs.microsoft.com/en-us/windows/ - * win32/procthread/scheduling-priorities */ - int result = SetPriorityClass( - reinterpret_cast(mainThread.native_handle()), - ABOVE_NORMAL_PRIORITY_CLASS); - if(result != 0) { - sif::error << "PeriodicTask: Windows SetPriorityClass failed with code " - << GetLastError() << std::endl; - } - result = SetThreadPriority( - reinterpret_cast(mainThread.native_handle()), - THREAD_PRIORITY_NORMAL); - if(result != 0) { - sif::error << "PeriodicTask: Windows SetPriorityClass failed with code " - << GetLastError() << std::endl; - } -#elif defined(LINUX) - // we can just copy and paste the code from linux here. -#endif -} - -PeriodicTask::~PeriodicTask(void) { - //Do not delete objects, we were responsible for ptrs only. - terminateThread = true; - if(mainThread.joinable()) { - mainThread.join(); - } - delete this; -} - -void PeriodicTask::taskEntryPoint(void* argument) { - PeriodicTask *originalTask(reinterpret_cast(argument)); - - - if (not originalTask->started) { - // we have to suspend/block here until the task is started. - // if semaphores are implemented, use them here. - std::unique_lock lock(initMutex); - initCondition.wait(lock); - } - - this->taskFunctionality(); - sif::debug << "PeriodicTask::taskEntryPoint: " - "Returned from taskFunctionality." << std::endl; -} - -ReturnValue_t PeriodicTask::startTask() { - started = true; - - // Notify task to start. - std::lock_guard lock(initMutex); - initCondition.notify_one(); - - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) { - std::this_thread::sleep_for(std::chrono::milliseconds(ms)); - return HasReturnvaluesIF::RETURN_OK; -} - -void PeriodicTask::taskFunctionality() { - std::chrono::milliseconds periodChrono(static_cast(period*1000)); - auto currentStartTime { - std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()) - }; - auto nextStartTime{ currentStartTime }; - - /* Enter the loop that defines the task behavior. */ - for (;;) { - if(terminateThread.load()) { - break; - } - for (ObjectList::iterator it = objectList.begin(); - it != objectList.end(); ++it) { - (*it)->performOperation(); - } - if(not delayForInterval(¤tStartTime, periodChrono)) { - sif::warning << "PeriodicTask: " << taskName << - " missed deadline!\n" << std::flush; - if(deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); - } - } - } -} - -ReturnValue_t PeriodicTask::addComponent(object_id_t object) { - ExecutableObjectIF* newObject = objectManager->get( - object); - if (newObject == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - objectList.push_back(newObject); - return HasReturnvaluesIF::RETURN_OK; -} - -uint32_t PeriodicTask::getPeriodMs() const { - return period * 1000; -} - -bool PeriodicTask::delayForInterval(chron_ms* previousWakeTimeMs, - const chron_ms interval) { - bool shouldDelay = false; - //Get current wakeup time - auto currentStartTime = - std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()); - /* Generate the tick time at which the task wants to wake. */ - auto nextTimeToWake_ms = (*previousWakeTimeMs) + interval; - - if (currentStartTime < *previousWakeTimeMs) { - /* The tick count has overflowed since this function was - lasted called. In this case the only time we should ever - actually delay is if the wake time has also overflowed, - and the wake time is greater than the tick time. When this - is the case it is as if neither time had overflowed. */ - if ((nextTimeToWake_ms < *previousWakeTimeMs) - && (nextTimeToWake_ms > currentStartTime)) { - shouldDelay = true; - } - } else { - /* The tick time has not overflowed. In this case we will - delay if either the wake time has overflowed, and/or the - tick time is less than the wake time. */ - if ((nextTimeToWake_ms < *previousWakeTimeMs) - || (nextTimeToWake_ms > currentStartTime)) { - shouldDelay = true; - } - } - - /* Update the wake time ready for the next call. */ - - (*previousWakeTimeMs) = nextTimeToWake_ms; - - if (shouldDelay) { - auto sleepTime = std::chrono::duration_cast( - nextTimeToWake_ms - currentStartTime); - std::this_thread::sleep_for(sleepTime); - return true; - } - //We are shifting the time in case the deadline was missed like rtems - (*previousWakeTimeMs) = currentStartTime; - return false; - -} +#include "../../ipc/MutexFactory.h" +#include "../../osal/host/Mutex.h" +#include "../../osal/host/PeriodicTask.h" + +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../tasks/ExecutableObjectIF.h" + +#include +#include + +#if defined(WIN32) +#include +#elif defined(LINUX) +#include +#endif + +PeriodicTask::PeriodicTask(const char *name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod setPeriod, + void (*setDeadlineMissedFunc)()) : + started(false), taskName(name), period(setPeriod), + deadlineMissedFunc(setDeadlineMissedFunc) { + // It is propably possible to set task priorities by using the native + // task handles for Windows / Linux + mainThread = std::thread(&PeriodicTask::taskEntryPoint, this, this); +#if defined(WIN32) + /* List of possible priority classes: + * https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ + * nf-processthreadsapi-setpriorityclass + * And respective thread priority numbers: + * https://docs.microsoft.com/en-us/windows/ + * win32/procthread/scheduling-priorities */ + int result = SetPriorityClass( + reinterpret_cast(mainThread.native_handle()), + ABOVE_NORMAL_PRIORITY_CLASS); + if(result != 0) { + sif::error << "PeriodicTask: Windows SetPriorityClass failed with code " + << GetLastError() << std::endl; + } + result = SetThreadPriority( + reinterpret_cast(mainThread.native_handle()), + THREAD_PRIORITY_NORMAL); + if(result != 0) { + sif::error << "PeriodicTask: Windows SetPriorityClass failed with code " + << GetLastError() << std::endl; + } +#elif defined(LINUX) + // we can just copy and paste the code from linux here. +#endif +} + +PeriodicTask::~PeriodicTask(void) { + //Do not delete objects, we were responsible for ptrs only. + terminateThread = true; + if(mainThread.joinable()) { + mainThread.join(); + } + delete this; +} + +void PeriodicTask::taskEntryPoint(void* argument) { + PeriodicTask *originalTask(reinterpret_cast(argument)); + + + if (not originalTask->started) { + // we have to suspend/block here until the task is started. + // if semaphores are implemented, use them here. + std::unique_lock lock(initMutex); + initCondition.wait(lock); + } + + this->taskFunctionality(); + sif::debug << "PeriodicTask::taskEntryPoint: " + "Returned from taskFunctionality." << std::endl; +} + +ReturnValue_t PeriodicTask::startTask() { + started = true; + + // Notify task to start. + std::lock_guard lock(initMutex); + initCondition.notify_one(); + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) { + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); + return HasReturnvaluesIF::RETURN_OK; +} + +void PeriodicTask::taskFunctionality() { + std::chrono::milliseconds periodChrono(static_cast(period*1000)); + auto currentStartTime { + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + }; + auto nextStartTime{ currentStartTime }; + + /* Enter the loop that defines the task behavior. */ + for (;;) { + if(terminateThread.load()) { + break; + } + for (ObjectList::iterator it = objectList.begin(); + it != objectList.end(); ++it) { + (*it)->performOperation(); + } + if(not delayForInterval(¤tStartTime, periodChrono)) { + sif::warning << "PeriodicTask: " << taskName << + " missed deadline!\n" << std::flush; + if(deadlineMissedFunc != nullptr) { + this->deadlineMissedFunc(); + } + } + } +} + +ReturnValue_t PeriodicTask::addComponent(object_id_t object) { + ExecutableObjectIF* newObject = objectManager->get( + object); + if (newObject == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + objectList.push_back(newObject); + return HasReturnvaluesIF::RETURN_OK; +} + +uint32_t PeriodicTask::getPeriodMs() const { + return period * 1000; +} + +bool PeriodicTask::delayForInterval(chron_ms* previousWakeTimeMs, + const chron_ms interval) { + bool shouldDelay = false; + //Get current wakeup time + auto currentStartTime = + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()); + /* Generate the tick time at which the task wants to wake. */ + auto nextTimeToWake_ms = (*previousWakeTimeMs) + interval; + + if (currentStartTime < *previousWakeTimeMs) { + /* The tick count has overflowed since this function was + lasted called. In this case the only time we should ever + actually delay is if the wake time has also overflowed, + and the wake time is greater than the tick time. When this + is the case it is as if neither time had overflowed. */ + if ((nextTimeToWake_ms < *previousWakeTimeMs) + && (nextTimeToWake_ms > currentStartTime)) { + shouldDelay = true; + } + } else { + /* The tick time has not overflowed. In this case we will + delay if either the wake time has overflowed, and/or the + tick time is less than the wake time. */ + if ((nextTimeToWake_ms < *previousWakeTimeMs) + || (nextTimeToWake_ms > currentStartTime)) { + shouldDelay = true; + } + } + + /* Update the wake time ready for the next call. */ + + (*previousWakeTimeMs) = nextTimeToWake_ms; + + if (shouldDelay) { + auto sleepTime = std::chrono::duration_cast( + nextTimeToWake_ms - currentStartTime); + std::this_thread::sleep_for(sleepTime); + return true; + } + //We are shifting the time in case the deadline was missed like rtems + (*previousWakeTimeMs) = currentStartTime; + return false; + +} diff --git a/osal/host/PeriodicTask.h b/osal/host/PeriodicTask.h index 7eb768cb..7689788a 100644 --- a/osal/host/PeriodicTask.h +++ b/osal/host/PeriodicTask.h @@ -1,123 +1,123 @@ -#ifndef FRAMEWORK_OSAL_HOST_PERIODICTASK_H_ -#define FRAMEWORK_OSAL_HOST_PERIODICTASK_H_ - -#include "../../objectmanager/ObjectManagerIF.h" -#include "../../tasks/PeriodicTaskIF.h" -#include "../../tasks/Typedef.h" - -#include -#include -#include -#include - -class ExecutableObjectIF; - -/** - * @brief This class represents a specialized task for - * periodic activities of multiple objects. - * @details - * - * @ingroup task_handling - */ -class PeriodicTask: public PeriodicTaskIF { -public: - /** - * @brief Standard constructor of the class. - * @details - * The class is initialized without allocated objects. These need to be - * added with #addComponent. - * @param priority - * @param stack_size - * @param setPeriod - * @param setDeadlineMissedFunc - * The function pointer to the deadline missed function that shall be - * assigned. - */ - PeriodicTask(const char *name, TaskPriority setPriority, TaskStackSize setStack, - TaskPeriod setPeriod,void (*setDeadlineMissedFunc)()); - /** - * @brief Currently, the executed object's lifetime is not coupled with - * the task object's lifetime, so the destructor is empty. - */ - virtual ~PeriodicTask(void); - - /** - * @brief The method to start the task. - * @details The method starts the task with the respective system call. - * Entry point is the taskEntryPoint method described below. - * The address of the task object is passed as an argument - * to the system call. - */ - ReturnValue_t startTask(void); - /** - * Adds an object to the list of objects to be executed. - * The objects are executed in the order added. - * @param object Id of the object to add. - * @return - * -@c RETURN_OK on success - * -@c RETURN_FAILED if the object could not be added. - */ - ReturnValue_t addComponent(object_id_t object); - - uint32_t getPeriodMs() const; - - ReturnValue_t sleepFor(uint32_t ms); - -protected: - using chron_ms = std::chrono::milliseconds; - bool started; - //!< Typedef for the List of objects. - typedef std::vector ObjectList; - std::thread mainThread; - std::atomic terminateThread = false; - - /** - * @brief This attribute holds a list of objects to be executed. - */ - ObjectList objectList; - - std::condition_variable initCondition; - std::mutex initMutex; - std::string taskName; - /** - * @brief The period of the task. - * @details - * The period determines the frequency of the task's execution. - * It is expressed in clock ticks. - */ - TaskPeriod period; - /** - * @brief The pointer to the deadline-missed function. - * @details - * This pointer stores the function that is executed if the task's deadline - * is missed. So, each may react individually on a timing failure. - * The pointer may be NULL, then nothing happens on missing the deadline. - * The deadline is equal to the next execution of the periodic task. - */ - void (*deadlineMissedFunc)(void); - /** - * @brief This is the function executed in the new task's context. - * @details - * It converts the argument back to the thread object type and copies the - * class instance to the task context. - * The taskFunctionality method is called afterwards. - * @param A pointer to the task object itself is passed as argument. - */ - - void taskEntryPoint(void* argument); - /** - * @brief The function containing the actual functionality of the task. - * @details - * The method sets and starts the task's period, then enters a loop that is - * repeated as long as the isRunning attribute is true. Within the loop, - * all performOperation methods of the added objects are called. Afterwards - * the checkAndRestartPeriod system call blocks the task until the next - * period. On missing the deadline, the deadlineMissedFunction is executed. - */ - void taskFunctionality(void); - - bool delayForInterval(chron_ms * previousWakeTimeMs, - const chron_ms interval); -}; - -#endif /* PERIODICTASK_H_ */ +#ifndef FRAMEWORK_OSAL_HOST_PERIODICTASK_H_ +#define FRAMEWORK_OSAL_HOST_PERIODICTASK_H_ + +#include "../../objectmanager/ObjectManagerIF.h" +#include "../../tasks/PeriodicTaskIF.h" +#include "../../tasks/Typedef.h" + +#include +#include +#include +#include + +class ExecutableObjectIF; + +/** + * @brief This class represents a specialized task for + * periodic activities of multiple objects. + * @details + * + * @ingroup task_handling + */ +class PeriodicTask: public PeriodicTaskIF { +public: + /** + * @brief Standard constructor of the class. + * @details + * The class is initialized without allocated objects. These need to be + * added with #addComponent. + * @param priority + * @param stack_size + * @param setPeriod + * @param setDeadlineMissedFunc + * The function pointer to the deadline missed function that shall be + * assigned. + */ + PeriodicTask(const char *name, TaskPriority setPriority, TaskStackSize setStack, + TaskPeriod setPeriod,void (*setDeadlineMissedFunc)()); + /** + * @brief Currently, the executed object's lifetime is not coupled with + * the task object's lifetime, so the destructor is empty. + */ + virtual ~PeriodicTask(void); + + /** + * @brief The method to start the task. + * @details The method starts the task with the respective system call. + * Entry point is the taskEntryPoint method described below. + * The address of the task object is passed as an argument + * to the system call. + */ + ReturnValue_t startTask(void); + /** + * Adds an object to the list of objects to be executed. + * The objects are executed in the order added. + * @param object Id of the object to add. + * @return + * -@c RETURN_OK on success + * -@c RETURN_FAILED if the object could not be added. + */ + ReturnValue_t addComponent(object_id_t object); + + uint32_t getPeriodMs() const; + + ReturnValue_t sleepFor(uint32_t ms); + +protected: + using chron_ms = std::chrono::milliseconds; + bool started; + //!< Typedef for the List of objects. + typedef std::vector ObjectList; + std::thread mainThread; + std::atomic terminateThread = false; + + /** + * @brief This attribute holds a list of objects to be executed. + */ + ObjectList objectList; + + std::condition_variable initCondition; + std::mutex initMutex; + std::string taskName; + /** + * @brief The period of the task. + * @details + * The period determines the frequency of the task's execution. + * It is expressed in clock ticks. + */ + TaskPeriod period; + /** + * @brief The pointer to the deadline-missed function. + * @details + * This pointer stores the function that is executed if the task's deadline + * is missed. So, each may react individually on a timing failure. + * The pointer may be NULL, then nothing happens on missing the deadline. + * The deadline is equal to the next execution of the periodic task. + */ + void (*deadlineMissedFunc)(void); + /** + * @brief This is the function executed in the new task's context. + * @details + * It converts the argument back to the thread object type and copies the + * class instance to the task context. + * The taskFunctionality method is called afterwards. + * @param A pointer to the task object itself is passed as argument. + */ + + void taskEntryPoint(void* argument); + /** + * @brief The function containing the actual functionality of the task. + * @details + * The method sets and starts the task's period, then enters a loop that is + * repeated as long as the isRunning attribute is true. Within the loop, + * all performOperation methods of the added objects are called. Afterwards + * the checkAndRestartPeriod system call blocks the task until the next + * period. On missing the deadline, the deadlineMissedFunction is executed. + */ + void taskFunctionality(void); + + bool delayForInterval(chron_ms * previousWakeTimeMs, + const chron_ms interval); +}; + +#endif /* PERIODICTASK_H_ */ diff --git a/osal/host/QueueFactory.cpp b/osal/host/QueueFactory.cpp index 052671ca..da3fea55 100644 --- a/osal/host/QueueFactory.cpp +++ b/osal/host/QueueFactory.cpp @@ -1,41 +1,41 @@ -#include "../../ipc/QueueFactory.h" -#include "../../osal/host/MessageQueue.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" -#include - -QueueFactory* QueueFactory::factoryInstance = nullptr; - - -ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessageIF* message, MessageQueueId_t sentFrom, - bool ignoreFault) { - return MessageQueue::sendMessageFromMessageQueue(sendTo,message, - sentFrom,ignoreFault); - return HasReturnvaluesIF::RETURN_OK; -} - -QueueFactory* QueueFactory::instance() { - if (factoryInstance == nullptr) { - factoryInstance = new QueueFactory; - } - return factoryInstance; -} - -QueueFactory::QueueFactory() { -} - -QueueFactory::~QueueFactory() { -} - -MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, - size_t maxMessageSize) { - // A thread-safe queue can be implemented by using a combination - // of std::queue and std::mutex. This uses dynamic memory allocation - // which could be alleviated by using a custom allocator, external library - // (etl::queue) or simply using std::queue, we're on a host machine anyway. - return new MessageQueue(messageDepth, maxMessageSize); -} - -void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { - delete queue; -} +#include "../../ipc/QueueFactory.h" +#include "../../osal/host/MessageQueue.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include + +QueueFactory* QueueFactory::factoryInstance = nullptr; + + +ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + return MessageQueue::sendMessageFromMessageQueue(sendTo,message, + sentFrom,ignoreFault); + return HasReturnvaluesIF::RETURN_OK; +} + +QueueFactory* QueueFactory::instance() { + if (factoryInstance == nullptr) { + factoryInstance = new QueueFactory; + } + return factoryInstance; +} + +QueueFactory::QueueFactory() { +} + +QueueFactory::~QueueFactory() { +} + +MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, + size_t maxMessageSize) { + // A thread-safe queue can be implemented by using a combination + // of std::queue and std::mutex. This uses dynamic memory allocation + // which could be alleviated by using a custom allocator, external library + // (etl::queue) or simply using std::queue, we're on a host machine anyway. + return new MessageQueue(messageDepth, maxMessageSize); +} + +void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { + delete queue; +} diff --git a/osal/host/QueueMapManager.cpp b/osal/host/QueueMapManager.cpp index 35db204e..47687bc1 100644 --- a/osal/host/QueueMapManager.cpp +++ b/osal/host/QueueMapManager.cpp @@ -1,51 +1,51 @@ -#include "../../ipc/MutexFactory.h" -#include "../../ipc/MutexHelper.h" -#include "../../osal/host/QueueMapManager.h" - -QueueMapManager* QueueMapManager::mqManagerInstance = nullptr; - -QueueMapManager::QueueMapManager() { - mapLock = MutexFactory::instance()->createMutex(); -} - -QueueMapManager* QueueMapManager::instance() { - if (mqManagerInstance == nullptr){ - mqManagerInstance = new QueueMapManager(); - } - return QueueMapManager::mqManagerInstance; -} - -ReturnValue_t QueueMapManager::addMessageQueue( - MessageQueueIF* queueToInsert, MessageQueueId_t* id) { - // Not thread-safe, but it is assumed all message queues are created - // at software initialization now. If this is to be made thread-safe in - // the future, it propably would be sufficient to lock the increment - // operation here - uint32_t currentId = queueCounter++; - auto returnPair = queueMap.emplace(currentId, queueToInsert); - if(not returnPair.second) { - // this should never happen for the atomic variable. - sif::error << "QueueMapManager: This ID is already inside the map!" - << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - if (id != nullptr) { - *id = currentId; - } - return HasReturnvaluesIF::RETURN_OK; -} - -MessageQueueIF* QueueMapManager::getMessageQueue( - MessageQueueId_t messageQueueId) const { - MutexHelper(mapLock, 50); - auto queueIter = queueMap.find(messageQueueId); - if(queueIter != queueMap.end()) { - return queueIter->second; - } - else { - sif::warning << "QueueMapManager::getQueueHandle: The ID" << - messageQueueId << " does not exists in the map" << std::endl; - return nullptr; - } -} - +#include "../../ipc/MutexFactory.h" +#include "../../ipc/MutexHelper.h" +#include "../../osal/host/QueueMapManager.h" + +QueueMapManager* QueueMapManager::mqManagerInstance = nullptr; + +QueueMapManager::QueueMapManager() { + mapLock = MutexFactory::instance()->createMutex(); +} + +QueueMapManager* QueueMapManager::instance() { + if (mqManagerInstance == nullptr){ + mqManagerInstance = new QueueMapManager(); + } + return QueueMapManager::mqManagerInstance; +} + +ReturnValue_t QueueMapManager::addMessageQueue( + MessageQueueIF* queueToInsert, MessageQueueId_t* id) { + // Not thread-safe, but it is assumed all message queues are created + // at software initialization now. If this is to be made thread-safe in + // the future, it propably would be sufficient to lock the increment + // operation here + uint32_t currentId = queueCounter++; + auto returnPair = queueMap.emplace(currentId, queueToInsert); + if(not returnPair.second) { + // this should never happen for the atomic variable. + sif::error << "QueueMapManager: This ID is already inside the map!" + << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if (id != nullptr) { + *id = currentId; + } + return HasReturnvaluesIF::RETURN_OK; +} + +MessageQueueIF* QueueMapManager::getMessageQueue( + MessageQueueId_t messageQueueId) const { + MutexHelper(mapLock, 50); + auto queueIter = queueMap.find(messageQueueId); + if(queueIter != queueMap.end()) { + return queueIter->second; + } + else { + sif::warning << "QueueMapManager::getQueueHandle: The ID" << + messageQueueId << " does not exists in the map" << std::endl; + return nullptr; + } +} + diff --git a/osal/host/QueueMapManager.h b/osal/host/QueueMapManager.h index acf20389..823fd4c2 100644 --- a/osal/host/QueueMapManager.h +++ b/osal/host/QueueMapManager.h @@ -1,47 +1,47 @@ -#ifndef FRAMEWORK_OSAL_HOST_QUEUEMAP_H_ -#define FRAMEWORK_OSAL_HOST_QUEUEMAP_H_ - -#include "../../ipc/MessageQueueSenderIF.h" -#include "../../osal/host/MessageQueue.h" -#include -#include - -using QueueMap = std::unordered_map; - - -/** - * An internal map to map message queue IDs to message queues. - * This propably should be a singleton.. - */ -class QueueMapManager { -public: - //! Returns the single instance of SemaphoreFactory. - static QueueMapManager* instance(); - - /** - * Insert a message queue into the map and returns a message queue ID - * @param queue The message queue to insert. - * @param id The passed value will be set unless a nullptr is passed - * @return - */ - ReturnValue_t addMessageQueue(MessageQueueIF* queue, MessageQueueId_t* - id = nullptr); - /** - * Get the message queue handle by providing a message queue ID. - * @param messageQueueId - * @return - */ - MessageQueueIF* getMessageQueue(MessageQueueId_t messageQueueId) const; - -private: - //! External instantiation is forbidden. - QueueMapManager(); - uint32_t queueCounter = 1; - MutexIF* mapLock; - QueueMap queueMap; - static QueueMapManager* mqManagerInstance; -}; - - - -#endif /* FRAMEWORK_OSAL_HOST_QUEUEMAP_H_ */ +#ifndef FRAMEWORK_OSAL_HOST_QUEUEMAP_H_ +#define FRAMEWORK_OSAL_HOST_QUEUEMAP_H_ + +#include "../../ipc/MessageQueueSenderIF.h" +#include "../../osal/host/MessageQueue.h" +#include +#include + +using QueueMap = std::unordered_map; + + +/** + * An internal map to map message queue IDs to message queues. + * This propably should be a singleton.. + */ +class QueueMapManager { +public: + //! Returns the single instance of SemaphoreFactory. + static QueueMapManager* instance(); + + /** + * Insert a message queue into the map and returns a message queue ID + * @param queue The message queue to insert. + * @param id The passed value will be set unless a nullptr is passed + * @return + */ + ReturnValue_t addMessageQueue(MessageQueueIF* queue, MessageQueueId_t* + id = nullptr); + /** + * Get the message queue handle by providing a message queue ID. + * @param messageQueueId + * @return + */ + MessageQueueIF* getMessageQueue(MessageQueueId_t messageQueueId) const; + +private: + //! External instantiation is forbidden. + QueueMapManager(); + uint32_t queueCounter = 1; + MutexIF* mapLock; + QueueMap queueMap; + static QueueMapManager* mqManagerInstance; +}; + + + +#endif /* FRAMEWORK_OSAL_HOST_QUEUEMAP_H_ */ diff --git a/osal/host/SemaphoreFactory.cpp b/osal/host/SemaphoreFactory.cpp index 58040428..c354c47c 100644 --- a/osal/host/SemaphoreFactory.cpp +++ b/osal/host/SemaphoreFactory.cpp @@ -1,42 +1,42 @@ -#include "../../tasks/SemaphoreFactory.h" -#include "../../osal/linux/BinarySemaphore.h" -#include "../../osal/linux/CountingSemaphore.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" - -const uint32_t SemaphoreIF::POLLING = 0; -const uint32_t SemaphoreIF::BLOCKING = 0xFFFFFFFF; - -SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; - -SemaphoreFactory::SemaphoreFactory() { -} - -SemaphoreFactory::~SemaphoreFactory() { - delete factoryInstance; -} - -SemaphoreFactory* SemaphoreFactory::instance() { - if (factoryInstance == nullptr){ - factoryInstance = new SemaphoreFactory(); - } - return SemaphoreFactory::factoryInstance; -} - -SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t arguments) { - // Just gonna wait for full C++20 for now. - sif::error << "SemaphoreFactory: Binary Semaphore not implemented yet." - " Returning nullptr!\n" << std::flush; - return nullptr; -} - -SemaphoreIF* SemaphoreFactory::createCountingSemaphore(const uint8_t maxCount, - uint8_t initCount, uint32_t arguments) { - // Just gonna wait for full C++20 for now. - sif::error << "SemaphoreFactory: Counting Semaphore not implemented yet." - " Returning nullptr!\n" << std::flush; - return nullptr; -} - -void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { - delete semaphore; -} +#include "../../tasks/SemaphoreFactory.h" +#include "../../osal/linux/BinarySemaphore.h" +#include "../../osal/linux/CountingSemaphore.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +const uint32_t SemaphoreIF::POLLING = 0; +const uint32_t SemaphoreIF::BLOCKING = 0xFFFFFFFF; + +SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; + +SemaphoreFactory::SemaphoreFactory() { +} + +SemaphoreFactory::~SemaphoreFactory() { + delete factoryInstance; +} + +SemaphoreFactory* SemaphoreFactory::instance() { + if (factoryInstance == nullptr){ + factoryInstance = new SemaphoreFactory(); + } + return SemaphoreFactory::factoryInstance; +} + +SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t arguments) { + // Just gonna wait for full C++20 for now. + sif::error << "SemaphoreFactory: Binary Semaphore not implemented yet." + " Returning nullptr!\n" << std::flush; + return nullptr; +} + +SemaphoreIF* SemaphoreFactory::createCountingSemaphore(const uint8_t maxCount, + uint8_t initCount, uint32_t arguments) { + // Just gonna wait for full C++20 for now. + sif::error << "SemaphoreFactory: Counting Semaphore not implemented yet." + " Returning nullptr!\n" << std::flush; + return nullptr; +} + +void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { + delete semaphore; +} diff --git a/osal/host/TaskFactory.cpp b/osal/host/TaskFactory.cpp index 3f527130..37df981a 100644 --- a/osal/host/TaskFactory.cpp +++ b/osal/host/TaskFactory.cpp @@ -1,55 +1,55 @@ -#include "../../osal/host/FixedTimeslotTask.h" -#include "../../osal/host/PeriodicTask.h" -#include "../../tasks/TaskFactory.h" -#include "../../returnvalues/HasReturnvaluesIF.h" -#include "../../tasks/PeriodicTaskIF.h" - -#include - -TaskFactory* TaskFactory::factoryInstance = new TaskFactory(); - -// Will propably not be used for hosted implementation -const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = 0; - -TaskFactory::TaskFactory() { -} - -TaskFactory::~TaskFactory() { -} - -TaskFactory* TaskFactory::instance() { - return TaskFactory::factoryInstance; -} - -PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, - TaskPriority taskPriority_,TaskStackSize stackSize_, - TaskPeriod periodInSeconds_, - TaskDeadlineMissedFunction deadLineMissedFunction_) { - // This is going to be interesting. Time now learn the C++ threading library - // :-) - return new PeriodicTask(name_, taskPriority_, stackSize_, periodInSeconds_, - deadLineMissedFunction_); -} - -FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_, - TaskPriority taskPriority_,TaskStackSize stackSize_, - TaskPeriod periodInSeconds_, - TaskDeadlineMissedFunction deadLineMissedFunction_) { - // This is going to be interesting. Time now learn the C++ threading library - // :-) - return new FixedTimeslotTask(name_, taskPriority_, stackSize_, - periodInSeconds_, deadLineMissedFunction_); -} - -ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) { - // This might block for some time! - delete task; - return HasReturnvaluesIF::RETURN_FAILED; -} - -ReturnValue_t TaskFactory::delayTask(uint32_t delayMs){ - std::this_thread::sleep_for(std::chrono::milliseconds(delayMs)); - return HasReturnvaluesIF::RETURN_OK; -} - - +#include "../../osal/host/FixedTimeslotTask.h" +#include "../../osal/host/PeriodicTask.h" +#include "../../tasks/TaskFactory.h" +#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../tasks/PeriodicTaskIF.h" + +#include + +TaskFactory* TaskFactory::factoryInstance = new TaskFactory(); + +// Will propably not be used for hosted implementation +const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = 0; + +TaskFactory::TaskFactory() { +} + +TaskFactory::~TaskFactory() { +} + +TaskFactory* TaskFactory::instance() { + return TaskFactory::factoryInstance; +} + +PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, + TaskPriority taskPriority_,TaskStackSize stackSize_, + TaskPeriod periodInSeconds_, + TaskDeadlineMissedFunction deadLineMissedFunction_) { + // This is going to be interesting. Time now learn the C++ threading library + // :-) + return new PeriodicTask(name_, taskPriority_, stackSize_, periodInSeconds_, + deadLineMissedFunction_); +} + +FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_, + TaskPriority taskPriority_,TaskStackSize stackSize_, + TaskPeriod periodInSeconds_, + TaskDeadlineMissedFunction deadLineMissedFunction_) { + // This is going to be interesting. Time now learn the C++ threading library + // :-) + return new FixedTimeslotTask(name_, taskPriority_, stackSize_, + periodInSeconds_, deadLineMissedFunction_); +} + +ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) { + // This might block for some time! + delete task; + return HasReturnvaluesIF::RETURN_FAILED; +} + +ReturnValue_t TaskFactory::delayTask(uint32_t delayMs){ + std::this_thread::sleep_for(std::chrono::milliseconds(delayMs)); + return HasReturnvaluesIF::RETURN_OK; +} + + From 902cd4d2101368140df6df6424b0eeb50a99faf8 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 5 Sep 2020 21:19:53 +0200 Subject: [PATCH 313/653] host osal update --- osal/host/FixedTimeslotTask.cpp | 14 ++++++++++---- osal/host/FixedTimeslotTask.h | 2 +- osal/host/MessageQueue.cpp | 18 +++++++++++------- osal/host/MessageQueue.h | 3 ++- osal/host/Mutex.cpp | 7 +++---- osal/host/Mutex.h | 11 ++++++----- osal/host/PeriodicTask.cpp | 6 +++--- osal/host/QueueMapManager.cpp | 5 +++-- osal/host/QueueMapManager.h | 6 +++--- osal/host/SemaphoreFactory.cpp | 3 --- osal/host/TaskFactory.cpp | 4 ---- 11 files changed, 42 insertions(+), 37 deletions(-) diff --git a/osal/host/FixedTimeslotTask.cpp b/osal/host/FixedTimeslotTask.cpp index 1139badb..e78c974a 100644 --- a/osal/host/FixedTimeslotTask.cpp +++ b/osal/host/FixedTimeslotTask.cpp @@ -90,9 +90,12 @@ ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { } void FixedTimeslotTask::taskFunctionality() { + pollingSeqTable.intializeSequenceAfterTaskCreation(); + // A local iterator for the Polling Sequence Table is created to // find the start time for the first entry. - FixedSlotSequence::SlotListIter slotListIter = pollingSeqTable.current; + auto slotListIter = pollingSeqTable.current; + // Get start time for first entry. chron_ms interval(slotListIter->pollingTimeMs); auto currentStartTime { @@ -122,8 +125,11 @@ void FixedTimeslotTask::taskFunctionality() { ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep) { - if (objectManager->get(componentId) != nullptr) { - pollingSeqTable.addSlot(componentId, slotTimeMs, executionStep, this); + ExecutableObjectIF* executableObject = objectManager-> + get(componentId); + if (executableObject != nullptr) { + pollingSeqTable.addSlot(componentId, slotTimeMs, executionStep, + executableObject, this); return HasReturnvaluesIF::RETURN_OK; } @@ -132,7 +138,7 @@ ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, return HasReturnvaluesIF::RETURN_FAILED; } -ReturnValue_t FixedTimeslotTask::checkAndInitializeSequence() const { +ReturnValue_t FixedTimeslotTask::checkSequence() const { return pollingSeqTable.checkSequence(); } diff --git a/osal/host/FixedTimeslotTask.h b/osal/host/FixedTimeslotTask.h index 3ea97b97..9985e2ee 100644 --- a/osal/host/FixedTimeslotTask.h +++ b/osal/host/FixedTimeslotTask.h @@ -61,7 +61,7 @@ public: ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep); - ReturnValue_t checkAndInitializeSequence() const; + ReturnValue_t checkSequence() const override; uint32_t getPeriodMs() const; diff --git a/osal/host/MessageQueue.cpp b/osal/host/MessageQueue.cpp index 8a34282c..bced3713 100644 --- a/osal/host/MessageQueue.cpp +++ b/osal/host/MessageQueue.cpp @@ -1,6 +1,7 @@ -#include "../../osal/host/MessageQueue.h" +#include "MessageQueue.h" +#include "QueueMapManager.h" + #include "../../serviceinterface/ServiceInterfaceStream.h" -#include "../../osal/host/QueueMapManager.h" #include "../../ipc/MutexFactory.h" #include "../../ipc/MutexHelper.h" @@ -9,7 +10,8 @@ MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize): queueLock = MutexFactory::instance()->createMutex(); auto result = QueueMapManager::instance()->addMessageQueue(this, &mqId); if(result != HasReturnvaluesIF::RETURN_OK) { - sif::error << "MessageQueue: Could not be created" << std::endl; + sif::error << "MessageQueue::MessageQueue:" + << " Could not be created" << std::endl; } } @@ -61,7 +63,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { } // not sure this will work.. //*message = std::move(messageQueue.front()); - MutexHelper mutexLock(queueLock, 20); + MutexHelper mutexLock(queueLock, MutexIF::TimeoutType::WAITING, 20); MessageQueueMessage* currentMessage = &messageQueue.front(); std::copy(currentMessage->getBuffer(), currentMessage->getBuffer() + messageSize, message->getBuffer()); @@ -126,7 +128,8 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, } if(targetQueue->messageQueue.size() < targetQueue->messageDepth) { - MutexHelper mutexLock(targetQueue->queueLock, 20); + MutexHelper mutexLock(targetQueue->queueLock, + MutexIF::TimeoutType::WAITING, 20); // not ideal, works for now though. MessageQueueMessage* mqmMessage = dynamic_cast(message); @@ -146,8 +149,9 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t MessageQueue::lockQueue(dur_millis_t lockTimeout) { - return queueLock->lockMutex(lockTimeout); +ReturnValue_t MessageQueue::lockQueue(MutexIF::TimeoutType timeoutType, + dur_millis_t lockTimeout) { + return queueLock->lockMutex(timeoutType, lockTimeout); } ReturnValue_t MessageQueue::unlockQueue() { diff --git a/osal/host/MessageQueue.h b/osal/host/MessageQueue.h index 21a01663..97a9e491 100644 --- a/osal/host/MessageQueue.h +++ b/osal/host/MessageQueue.h @@ -182,7 +182,8 @@ public: bool isDefaultDestinationSet() const override; - ReturnValue_t lockQueue(dur_millis_t lockTimeout); + ReturnValue_t lockQueue(MutexIF::TimeoutType timeoutType, + dur_millis_t lockTimeout); ReturnValue_t unlockQueue(); protected: /** diff --git a/osal/host/Mutex.cpp b/osal/host/Mutex.cpp index 2718f2b9..8471cab8 100644 --- a/osal/host/Mutex.cpp +++ b/osal/host/Mutex.cpp @@ -1,10 +1,9 @@ -#include "../../osal/host/Mutex.h" +#include "Mutex.h" #include "../../serviceinterface/ServiceInterfaceStream.h" -const uint32_t MutexIF::POLLING = 0; -const uint32_t MutexIF::BLOCKING = 0xffffffff; +Mutex::Mutex() {} -ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { +ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType, uint32_t timeoutMs) { if(timeoutMs == MutexIF::BLOCKING) { mutex.lock(); locked = true; diff --git a/osal/host/Mutex.h b/osal/host/Mutex.h index 4461e5f2..24dafbbd 100644 --- a/osal/host/Mutex.h +++ b/osal/host/Mutex.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_MUTEX_H_ -#define FRAMEWORK_OSAL_FREERTOS_MUTEX_H_ +#ifndef FSFW_OSAL_HOSTED_MUTEX_H_ +#define FSFW_OSAL_HOSTED_MUTEX_H_ #include "../../ipc/MutexIF.h" @@ -15,8 +15,9 @@ */ class Mutex : public MutexIF { public: - Mutex() = default; - ReturnValue_t lockMutex(uint32_t timeoutMs = MutexIF::BLOCKING) override; + Mutex(); + ReturnValue_t lockMutex(TimeoutType timeoutType = + TimeoutType::BLOCKING, uint32_t timeoutMs = 0) override; ReturnValue_t unlockMutex() override; std::timed_mutex* getMutexHandle(); @@ -25,4 +26,4 @@ private: std::timed_mutex mutex; }; -#endif /* FRAMEWORK_FREERTOS_MUTEX_H_ */ +#endif /* FSFW_OSAL_HOSTED_MUTEX_H_ */ diff --git a/osal/host/PeriodicTask.cpp b/osal/host/PeriodicTask.cpp index 0b5f8bbe..f4ee079b 100644 --- a/osal/host/PeriodicTask.cpp +++ b/osal/host/PeriodicTask.cpp @@ -1,7 +1,7 @@ -#include "../../ipc/MutexFactory.h" -#include "../../osal/host/Mutex.h" -#include "../../osal/host/PeriodicTask.h" +#include "Mutex.h" +#include "PeriodicTask.h" +#include "../../ipc/MutexFactory.h" #include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../tasks/ExecutableObjectIF.h" diff --git a/osal/host/QueueMapManager.cpp b/osal/host/QueueMapManager.cpp index 47687bc1..1b2094e9 100644 --- a/osal/host/QueueMapManager.cpp +++ b/osal/host/QueueMapManager.cpp @@ -1,6 +1,7 @@ +#include "QueueMapManager.h" + #include "../../ipc/MutexFactory.h" #include "../../ipc/MutexHelper.h" -#include "../../osal/host/QueueMapManager.h" QueueMapManager* QueueMapManager::mqManagerInstance = nullptr; @@ -37,7 +38,7 @@ ReturnValue_t QueueMapManager::addMessageQueue( MessageQueueIF* QueueMapManager::getMessageQueue( MessageQueueId_t messageQueueId) const { - MutexHelper(mapLock, 50); + MutexHelper(mapLock, MutexIF::TimeoutType::WAITING, 50); auto queueIter = queueMap.find(messageQueueId); if(queueIter != queueMap.end()) { return queueIter->second; diff --git a/osal/host/QueueMapManager.h b/osal/host/QueueMapManager.h index 823fd4c2..d7d5c915 100644 --- a/osal/host/QueueMapManager.h +++ b/osal/host/QueueMapManager.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_OSAL_HOST_QUEUEMAP_H_ -#define FRAMEWORK_OSAL_HOST_QUEUEMAP_H_ +#ifndef FSFW_OSAL_HOST_QUEUEMAPMANAGER_H_ +#define FSFW_OSAL_HOST_QUEUEMAPMANAGER_H_ #include "../../ipc/MessageQueueSenderIF.h" #include "../../osal/host/MessageQueue.h" @@ -44,4 +44,4 @@ private: -#endif /* FRAMEWORK_OSAL_HOST_QUEUEMAP_H_ */ +#endif /* FSFW_OSAL_HOST_QUEUEMAPMANAGER_H_ */ diff --git a/osal/host/SemaphoreFactory.cpp b/osal/host/SemaphoreFactory.cpp index c354c47c..b19b2c75 100644 --- a/osal/host/SemaphoreFactory.cpp +++ b/osal/host/SemaphoreFactory.cpp @@ -3,9 +3,6 @@ #include "../../osal/linux/CountingSemaphore.h" #include "../../serviceinterface/ServiceInterfaceStream.h" -const uint32_t SemaphoreIF::POLLING = 0; -const uint32_t SemaphoreIF::BLOCKING = 0xFFFFFFFF; - SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; SemaphoreFactory::SemaphoreFactory() { diff --git a/osal/host/TaskFactory.cpp b/osal/host/TaskFactory.cpp index 37df981a..bc65504c 100644 --- a/osal/host/TaskFactory.cpp +++ b/osal/host/TaskFactory.cpp @@ -25,8 +25,6 @@ PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, TaskPriority taskPriority_,TaskStackSize stackSize_, TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) { - // This is going to be interesting. Time now learn the C++ threading library - // :-) return new PeriodicTask(name_, taskPriority_, stackSize_, periodInSeconds_, deadLineMissedFunction_); } @@ -35,8 +33,6 @@ FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_, TaskPriority taskPriority_,TaskStackSize stackSize_, TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) { - // This is going to be interesting. Time now learn the C++ threading library - // :-) return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_, deadLineMissedFunction_); } From f7223abaa39a1ac10107f91cd16f18e40932d3fd Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 5 Sep 2020 21:20:10 +0200 Subject: [PATCH 314/653] added define necessary for minGW --- timemanager/CCSDSTime.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/timemanager/CCSDSTime.cpp b/timemanager/CCSDSTime.cpp index a5a38e27..12ecf34a 100644 --- a/timemanager/CCSDSTime.cpp +++ b/timemanager/CCSDSTime.cpp @@ -1,8 +1,12 @@ -#include "CCSDSTime.h" +#include "../timemanager/CCSDSTime.h" #include #include #include +#ifndef SCNu8 + #define SCNu8 "hhu" +#endif + CCSDSTime::CCSDSTime() { } From 234fbcbf417d201922e13e98c0a6fe7bda37a967 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 6 Sep 2020 09:34:06 +0200 Subject: [PATCH 315/653] small bugfix in error checking --- osal/linux/TmTcUnixUdpBridge.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osal/linux/TmTcUnixUdpBridge.cpp b/osal/linux/TmTcUnixUdpBridge.cpp index 46b26254..80d02b25 100644 --- a/osal/linux/TmTcUnixUdpBridge.cpp +++ b/osal/linux/TmTcUnixUdpBridge.cpp @@ -24,7 +24,7 @@ TmTcUnixUdpBridge::TmTcUnixUdpBridge(object_id_t objectId, // Set up UDP socket: https://man7.org/linux/man-pages/man7/ip.7.html //clientSocket = socket(AF_INET, SOCK_DGRAM, 0); serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if(socket < 0) { + if(serverSocket < 0) { sif::error << "TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not open" " UDP socket!" << std::endl; handleSocketError(); From e9b86e51df95c5880ace312ed978933f98abde68 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 6 Sep 2020 15:23:38 +0200 Subject: [PATCH 316/653] init commit --- datapool/ControllerSet.h | 15 - datapool/DataPool.cpp | 131 -------- datapool/DataPool.h | 135 -------- datapool/DataSet.cpp | 150 --------- datapool/DataSet.h | 159 ---------- datapool/DataSetIF.h | 56 ++-- datapool/HkSwitchHelper.cpp | 13 +- datapool/PoolDataSetBase.cpp | 169 ++++++++++ datapool/PoolDataSetBase.h | 152 +++++++++ datapool/PoolDataSetIF.h | 33 ++ datapool/PoolEntry.cpp | 1 + datapool/PoolEntry.h | 6 +- datapool/PoolEntryIF.h | 6 +- datapool/PoolRawAccess.cpp | 187 ----------- datapool/PoolRawAccess.h | 152 --------- datapool/PoolVarList.h | 17 +- datapool/PoolVariable.h | 295 ------------------ datapool/PoolVariableIF.h | 114 ++++--- datapool/PoolVector.h | 233 -------------- datapool/SharedDataSetIF.h | 14 + {datapool => datapoolglob}/ControllerSet.cpp | 2 +- datapoolglob/ControllerSet.h | 15 + {datapool => datapoolglob}/DataPoolAdmin.cpp | 25 +- {datapool => datapoolglob}/DataPoolAdmin.h | 18 +- .../DataPoolParameterWrapper.cpp | 14 +- .../DataPoolParameterWrapper.h | 0 datapoolglob/GlobalDataPool.cpp | 133 ++++++++ datapoolglob/GlobalDataPool.h | 149 +++++++++ datapoolglob/GlobalDataSet.cpp | 48 +++ datapoolglob/GlobalDataSet.h | 98 ++++++ datapoolglob/GlobalPoolVariable.h | 213 +++++++++++++ datapoolglob/GlobalPoolVariable.tpp | 117 +++++++ datapoolglob/GlobalPoolVector.h | 185 +++++++++++ datapoolglob/GlobalPoolVector.tpp | 117 +++++++ {datapool => datapoolglob}/PIDReader.h | 39 ++- {datapool => datapoolglob}/PIDReaderList.h | 10 +- datapoolglob/PoolRawAccess.cpp | 239 ++++++++++++++ datapoolglob/PoolRawAccess.h | 220 +++++++++++++ 38 files changed, 2090 insertions(+), 1590 deletions(-) delete mode 100644 datapool/ControllerSet.h delete mode 100644 datapool/DataPool.cpp delete mode 100644 datapool/DataPool.h delete mode 100644 datapool/DataSet.cpp delete mode 100644 datapool/DataSet.h create mode 100644 datapool/PoolDataSetBase.cpp create mode 100644 datapool/PoolDataSetBase.h create mode 100644 datapool/PoolDataSetIF.h delete mode 100644 datapool/PoolRawAccess.cpp delete mode 100644 datapool/PoolRawAccess.h delete mode 100644 datapool/PoolVariable.h delete mode 100644 datapool/PoolVector.h create mode 100644 datapool/SharedDataSetIF.h rename {datapool => datapoolglob}/ControllerSet.cpp (79%) create mode 100644 datapoolglob/ControllerSet.h rename {datapool => datapoolglob}/DataPoolAdmin.cpp (94%) rename {datapool => datapoolglob}/DataPoolAdmin.h (92%) rename {datapool => datapoolglob}/DataPoolParameterWrapper.cpp (95%) rename {datapool => datapoolglob}/DataPoolParameterWrapper.h (100%) create mode 100644 datapoolglob/GlobalDataPool.cpp create mode 100644 datapoolglob/GlobalDataPool.h create mode 100644 datapoolglob/GlobalDataSet.cpp create mode 100644 datapoolglob/GlobalDataSet.h create mode 100644 datapoolglob/GlobalPoolVariable.h create mode 100644 datapoolglob/GlobalPoolVariable.tpp create mode 100644 datapoolglob/GlobalPoolVector.h create mode 100644 datapoolglob/GlobalPoolVector.tpp rename {datapool => datapoolglob}/PIDReader.h (77%) rename {datapool => datapoolglob}/PIDReaderList.h (68%) create mode 100644 datapoolglob/PoolRawAccess.cpp create mode 100644 datapoolglob/PoolRawAccess.h diff --git a/datapool/ControllerSet.h b/datapool/ControllerSet.h deleted file mode 100644 index e27debff..00000000 --- a/datapool/ControllerSet.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef CONTROLLERSET_H_ -#define CONTROLLERSET_H_ - -#include "DataSet.h" - -class ControllerSet :public DataSet { -public: - ControllerSet(); - virtual ~ControllerSet(); - - virtual void setToDefault() = 0; - void setInvalid(); -}; - -#endif /* CONTROLLERSET_H_ */ diff --git a/datapool/DataPool.cpp b/datapool/DataPool.cpp deleted file mode 100644 index 1b6cb7a1..00000000 --- a/datapool/DataPool.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include "DataPool.h" -#include "../serviceinterface/ServiceInterfaceStream.h" -#include "../ipc/MutexFactory.h" - -DataPool::DataPool( void ( *initFunction )( std::map* pool_map ) ) { - mutex = MutexFactory::instance()->createMutex(); - if (initFunction != NULL ) { - initFunction( &this->data_pool ); - } -} - -DataPool::~DataPool() { - MutexFactory::instance()->deleteMutex(mutex); - for ( std::map::iterator it = this->data_pool.begin(); it != this->data_pool.end(); ++it ) { - delete it->second; - } -} - -//The function checks PID, type and array length before returning a copy of the PoolEntry. In failure case, it returns a temp-Entry with size 0 and NULL-ptr. -template PoolEntry* DataPool::getData( uint32_t data_pool_id, uint8_t sizeOrPosition ) { - std::map::iterator it = this->data_pool.find( data_pool_id ); - if ( it != this->data_pool.end() ) { - PoolEntry* entry = dynamic_cast< PoolEntry* >( it->second ); - if (entry != NULL ) { - if ( sizeOrPosition <= entry->length ) { - return entry; - } - } - } - return NULL; -} - -PoolEntryIF* DataPool::getRawData( uint32_t data_pool_id ) { - std::map::iterator it = this->data_pool.find( data_pool_id ); - if ( it != this->data_pool.end() ) { - return it->second; - } else { - return NULL; - } -} - -//uint8_t DataPool::getRawData( uint32_t data_pool_id, uint8_t* address, uint16_t* size, uint32_t maxSize ) { -// std::map::iterator it = this->data_pool.find( data_pool_id ); -// if ( it != this->data_pool.end() ) { -// if ( it->second->getByteSize() <= maxSize ) { -// *size = it->second->getByteSize(); -// memcpy( address, it->second->getRawData(), *size ); -// return DP_SUCCESSFUL; -// } -// } -// *size = 0; -// return DP_FAILURE; -//} - -ReturnValue_t DataPool::freeDataPoolLock() { - ReturnValue_t status = mutex->unlockMutex(); - if ( status != RETURN_OK ) { - sif::error << "DataPool::DataPool: unlock of mutex failed with error code: " << status << std::endl; - } - return status; -} - -ReturnValue_t DataPool::lockDataPool() { - ReturnValue_t status = mutex->lockMutex(MutexIF::BLOCKING); - if ( status != RETURN_OK ) { - sif::error << "DataPool::DataPool: lock of mutex failed with error code: " << status << std::endl; - } - return status; -} - -void DataPool::print() { - sif::debug << "DataPool contains: " << std::endl; - std::map::iterator dataPoolIt; - dataPoolIt = this->data_pool.begin(); - while( dataPoolIt != this->data_pool.end() ) { - sif::debug << std::hex << dataPoolIt->first << std::dec << " |"; - dataPoolIt->second->print(); - dataPoolIt++; - } -} - -template PoolEntry* DataPool::getData( uint32_t data_pool_id, uint8_t size ); -template PoolEntry* DataPool::getData( uint32_t data_pool_id, uint8_t size ); -template PoolEntry* DataPool::getData( uint32_t data_pool_id, uint8_t size ); -template PoolEntry* DataPool::getData(uint32_t data_pool_id, - uint8_t size); -template PoolEntry* DataPool::getData( uint32_t data_pool_id, uint8_t size ); -template PoolEntry* DataPool::getData( uint32_t data_pool_id, uint8_t size ); -template PoolEntry* DataPool::getData( uint32_t data_pool_id, uint8_t size ); -template PoolEntry* DataPool::getData( uint32_t data_pool_id, uint8_t size ); -template PoolEntry* DataPool::getData(uint32_t data_pool_id, - uint8_t size); - - -uint32_t DataPool::PIDToDataPoolId(uint32_t parameter_id) { - return (parameter_id >> 8) & 0x00FFFFFF; -} - -uint8_t DataPool::PIDToArrayIndex(uint32_t parameter_id) { - return (parameter_id & 0x000000FF); -} - -uint32_t DataPool::poolIdAndPositionToPid(uint32_t poolId, uint8_t index) { - return (poolId << 8) + index; -} - - -//SHOULDDO: Do we need a mutex lock here... I don't think so, as we only check static const values of elements in a list that do not change. -//there is no guarantee in the standard, but it seems to me that the implementation is safe -UM -ReturnValue_t DataPool::getType(uint32_t parameter_id, Type* type) { - std::map::iterator it = this->data_pool.find( PIDToDataPoolId(parameter_id)); - if ( it != this->data_pool.end() ) { - *type = it->second->getType(); - return RETURN_OK; - } else { - *type = Type::UNKNOWN_TYPE; - return RETURN_FAILED; - } -} - -bool DataPool::exists(uint32_t parameterId) { - uint32_t poolId = PIDToDataPoolId(parameterId); - uint32_t index = PIDToArrayIndex(parameterId); - std::map::iterator it = this->data_pool.find( poolId ); - if (it != data_pool.end()) { - if (it->second->getSize() >= index) { - return true; - } - } - return false; -} diff --git a/datapool/DataPool.h b/datapool/DataPool.h deleted file mode 100644 index 7abf2898..00000000 --- a/datapool/DataPool.h +++ /dev/null @@ -1,135 +0,0 @@ -/** - * \file DataPool.h - * - * \date 10/17/2012 - * \author Bastian Baetz - * - * \brief This file contains the definition of the DataPool class and (temporarily) - * the "extern" definition of the global dataPool instance. - */ - -#ifndef DATAPOOL_H_ -#define DATAPOOL_H_ - -#include "PoolEntry.h" -#include "../globalfunctions/Type.h" -#include "../ipc/MutexIF.h" -#include - -/** - * \defgroup data_pool Data Pool - * This is the group, where all classes associated with Data Pool Handling belong to. - * This includes classes to access Data Pool variables. - */ - -#define DP_SUCCESSFUL 0 -#define DP_FAILURE 1 - -/** - * \brief This class represents the OBSW global data-pool. - * - * \details All variables are registered and space is allocated in an initialization - * function, which is passed do the constructor. - * Space for the variables is allocated on the heap (with a new call). - * The data is found by a data pool id, which uniquely represents a variable. - * Data pool variables should be used with a blackboard logic in mind, - * which means read data is valid (if flagged so), but not necessarily up-to-date. - * Variables are either single values or arrays. - * \ingroup data_pool - */ -class DataPool : public HasReturnvaluesIF { -private: - /** - * \brief This is the actual data pool itself. - * \details It is represented by a map - * with the data pool id as index and a pointer to a single PoolEntry as value. - */ - std::map data_pool; -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. - */ - MutexIF* mutex; - /** - * \brief In the classes constructor, the passed initialization function is called. - * \details To enable filling the pool, - * a pointer to the map is passed, allowing direct access to the pool's content. - * On runtime, adding or removing variables is forbidden. - */ - DataPool( void ( *initFunction )( std::map* pool_map ) ); - /** - * \brief The destructor iterates through the data_pool map and calls all Entries destructors to clean up the heap. - */ - ~DataPool(); - /** - * \brief This is the default call to access the pool. - * \details A pointer to the PoolEntry object is returned. - * The call checks data pool id, type and array size. Returns NULL in case of failure. - * \param data_pool_id The data pool id to search. - * \param sizeOrPosition The array size (not byte size!) of the pool entry, or the position the user wants to read. - * If smaller than the entry size, everything's ok. - */ - template PoolEntry* getData( uint32_t data_pool_id, uint8_t sizeOrPosition ); - /** - * \brief An alternative call to get a data pool entry in case the type is not implicitly known - * (i.e. in Housekeeping Telemetry). - * \details It returns a basic interface and does NOT perform - * a size check. The caller has to assure he does not copy too much data. - * Returns NULL in case the entry is not found. - * \param data_pool_id The data pool id to search. - */ - PoolEntryIF* getRawData( uint32_t data_pool_id ); - /** - * \brief This is a small helper function to facilitate locking the global data pool. - * \details It fetches the pool's mutex id and tries to acquire the mutex. - */ - ReturnValue_t lockDataPool(); - /** - * \brief This is a small helper function to facilitate unlocking the global data pool. - * \details It fetches the pool's mutex id and tries to free the mutex. - */ - ReturnValue_t freeDataPoolLock(); - /** - * \brief The print call is a simple debug method. - * \details It prints the current content of the data pool. - * It iterates through the data_pool map and calls each entry's print() method. - */ - void print(); - /** - * Extracts the data pool id from a SCOS 2000 PID. - * @param parameter_id The passed Parameter ID. - * @return The data pool id as used within the OBSW. - */ - static uint32_t PIDToDataPoolId( uint32_t parameter_id ); - /** - * Extracts an array index out of a SCOS 2000 PID. - * @param parameter_id The passed Parameter ID. - * @return The index of the corresponding data pool entry. - */ - static uint8_t PIDToArrayIndex( uint32_t parameter_id ); - /** - * Retransforms a data pool id and an array index to a SCOS 2000 PID. - */ - static uint32_t poolIdAndPositionToPid( uint32_t poolId, uint8_t index ); - - /** - * 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. - * @param parameterId The PID (not pool id!) of a parameter. - * @return true if exists, false else. - */ - bool exists(uint32_t parameterId); -}; - -//We assume someone globally instantiates a DataPool. -extern DataPool dataPool; -#endif /* DATAPOOL_H_ */ diff --git a/datapool/DataSet.cpp b/datapool/DataSet.cpp deleted file mode 100644 index e41489bd..00000000 --- a/datapool/DataSet.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include "DataSet.h" -#include "../serviceinterface/ServiceInterfaceStream.h" - -DataSet::DataSet() : - fill_count(0), state(DATA_SET_UNINITIALISED) { - for (unsigned count = 0; count < DATA_SET_MAX_SIZE; count++) { - registeredVariables[count] = NULL; - } -} - -DataSet::~DataSet() { - //Don't do anything with your variables, they are dead already! (Destructor is already called) -} - -ReturnValue_t DataSet::read() { - ReturnValue_t result = RETURN_OK; - if (state == DATA_SET_UNINITIALISED) { - lockDataPool(); - for (uint16_t count = 0; count < fill_count; count++) { - if (registeredVariables[count]->getReadWriteMode() - != PoolVariableIF::VAR_WRITE - && registeredVariables[count]->getDataPoolId() - != PoolVariableIF::NO_PARAMETER) { - ReturnValue_t status = registeredVariables[count]->read(); - if (status != RETURN_OK) { - result = INVALID_PARAMETER_DEFINITION; - break; - } - } - } - state = DATA_SET_WAS_READ; - freeDataPoolLock(); - } else { - sif::error << "DataSet::read(): Call made in wrong position." << std::endl; - result = SET_WAS_ALREADY_READ; - } - return result; -} - -ReturnValue_t DataSet::commit(uint8_t valid) { - setValid(valid); - return commit(); -} - -ReturnValue_t DataSet::commit() { - if (state == DATA_SET_WAS_READ) { - lockDataPool(); - for (uint16_t count = 0; count < fill_count; count++) { - if (registeredVariables[count]->getReadWriteMode() - != PoolVariableIF::VAR_READ - && registeredVariables[count]->getDataPoolId() - != PoolVariableIF::NO_PARAMETER) { - registeredVariables[count]->commit(); - } - } - state = DATA_SET_UNINITIALISED; - freeDataPoolLock(); - return RETURN_OK; - } else { - ReturnValue_t result = RETURN_OK; - lockDataPool(); - for (uint16_t count = 0; count < fill_count; count++) { - if (registeredVariables[count]->getReadWriteMode() - == PoolVariableIF::VAR_WRITE - && registeredVariables[count]->getDataPoolId() - != PoolVariableIF::NO_PARAMETER) { - registeredVariables[count]->commit(); - } else if (registeredVariables[count]->getDataPoolId() - != PoolVariableIF::NO_PARAMETER) { - if (result != COMMITING_WITHOUT_READING) { - sif::error << - "DataSet::commit(): commit-without-read " - "call made with non write-only variable." << std::endl; - result = COMMITING_WITHOUT_READING; - } - } - } - state = DATA_SET_UNINITIALISED; - freeDataPoolLock(); - return result; - } - -} - -void DataSet::registerVariable(PoolVariableIF* variable) { - if (state == DATA_SET_UNINITIALISED) { - if (variable != NULL) { - if (fill_count < DATA_SET_MAX_SIZE) { - registeredVariables[fill_count] = variable; - fill_count++; - return; - } - } - } - sif::error - << "DataSet::registerVariable: failed. Either NULL, or set is full, or call made in wrong position." - << std::endl; - return; -} - -uint8_t DataSet::freeDataPoolLock() { - return ::dataPool.freeDataPoolLock(); -} - -uint8_t DataSet::lockDataPool() { - return ::dataPool.lockDataPool(); -} - -ReturnValue_t DataSet::serialize(uint8_t** buffer, size_t* size, - size_t maxSize, Endianness streamEndianness) const { - ReturnValue_t result = RETURN_FAILED; - for (uint16_t count = 0; count < fill_count; count++) { - result = registeredVariables[count]->serialize(buffer, size, maxSize, - streamEndianness); - if (result != RETURN_OK) { - return result; - } - } - return result; -} - -size_t DataSet::getSerializedSize() const { - size_t size = 0; - for (uint16_t count = 0; count < fill_count; count++) { - size += registeredVariables[count]->getSerializedSize(); - } - 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, size_t* size, - Endianness streamEndianness) { - ReturnValue_t result = RETURN_FAILED; - for (uint16_t count = 0; count < fill_count; count++) { - result = registeredVariables[count]->deSerialize(buffer, size, - streamEndianness); - if (result != RETURN_OK) { - return result; - } - } - return result; -} diff --git a/datapool/DataSet.h b/datapool/DataSet.h deleted file mode 100644 index 04044bfe..00000000 --- a/datapool/DataSet.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * \file DataSet.h - * - * \brief This file contains the DataSet class and a small structure called DataSetContent. - * - * \date 10/17/2012 - * - * \author Bastian Baetz - * - */ - -#ifndef DATASET_H_ -#define DATASET_H_ - -#include "DataPool.h" -#include "DataSetIF.h" -#include "PoolRawAccess.h" -#include "PoolVariable.h" -#include "PoolVarList.h" -#include "PoolVector.h" -#include "../serialize/SerializeAdapter.h" -/** - * \brief The DataSet class manages a set of locally checked out variables. - * - * \details This class manages a list, where a set of local variables (or pool variables) are - * registered. They are checked-out (i.e. their values are looked up and copied) - * with the read call. After the user finishes working with the pool variables, - * he can write back all variable values to the pool with the commit call. - * The data set manages locking and freeing the data pool, to ensure that all values - * are read and written back at once. - * An internal state manages usage of this class. Variables may only be registered before - * the read call is made, and the commit call only after the read call. - * If pool variables are writable and not committed until destruction of the set, the - * DataSet class automatically sets the valid flag in the data pool to invalid (without) - * changing the variable's value. - * - * \ingroup data_pool - */ -class DataSet: public DataSetIF, public HasReturnvaluesIF, public SerializeIF { -private: - //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. - - /** - * \brief This array represents all pool variables registered in this set. - * \details It has a maximum size of DATA_SET_MAX_SIZE. - */ - PoolVariableIF* registeredVariables[DATA_SET_MAX_SIZE]; - /** - * \brief The fill_count attribute ensures that the variables register in the correct array - * position and that the maximum number of variables is not exceeded. - */ - uint16_t fill_count; - /** - * States of the seet. - */ - enum States { - DATA_SET_UNINITIALISED, //!< DATA_SET_UNINITIALISED - DATA_SET_WAS_READ //!< DATA_SET_WAS_READ - }; - /** - * \brief state manages the internal state of the data set, which is important e.g. for the - * behavior on destruction. - */ - States state; - /** - * \brief This is a small helper function to facilitate locking the global data pool. - * \details It makes use of the lockDataPool method offered by the DataPool class. - */ - uint8_t lockDataPool(); - /** - * \brief This is a small helper function to facilitate unlocking the global data pool. - * \details It makes use of the freeDataPoolLock method offered by the DataPool class. - */ - uint8_t freeDataPoolLock(); - -public: - 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 ); - static const ReturnValue_t COMMITING_WITHOUT_READING = - MAKE_RETURN_CODE(0x03); - - /** - * \brief The constructor simply sets the fill_count to zero and sets the state to "uninitialized". - */ - DataSet(); - /** - * \brief The destructor automatically manages writing the valid information of variables. - * \details In case the data set was read out, but not committed (indicated by state), - * the destructor parses all variables that are still registered to the set. - * For each, the valid flag in the data pool is set to "invalid". - */ - ~DataSet(); - /** - * \brief The read call initializes reading out all registered variables. - * \details It iterates through the list of registered variables and calls all read() - * functions of the registered pool variables (which read out their values from the - * data pool) which are not write-only. In case of an error (e.g. a wrong data type, - * or an invalid data pool id), the operation is aborted and - * \c INVALID_PARAMETER_DEFINITION returned. - * The data pool is locked during the whole read operation and freed afterwards. - * The state changes to "was written" after this operation. - * \return - \c RETURN_OK if all variables were read successfully. - * - \c INVALID_PARAMETER_DEFINITION if PID, size or type of the - * requested variable is invalid. - * - \c SET_WAS_ALREADY_READ if read() is called twice without calling - * commit() in between - */ - ReturnValue_t read(); - /** - * \brief The commit call initializes writing back the registered variables. - * \details It iterates through the list of registered variables and calls - * the commit() method of the remaining registered variables (which write back - * their values to the pool). - * The data pool is locked during the whole commit operation and freed afterwards. - * The state changes to "was committed" after this operation. - * If the set does contain at least one variable which is not write-only commit() - * can only be called after read(). If the set only contains variables which are - * write only, commit() can be called without a preceding read() call. - * \return - \c RETURN_OK if all variables were read successfully. - * - \c COMMITING_WITHOUT_READING if set was not read yet and contains non write-only - * variables - */ - ReturnValue_t commit(void); - /** - * Variant of method above which sets validity of all elements of the set. - * @param valid Validity information from PoolVariableIF. - * \return - \c RETURN_OK if all variables were read successfully. - * - \c COMMITING_WITHOUT_READING if set was not read yet and contains non write-only - * variables - */ - ReturnValue_t commit(uint8_t valid); - /** - * \brief This operation is used to register the local variables in the set. - * \details It copies all required information to the currently - * free space in the registeredVariables list. - */ - 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, size_t* size, - size_t maxSize, Endianness streamEndianness) const override; - - size_t getSerializedSize() const override; - - ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) override; - -}; - -#endif /* DATASET_H_ */ diff --git a/datapool/DataSetIF.h b/datapool/DataSetIF.h index 7741477d..a6634a5c 100644 --- a/datapool/DataSetIF.h +++ b/datapool/DataSetIF.h @@ -1,39 +1,47 @@ -/** - * \file DataSetIF.h - * - * \brief This file contains the small interface to access the DataSet class. - * - * \date 10/23/2012 - * - * \author Bastian Baetz - * - */ - -#ifndef DATASETIF_H_ -#define DATASETIF_H_ +#ifndef FSFW_DATAPOOL_DATASETIF_H_ +#define FSFW_DATAPOOL_DATASETIF_H_ +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../timemanager/Clock.h" class PoolVariableIF; /** - * \brief This class defines a small interface to register on a DataSet. + * @brief This class defines a small interface to register on a DataSet. * - * \details Currently, the only purpose of this interface is to provide a method for locally - * checked-out variables to register on a data set. Still, it may become useful for - * other purposes as well. - * - * \ingroup data_pool + * @details + * Currently, the only purpose of this interface is to provide a + * method for locally checked-out variables to register on a data set. + * Still, it may become useful for other purposes as well. + * @author Bastian Baetz + * @ingroup data_pool */ class DataSetIF { public: + static constexpr uint8_t INTERFACE_ID = CLASS_ID::DATA_SET_CLASS; + static constexpr ReturnValue_t INVALID_PARAMETER_DEFINITION = + MAKE_RETURN_CODE( 0x01 ); + static constexpr ReturnValue_t SET_WAS_ALREADY_READ = MAKE_RETURN_CODE( 0x02 ); + static constexpr ReturnValue_t COMMITING_WITHOUT_READING = + MAKE_RETURN_CODE(0x03); + + static constexpr ReturnValue_t DATA_SET_UNINITIALISED = MAKE_RETURN_CODE( 0x04 ); + static constexpr ReturnValue_t DATA_SET_FULL = MAKE_RETURN_CODE( 0x05 ); + static constexpr ReturnValue_t POOL_VAR_NULL = MAKE_RETURN_CODE( 0x06 ); + /** - * \brief This is an empty virtual destructor, as it is proposed for C++ interfaces. + * @brief This is an empty virtual destructor, + * as it is proposed for C++ interfaces. */ virtual ~DataSetIF() {} + /** - * \brief This operation provides a method to register local data pool variables - * to register in a data set by passing itself to this DataSet operation. + * @brief This operation provides a method to register local data pool + * variables to register in a data set by passing itself + * to this DataSet operation. */ - virtual void registerVariable( PoolVariableIF* variable ) = 0; + virtual ReturnValue_t registerVariable(PoolVariableIF* variable) = 0; + + virtual uint16_t getFillCount() const = 0; }; -#endif /* DATASETIF_H_ */ +#endif /* FSFW_DATAPOOL_DATASETIF_H_ */ diff --git a/datapool/HkSwitchHelper.cpp b/datapool/HkSwitchHelper.cpp index 04096aca..1a2a25eb 100644 --- a/datapool/HkSwitchHelper.cpp +++ b/datapool/HkSwitchHelper.cpp @@ -1,5 +1,4 @@ -#include "HkSwitchHelper.h" -//#include +#include "../datapool/HkSwitchHelper.h" #include "../ipc/QueueFactory.h" HkSwitchHelper::HkSwitchHelper(EventReportingProxyIF* eventProxy) : @@ -22,14 +21,14 @@ ReturnValue_t HkSwitchHelper::initialize() { } ReturnValue_t HkSwitchHelper::performOperation(uint8_t operationCode) { - CommandMessage message; - while (actionQueue->receiveMessage(&message) == HasReturnvaluesIF::RETURN_OK) { - ReturnValue_t result = commandActionHelper.handleReply(&message); + CommandMessage command; + while (actionQueue->receiveMessage(&command) == HasReturnvaluesIF::RETURN_OK) { + ReturnValue_t result = commandActionHelper.handleReply(&command); if (result == HasReturnvaluesIF::RETURN_OK) { continue; } - message.setToUnknownCommand(); - actionQueue->reply(&message); + command.setToUnknownCommand(); + actionQueue->reply(&command); } return HasReturnvaluesIF::RETURN_OK; diff --git a/datapool/PoolDataSetBase.cpp b/datapool/PoolDataSetBase.cpp new file mode 100644 index 00000000..1acd3fd3 --- /dev/null +++ b/datapool/PoolDataSetBase.cpp @@ -0,0 +1,169 @@ +#include "PoolDataSetBase.h" +#include "../serviceinterface/ServiceInterfaceStream.h" + +PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray, + const size_t maxFillCount): + registeredVariables(registeredVariablesArray), + maxFillCount(maxFillCount) { +} + +PoolDataSetBase::~PoolDataSetBase() {} + +ReturnValue_t PoolDataSetBase::registerVariable( + PoolVariableIF *variable) { + if (state != States::DATA_SET_UNINITIALISED) { + sif::error << "DataSet::registerVariable: " + "Call made in wrong position." << std::endl; + return DataSetIF::DATA_SET_UNINITIALISED; + } + if (variable == nullptr) { + sif::error << "DataSet::registerVariable: " + "Pool variable is nullptr." << std::endl; + return DataSetIF::POOL_VAR_NULL; + } + if (fillCount >= maxFillCount) { + sif::error << "DataSet::registerVariable: " + "DataSet is full." << std::endl; + return DataSetIF::DATA_SET_FULL; + } + registeredVariables[fillCount] = variable; + fillCount++; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t PoolDataSetBase::read(uint32_t lockTimeout) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + if (state == States::DATA_SET_UNINITIALISED) { + lockDataPool(lockTimeout); + for (uint16_t count = 0; count < fillCount; count++) { + result = readVariable(count); + if(result != RETURN_OK) { + break; + } + } + state = States::DATA_SET_WAS_READ; + unlockDataPool(); + } + else { + sif::error << "DataSet::read(): " + "Call made in wrong position. Don't forget to commit" + " member datasets!" << std::endl; + result = SET_WAS_ALREADY_READ; + } + return result; +} + +uint16_t PoolDataSetBase::getFillCount() const { + return fillCount; +} + +ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + // These checks are often performed by the respective + // variable implementation too, but I guess a double check does not hurt. + if (registeredVariables[count]->getReadWriteMode() != + PoolVariableIF::VAR_WRITE and + registeredVariables[count]->getDataPoolId() + != PoolVariableIF::NO_PARAMETER) + { + result = registeredVariables[count]->readWithoutLock(); + if(result != HasReturnvaluesIF::RETURN_OK) { + result = INVALID_PARAMETER_DEFINITION; + } + } + return result; +} + +ReturnValue_t PoolDataSetBase::commit(uint32_t lockTimeout) { + if (state == States::DATA_SET_WAS_READ) { + handleAlreadyReadDatasetCommit(lockTimeout); + return HasReturnvaluesIF::RETURN_OK; + } + else { + return handleUnreadDatasetCommit(lockTimeout); + } +} + +void PoolDataSetBase::handleAlreadyReadDatasetCommit(uint32_t lockTimeout) { + lockDataPool(lockTimeout); + for (uint16_t count = 0; count < fillCount; count++) { + if (registeredVariables[count]->getReadWriteMode() + != PoolVariableIF::VAR_READ + && registeredVariables[count]->getDataPoolId() + != PoolVariableIF::NO_PARAMETER) { + registeredVariables[count]->commitWithoutLock(); + } + } + state = States::DATA_SET_UNINITIALISED; + unlockDataPool(); +} + +ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(uint32_t lockTimeout) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + lockDataPool(lockTimeout); + for (uint16_t count = 0; count < fillCount; count++) { + if (registeredVariables[count]->getReadWriteMode() + == PoolVariableIF::VAR_WRITE + && registeredVariables[count]->getDataPoolId() + != PoolVariableIF::NO_PARAMETER) { + registeredVariables[count]->commitWithoutLock(); + } else if (registeredVariables[count]->getDataPoolId() + != PoolVariableIF::NO_PARAMETER) { + if (result != COMMITING_WITHOUT_READING) { + sif::error << "DataSet::commit(): commit-without-read call made " + "with non write-only variable." << std::endl; + result = COMMITING_WITHOUT_READING; + } + } + } + state = States::DATA_SET_UNINITIALISED; + unlockDataPool(); + return result; +} + + +ReturnValue_t PoolDataSetBase::lockDataPool(uint32_t timeoutMs) { + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t PoolDataSetBase::unlockDataPool() { + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t PoolDataSetBase::serialize(uint8_t** buffer, size_t* size, + const size_t maxSize, SerializeIF::Endianness streamEndianness) const { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + for (uint16_t count = 0; count < fillCount; count++) { + result = registeredVariables[count]->serialize(buffer, size, maxSize, + streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + return result; +} + +ReturnValue_t PoolDataSetBase::deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + for (uint16_t count = 0; count < fillCount; count++) { + result = registeredVariables[count]->deSerialize(buffer, size, + streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + return result; +} + +size_t PoolDataSetBase::getSerializedSize() const { + uint32_t size = 0; + for (uint16_t count = 0; count < fillCount; count++) { + size += registeredVariables[count]->getSerializedSize(); + } + return size; +} + +void PoolDataSetBase::setContainer(PoolVariableIF **variablesContainer) { + this->registeredVariables = variablesContainer; +} diff --git a/datapool/PoolDataSetBase.h b/datapool/PoolDataSetBase.h new file mode 100644 index 00000000..a8931d62 --- /dev/null +++ b/datapool/PoolDataSetBase.h @@ -0,0 +1,152 @@ +#ifndef FSFW_DATAPOOL_POOLDATASETBASE_H_ +#define FSFW_DATAPOOL_POOLDATASETBASE_H_ + +#include "PoolDataSetIF.h" +#include "PoolVariableIF.h" +#include "../ipc/MutexIF.h" + +/** + * @brief The DataSetBase class manages a set of locally checked out variables. + * @details + * This class manages a list, where a set of local variables (or pool variables) + * are registered. They are checked-out (i.e. their values are looked + * up and copied) with the read call. After the user finishes working with the + * pool variables, he can write back all variable values to the pool with + * the commit call. The data set manages locking and freeing the data pool, + * to ensure that all values are read and written back at once. + * + * An internal state manages usage of this class. Variables may only be + * registered before the read call is made, and the commit call only + * after the read call. + * + * If pool variables are writable and not committed until destruction + * of the set, the DataSet class automatically sets the valid flag in the + * data pool to invalid (without) changing the variable's value. + * + * The base class lockDataPool und unlockDataPool implementation are empty + * and should be implemented to protect the underlying pool type. + * @author Bastian Baetz + * @ingroup data_pool + */ +class PoolDataSetBase: public PoolDataSetIF, + public SerializeIF, + public HasReturnvaluesIF { +public: + + /** + * @brief Creates an empty dataset. Use registerVariable or + * supply a pointer to this dataset to PoolVariable + * initializations to register pool variables. + */ + PoolDataSetBase(PoolVariableIF** registeredVariablesArray, + const size_t maxFillCount); + virtual~ PoolDataSetBase(); + + /** + * @brief The read call initializes reading out all registered variables. + * @details + * It iterates through the list of registered variables and calls all read() + * functions of the registered pool variables (which read out their values + * from the data pool) which are not write-only. + * In case of an error (e.g. a wrong data type, or an invalid data pool id), + * the operation is aborted and @c INVALID_PARAMETER_DEFINITION returned. + * + * The data pool is locked during the whole read operation and + * freed afterwards.The state changes to "was written" after this operation. + * @return + * - @c RETURN_OK if all variables were read successfully. + * - @c INVALID_PARAMETER_DEFINITION if PID, size or type of the + * requested variable is invalid. + * - @c SET_WAS_ALREADY_READ if read() is called twice without calling + * commit() in between + */ + virtual ReturnValue_t read(uint32_t lockTimeout = + MutexIF::BLOCKING) override; + /** + * @brief The commit call initializes writing back the registered variables. + * @details + * It iterates through the list of registered variables and calls the + * commit() method of the remaining registered variables (which write back + * their values to the pool). + * + * The data pool is locked during the whole commit operation and + * freed afterwards. The state changes to "was committed" after this operation. + * + * If the set does contain at least one variable which is not write-only + * commit() can only be called after read(). If the set only contains + * variables which are write only, commit() can be called without a + * preceding read() call. + * @return - @c RETURN_OK if all variables were read successfully. + * - @c COMMITING_WITHOUT_READING if set was not read yet and + * contains non write-only variables + */ + virtual ReturnValue_t commit(uint32_t lockTimeout = + MutexIF::BLOCKING) override; + + /** + * Register the passed pool variable instance into the data set. + * @param variable + * @return + */ + virtual ReturnValue_t registerVariable( PoolVariableIF* variable) override; + /** + * Provides the means to lock the underlying data structure to ensure + * thread-safety. Default implementation is empty + * @return Always returns -@c RETURN_OK + */ + virtual ReturnValue_t lockDataPool(uint32_t timeoutMs = + MutexIF::BLOCKING) override; + /** + * Provides the means to unlock the underlying data structure to ensure + * thread-safety. Default implementation is empty + * @return Always returns -@c RETURN_OK + */ + virtual ReturnValue_t unlockDataPool() override; + + virtual uint16_t getFillCount() const; + + /* SerializeIF implementations */ + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + const size_t maxSize, + SerializeIF::Endianness streamEndianness) const override; + virtual size_t getSerializedSize() const override; + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) override; + +protected: + /** + * @brief The fill_count attribute ensures that the variables + * register in the correct array position and that the maximum + * number of variables is not exceeded. + */ + uint16_t fillCount = 0; + /** + * States of the seet. + */ + enum class States { + DATA_SET_UNINITIALISED, //!< DATA_SET_UNINITIALISED + DATA_SET_WAS_READ //!< DATA_SET_WAS_READ + }; + /** + * @brief state manages the internal state of the data set, + * which is important e.g. for the behavior on destruction. + */ + States state = States::DATA_SET_UNINITIALISED; + + /** + * @brief This array represents all pool variables registered in this set. + * Child classes can use a static or dynamic container to create + * an array of registered variables and assign the first entry here. + */ + PoolVariableIF** registeredVariables = nullptr; + const size_t maxFillCount = 0; + + void setContainer(PoolVariableIF** variablesContainer); + +private: + ReturnValue_t readVariable(uint16_t count); + void handleAlreadyReadDatasetCommit(uint32_t lockTimeout); + ReturnValue_t handleUnreadDatasetCommit(uint32_t lockTimeout); +}; + +#endif /* FSFW_DATAPOOL_POOLDATASETBASE_H_ */ diff --git a/datapool/PoolDataSetIF.h b/datapool/PoolDataSetIF.h new file mode 100644 index 00000000..aa45fa54 --- /dev/null +++ b/datapool/PoolDataSetIF.h @@ -0,0 +1,33 @@ +#ifndef FSFW_DATAPOOL_POOLDATASETIF_H_ +#define FSFW_DATAPOOL_POOLDATASETIF_H_ + +#include "DataSetIF.h" + +/** + * @brief Extendes the DataSetIF by adding abstract functions to lock + * and unlock a data pool and read/commit semantics. + */ +class PoolDataSetIF: public DataSetIF { +public: + virtual~ PoolDataSetIF() {}; + + virtual ReturnValue_t read(dur_millis_t lockTimeout) = 0; + virtual ReturnValue_t commit(dur_millis_t lockTimeout) = 0; + + /** + * @brief Most underlying data structures will have a pool like structure + * and will require a lock and unlock mechanism to ensure + * thread-safety + * @return Lock operation result + */ + virtual ReturnValue_t lockDataPool(dur_millis_t timeoutMs) = 0; + /** + * @brief Unlock call corresponding to the lock call. + * @return Unlock operation result + */ + virtual ReturnValue_t unlockDataPool() = 0; + + virtual bool isValid() const = 0; +}; + +#endif /* FSFW_DATAPOOL_POOLDATASETIF_H_ */ diff --git a/datapool/PoolEntry.cpp b/datapool/PoolEntry.cpp index 56e489a5..fb73328c 100644 --- a/datapool/PoolEntry.cpp +++ b/datapool/PoolEntry.cpp @@ -1,4 +1,5 @@ #include "PoolEntry.h" + #include "../serviceinterface/ServiceInterfaceStream.h" #include "../globalfunctions/arrayprinter.h" #include diff --git a/datapool/PoolEntry.h b/datapool/PoolEntry.h index 7b47c673..033db40d 100644 --- a/datapool/PoolEntry.h +++ b/datapool/PoolEntry.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_DATAPOOL_POOLENTRY_H_ -#define FRAMEWORK_DATAPOOL_POOLENTRY_H_ +#ifndef FSFW_DATAPOOL_POOLENTRY_H_ +#define FSFW_DATAPOOL_POOLENTRY_H_ #include "PoolEntryIF.h" @@ -127,4 +127,4 @@ public: Type getType(); }; -#endif /* POOLENTRY_H_ */ +#endif /* FSFW_DATAPOOL_POOLENTRY_H_ */ diff --git a/datapool/PoolEntryIF.h b/datapool/PoolEntryIF.h index 462de18b..d9db5237 100644 --- a/datapool/PoolEntryIF.h +++ b/datapool/PoolEntryIF.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_DATAPOOL_POOLENTRYIF_H_ -#define FRAMEWORK_DATAPOOL_POOLENTRYIF_H_ +#ifndef FSFW_DATAPOOL_POOLENTRYIF_H_ +#define FSFW_DATAPOOL_POOLENTRYIF_H_ #include "../globalfunctions/Type.h" #include @@ -60,4 +60,4 @@ public: virtual Type getType() = 0; }; -#endif /* POOLENTRYIF_H_ */ +#endif /* FSFW_DATAPOOL_POOLENTRYIF_H_ */ diff --git a/datapool/PoolRawAccess.cpp b/datapool/PoolRawAccess.cpp deleted file mode 100644 index f9264081..00000000 --- a/datapool/PoolRawAccess.cpp +++ /dev/null @@ -1,187 +0,0 @@ -#include "DataPool.h" -#include "PoolEntryIF.h" -#include "PoolRawAccess.h" -#include "../serviceinterface/ServiceInterfaceStream.h" -#include "../serialize/EndianConverter.h" - -#include - -PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry, - DataSetIF *data_set, ReadWriteMode_t 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); - } -} - -PoolRawAccess::~PoolRawAccess() { - -} - -ReturnValue_t PoolRawAccess::read() { - PoolEntryIF *read_out = ::dataPool.getRawData(dataPoolId); - 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; - uint8_t *ptr = - &((uint8_t*) read_out->getRawData())[arrayPosition]; - memcpy(value, ptr, typeSize); - return HasReturnvaluesIF::RETURN_OK; - } else { - //Error value type too large. - } - } else { - //Error index requested too large - } - } else { - //Error entry does not exist. - } - sif::error << "PoolRawAccess: read of DP Variable 0x" << std::hex - << dataPoolId << std::dec << " failed." << std::endl; - valid = INVALID; - typeSize = 0; - sizeTillEnd = 0; - memset(value, 0, sizeof(value)); - return HasReturnvaluesIF::RETURN_FAILED; -} - -ReturnValue_t PoolRawAccess::commit() { - PoolEntryIF *write_back = ::dataPool.getRawData(dataPoolId); - if ((write_back != NULL) && (readWriteMode != VAR_READ)) { - write_back->setValid(valid); - uint8_t array_position = arrayEntry * typeSize; - uint8_t *ptr = &((uint8_t*) write_back->getRawData())[array_position]; - memcpy(ptr, value, typeSize); - return HasReturnvaluesIF::RETURN_OK; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -uint8_t* PoolRawAccess::getEntry() { - return value; -} - -ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t *buffer, - size_t *writtenBytes, size_t maxSize) { - uint8_t *data_ptr = getEntry(); -// debug << "PoolRawAccess::getEntry: Array position: " << index * size_of_type << " Size of T: " << (int)size_of_type << " ByteSize: " << byte_size << " Position: " << *size << std::endl; - if (typeSize == 0) { - return DATA_POOL_ACCESS_FAILED; - } - if (typeSize > maxSize) { - return INCORRECT_SIZE; - } - EndianConverter::convertBigEndian(buffer, data_ptr, typeSize); - *writtenBytes = typeSize; - return HasReturnvaluesIF::RETURN_OK; -} - -Type PoolRawAccess::getType() { - return type; -} - -size_t PoolRawAccess::getSizeOfType() { - return typeSize; -} - -size_t PoolRawAccess::getArraySize() { - return arraySize; -} - -uint32_t PoolRawAccess::getDataPoolId() const { - return dataPoolId; -} - -PoolVariableIF::ReadWriteMode_t PoolRawAccess::getReadWriteMode() const { - return readWriteMode; -} - -ReturnValue_t PoolRawAccess::setEntryFromBigEndian(const uint8_t *buffer, - size_t setSize) { - if (typeSize == setSize) { - EndianConverter::convertBigEndian(value, buffer, typeSize); - return HasReturnvaluesIF::RETURN_OK; - } else { - sif::error - << "PoolRawAccess::setEntryFromBigEndian: Illegal sizes: Internal" - << (uint32_t) typeSize << ", Requested: " << setSize - << std::endl; - return INCORRECT_SIZE; - } -} - -bool PoolRawAccess::isValid() const { - if (valid != INVALID) - return true; - else - return false; -} - -void PoolRawAccess::setValid(uint8_t valid) { - this->valid = valid; -} - -size_t PoolRawAccess::getSizeTillEnd() const { - return sizeTillEnd; -} - -ReturnValue_t PoolRawAccess::serialize(uint8_t **buffer, size_t *size, - size_t maxSize, Endianness streamEndianness) const { - if (typeSize + *size <= maxSize) { - switch (streamEndianness) { - case (Endianness::BIG): - EndianConverter::convertBigEndian(*buffer, value, typeSize); - break; - case (Endianness::LITTLE): - EndianConverter::convertLittleEndian(*buffer, value, typeSize); - break; - default: - case (Endianness::MACHINE): - memcpy(*buffer, value, typeSize); - break; - } - *size += typeSize; - (*buffer) += typeSize; - return HasReturnvaluesIF::RETURN_OK; - } else { - return SerializeIF::BUFFER_TOO_SHORT; - } -} - -size_t PoolRawAccess::getSerializedSize() const { - return typeSize; -} - -ReturnValue_t PoolRawAccess::deSerialize(const uint8_t **buffer, size_t *size, - Endianness streamEndianness) { - - if (*size >= typeSize) { - switch (streamEndianness) { - case (Endianness::BIG): - EndianConverter::convertBigEndian(value, *buffer, typeSize); - break; - case (Endianness::LITTLE): - EndianConverter::convertLittleEndian(value, *buffer, typeSize); - break; - default: - case (Endianness::MACHINE): - memcpy(value, *buffer, typeSize); - break; - } - *size -= typeSize; - *buffer += typeSize; - return HasReturnvaluesIF::RETURN_OK; - } else { - return SerializeIF::STREAM_TOO_SHORT; - } -} diff --git a/datapool/PoolRawAccess.h b/datapool/PoolRawAccess.h deleted file mode 100644 index 0c7a06bf..00000000 --- a/datapool/PoolRawAccess.h +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef POOLRAWACCESS_H_ -#define POOLRAWACCESS_H_ - -#include "DataSetIF.h" -#include "PoolVariableIF.h" - -/** - * This class allows accessing Data Pool variables as raw bytes. - * This is necessary to have an access method for HK data, as the PID's alone do not - * provide a type information. - * \ingroup data_pool - */ -class PoolRawAccess: public PoolVariableIF { -private: - /** - * \brief To access the correct data pool entry on read and commit calls, the data pool id - * is stored. - */ - uint32_t dataPoolId; - /** - * \brief The array entry that is fetched from the data pool. - */ - uint8_t arrayEntry; - /** - * \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. - */ - size_t typeSize; - /** - * The size of the DP array (single values return 1) - */ - size_t arraySize; - /** - * The size (in bytes) from the selected entry till the end of this DataPool variable. - */ - size_t sizeTillEnd; - /** - * \brief The information whether the class is read-write or read-only is stored here. - */ - ReadWriteMode_t readWriteMode; - static const uint8_t RAW_MAX_SIZE = sizeof(double); -protected: - /** - * \brief This is a call to read the value from the global data pool. - * \details When executed, this operation tries to fetch the pool entry with matching - * data pool id from the global data pool and copies the value and the valid - * information to its local attributes. In case of a failure (wrong type or - * pool id not found), the variable is set to zero and invalid. - * The operation does NOT provide any mutual exclusive protection by itself. - */ - ReturnValue_t read(); - /** - * \brief The commit call writes back the variable's value to the data pool. - * \details It checks type and size, as well as if the variable is writable. If so, - * the value is copied and the valid flag is automatically set to "valid". - * The operation does NOT provide any mutual exclusive protection by itself. - * - */ - ReturnValue_t commit(); -public: - 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]; - PoolRawAccess(uint32_t data_pool_id, uint8_t arrayEntry, - DataSetIF *data_set, ReadWriteMode_t setReadWriteMode = - PoolVariableIF::VAR_READ); - /** - * \brief The classes destructor is empty. If commit() was not called, the local value is - * discarded and not written back to the data pool. - */ - ~PoolRawAccess(); - /** - * \brief This operation returns a pointer to the entry fetched. - * \details This means, it does not return a pointer to byte "index", but to the start byte of - * array entry "index". Example: If the original data pool array consists of an double - * array of size four, getEntry(1) returns &(this->value[8]). - */ - uint8_t* getEntry(); - /** - * \brief This operation returns the fetched entry from the data pool and - * flips the bytes, if necessary. - * \details It makes use of the getEntry call of this function, but additionally flips the - * bytes to big endian, which is the default for external communication (as House- - * keeping telemetry). To achieve this, the data is copied directly to the passed - * buffer, if it fits in the given maxSize. - * \param buffer A pointer to a buffer to write to - * \param writtenBytes The number of bytes written is returned with this value. - * \param maxSize The maximum size that the function may write to buffer. - * \return - \c RETURN_OK if entry could be acquired - * - \c RETURN_FAILED else. - */ - ReturnValue_t getEntryEndianSafe(uint8_t *buffer, size_t *size, - size_t maxSize); - /** - * With this method, the content can be set from a big endian buffer safely. - * @param buffer Pointer to the data to set - * @param size Size of the data to write. Must fit this->size. - * @return - \c RETURN_OK on success - * - \c RETURN_FAILED on failure - */ - ReturnValue_t setEntryFromBigEndian(const uint8_t *buffer, - size_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. - */ - size_t getSizeOfType(); - /** - * - * @return the size of the datapool array - */ - size_t getArraySize(); - /** - * \brief This operation returns the data pool id of the variable. - */ - uint32_t getDataPoolId() const; - /** - * This method returns if the variable is read-write or read-only. - */ - ReadWriteMode_t getReadWriteMode() const; - /** - * \brief With this call, the valid information of the variable is returned. - */ - bool isValid() const; - - void setValid(uint8_t valid); - /** - * Getter for the remaining size. - */ - size_t getSizeTillEnd() const; - - ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, - Endianness streamEndianness) const override; - - size_t getSerializedSize() const override; - - ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, - Endianness streamEndianness) override; -}; - -#endif /* POOLRAWACCESS_H_ */ diff --git a/datapool/PoolVarList.h b/datapool/PoolVarList.h index 035ff2ac..0b2b0f06 100644 --- a/datapool/PoolVarList.h +++ b/datapool/PoolVarList.h @@ -1,14 +1,15 @@ -#ifndef POOLVARLIST_H_ -#define POOLVARLIST_H_ +#ifndef FSFW_DATAPOOL_POOLVARLIST_H_ +#define FSFW_DATAPOOL_POOLVARLIST_H_ -#include "PoolVariable.h" -#include "PoolVariableIF.h" +#include "../datapool/PoolVariableIF.h" +#include "../datapoolglob/GlobalPoolVariable.h" template class PoolVarList { private: - PoolVariable variables[n_var]; + GlobPoolVar variables[n_var]; public: - PoolVarList( const uint32_t set_id[n_var], DataSetIF* dataSet, PoolVariableIF::ReadWriteMode_t setReadWriteMode ) { + PoolVarList( const uint32_t set_id[n_var], DataSetIF* dataSet, + PoolVariableIF::ReadWriteMode_t setReadWriteMode ) { //I really should have a look at the new init list c++ syntax. if (dataSet == NULL) { return; @@ -20,9 +21,9 @@ public: } } - PoolVariable &operator [](int i) { return variables[i]; } + GlobPoolVar &operator [](int i) { return variables[i]; } }; -#endif /* POOLVARLIST_H_ */ +#endif /* FSFW_DATAPOOL_POOLVARLIST_H_ */ diff --git a/datapool/PoolVariable.h b/datapool/PoolVariable.h deleted file mode 100644 index a9d3407d..00000000 --- a/datapool/PoolVariable.h +++ /dev/null @@ -1,295 +0,0 @@ -/* - * \file PoolVariable.h - * - * \brief This file contains the PoolVariable class, which locally represents a non-array data pool variable. - * - * \date 10/17/2012 - * - * \author Bastian Baetz - */ - -#ifndef POOLVARIABLE_H_ -#define POOLVARIABLE_H_ - -#include "DataSetIF.h" -#include "PoolEntry.h" -#include "PoolVariableIF.h" -#include "../serialize/SerializeAdapter.h" -#include "../serviceinterface/ServiceInterfaceStream.h" - -template class PoolVarList; - -/** - * \brief This is the access class for non-array data pool entries. - * - * \details To ensure safe usage of the data pool, operation is not done directly on the data pool - * entries, but on local copies. This class provides simple type-safe access to single - * data pool entries (i.e. entries with length = 1). - * The class can be instantiated as read-write and read only. - * It provides a commit-and-roll-back semantic, which means that the variable's value in - * the data pool is not changed until the commit call is executed. - * \tparam T The template parameter sets the type of the variable. Currently, all plain data types - * are supported, but in principle any type is possible. - * \ingroup data_pool - */ -template -class PoolVariable: public PoolVariableIF { - template friend class PoolVarList; -protected: - /** - * \brief To access the correct data pool entry on read and commit calls, the data pool id - * is stored. - */ - uint32_t dataPoolId; - /** - * \brief The valid information as it was stored in the data pool is copied to this attribute. - */ - uint8_t valid; - /** - * \brief The information whether the class is read-write or read-only is stored here. - */ - ReadWriteMode_t readWriteMode; - /** - * \brief This is a call to read the value from the global data pool. - * \details When executed, this operation tries to fetch the pool entry with matching - * data pool id from the global data pool and copies the value and the valid - * information to its local attributes. In case of a failure (wrong type or - * pool id not found), the variable is set to zero and invalid. - * The operation does NOT provide any mutual exclusive protection by itself. - */ - ReturnValue_t read() { - PoolEntry *read_out = ::dataPool.getData < T > (dataPoolId, 1); - if (read_out != NULL) { - valid = read_out->valid; - value = *(read_out->address); - return HasReturnvaluesIF::RETURN_OK; - } else { - value = 0; - valid = false; - sif::error << "PoolVariable: read of DP Variable 0x" << std::hex - << dataPoolId << std::dec << " failed." << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - } - /** - * \brief The commit call writes back the variable's value to the data pool. - * \details It checks type and size, as well as if the variable is writable. If so, - * the value is copied and the valid flag is automatically set to "valid". - * The operation does NOT provide any mutual exclusive protection by itself. - * - */ - ReturnValue_t commit() { - PoolEntry *write_back = ::dataPool.getData < T > (dataPoolId, 1); - if ((write_back != NULL) && (readWriteMode != VAR_READ)) { - write_back->valid = valid; - *(write_back->address) = value; - return HasReturnvaluesIF::RETURN_OK; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } - } - /** - * Empty ctor for List initialization - */ - PoolVariable() : - dataPoolId(PoolVariableIF::NO_PARAMETER), valid( - PoolVariableIF::INVALID), readWriteMode(VAR_READ), value(0) { - - } -public: - /** - * \brief This is the local copy of the data pool entry. - * \details The user can work on this attribute - * just like he would on a simple local variable. - */ - T value; - /** - * \brief In the constructor, the variable can register itself in a DataSet (if not NULL is - * passed). - * \details It DOES NOT fetch the current value from the data pool, but sets the value - * attribute to default (0). The value is fetched within the read() operation. - * \param set_id This is the id in the global data pool this instance of the access class - * corresponds to. - * \param dataSet The data set in which the variable shall register itself. If NULL, - * the variable is not registered. - * \param setWritable If this flag is set to true, changes in the value attribute can be - * written back to the data pool, otherwise not. - */ - PoolVariable(uint32_t set_id, DataSetIF *dataSet, - ReadWriteMode_t setReadWriteMode) : - dataPoolId(set_id), valid(PoolVariableIF::INVALID), readWriteMode( - setReadWriteMode), value(0) { - if (dataSet != NULL) { - dataSet->registerVariable(this); - } - } - /** - * Copy ctor to copy classes containing Pool Variables. - */ - PoolVariable(const PoolVariable &rhs) : - dataPoolId(rhs.dataPoolId), valid(rhs.valid), readWriteMode( - rhs.readWriteMode), value(rhs.value) { - } - - /** - * \brief The classes destructor is empty. - * \details If commit() was not called, the local value is - * discarded and not written back to the data pool. - */ - ~PoolVariable() { - - } - /** - * \brief This operation returns the data pool id of the variable. - */ - uint32_t getDataPoolId() const { - return dataPoolId; - } - /** - * This operation sets the data pool id of the variable. - * The method is necessary to set id's of data pool member variables with bad initialization. - */ - void setDataPoolId(uint32_t poolId) { - dataPoolId = poolId; - } - /** - * This method returns if the variable is write-only, read-write or read-only. - */ - ReadWriteMode_t getReadWriteMode() const { - return readWriteMode; - } - /** - * \brief With this call, the valid information of the variable is returned. - */ - bool isValid() const { - if (valid) - return true; - else - return false; - } - - uint8_t getValid() { - return valid; - } - - void setValid(uint8_t valid) { - this->valid = valid; - } - - operator T() { - return value; - } - - operator T() const { - return value; - } - - PoolVariable& operator=(T newValue) { - value = newValue; - return *this; - } - - PoolVariable& operator=(PoolVariable newPoolVariable) { - value = newPoolVariable.value; - return *this; - } - - virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, - size_t maxSize, Endianness streamEndianness) const override { - return SerializeAdapter::serialize(&value, buffer, size, maxSize, - streamEndianness); - } - - virtual size_t getSerializedSize() const override { - return SerializeAdapter::getSerializedSize(&value); - } - - virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, - Endianness streamEndianness) override { - return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness); - } -}; - -typedef PoolVariable db_uint8_t; -typedef PoolVariable db_uint16_t; -typedef PoolVariable db_uint32_t; -typedef PoolVariable db_int8_t; -typedef PoolVariable db_int16_t; -typedef PoolVariable db_int32_t; -typedef PoolVariable db_bool_t; -typedef PoolVariable db_float_t; -typedef PoolVariable db_double_t; -//Alternative (but I thing this is not as useful: code duplication, differences too small): - -//template -//class PoolReader : public PoolVariableIF { -//private: -// uint32_t parameter_id; -// uint8_t valid; -//public: -// T value; -// PoolReader( uint32_t set_id, DataSetIF* set ) : parameter_id(set_id), valid(false), value(0) { -// set->registerVariable( this ); -// } -// -// ~PoolReader() {}; -// -// uint8_t commit() { -// return HasReturnvaluesIF::RETURN_OK; -// } -// -// uint8_t read() { -// PoolEntry* read_out = ::dataPool.getData( parameter_id, 1 ); -// if ( read_out != NULL ) { -// valid = read_out->valid; -// value = *(read_out->address); -// return HasReturnvaluesIF::RETURN_OK; -// } else { -// value = 0; -// valid = false; -// return CHECKOUT_FAILED; -// } -// } -// uint32_t getParameterId() { return parameter_id; } -// bool isWritable() { return false; }; -// bool isValid() { if (valid) return true; else return false; } -//}; -// -//template -//class PoolWriter : public PoolVariableIF { -//private: -// uint32_t parameter_id; -//public: -// T value; -// PoolWriter( uint32_t set_id, DataSetIF* set ) : parameter_id(set_id), value(0) { -// set->registerVariable( this ); -// } -// -// ~PoolWriter() {}; -// -// uint8_t commit() { -// PoolEntry* write_back = ::dataPool.getData( parameter_id, 1 ); -// if ( write_back != NULL ) { -// write_back->valid = true; -// *(write_back->address) = value; -// return HasReturnvaluesIF::RETURN_OK; -// } else { -// return CHECKOUT_FAILED; -// } -// } -// uint8_t read() { -// PoolEntry* read_out = ::dataPool.getData( parameter_id, 1 ); -// if ( read_out != NULL ) { -// value = *(read_out->address); -// return HasReturnvaluesIF::RETURN_OK; -// } else { -// value = 0; -// return CHECKOUT_FAILED; -// } -// } -// uint32_t getParameterId() { return parameter_id; } -// bool isWritable() { return true; }; -// bool isValid() { return false; } -//}; - -#endif /* POOLVARIABLE_H_ */ diff --git a/datapool/PoolVariableIF.h b/datapool/PoolVariableIF.h index f47173df..cd15f744 100644 --- a/datapool/PoolVariableIF.h +++ b/datapool/PoolVariableIF.h @@ -1,71 +1,99 @@ -/* - * \file PoolVariableIF.h - * - * \brief This file contains the interface definition for pool variables. - * - * \date 10/17/2012 - * - * \author Bastian Baetz - */ - -#ifndef POOLVARIABLEIF_H_ -#define POOLVARIABLEIF_H_ +#ifndef FSFW_DATAPOOL_POOLVARIABLEIF_H_ +#define FSFW_DATAPOOL_POOLVARIABLEIF_H_ #include "../returnvalues/HasReturnvaluesIF.h" #include "../serialize/SerializeIF.h" /** - * \brief This interface is used to control local data pool variable representations. - * - * \details To securely handle data pool variables, all pool entries are locally managed by - * data pool variable access classes, which are called pool variables. To ensure a - * common state of a set of variables needed in a function, these local pool variables - * again are managed by other classes, e.g. the DataSet. This interface provides unified - * access to local pool variables for such manager classes. - * \ingroup data_pool + * @brief This interface is used to control data pool + * variable representations. + * @details + * To securely handle data pool variables, all pool entries are locally + * managed by data pool variable access classes, which are called pool + * variables. To ensure a common state of a set of variables needed in a + * function, these local pool variables again are managed by other classes, + * like the DataSet classes. This interface provides unified access to + * local pool variables for such manager classes. + * @author Bastian Baetz + * @ingroup data_pool */ class PoolVariableIF : public SerializeIF { - friend class DataSet; -protected: - /** - * \brief The commit call shall write back a newly calculated local value to the data pool. - */ - virtual ReturnValue_t commit() = 0; - /** - * \brief The read call shall read the value of this parameter from the data pool and store - * the content locally. - */ - virtual ReturnValue_t read() = 0; + friend class PoolDataSetBase; + friend class GlobDataSet; + friend class LocalPoolDataSetBase; public: - static const uint8_t VALID = 1; - static const uint8_t INVALID = 0; - static const uint32_t NO_PARAMETER = 0; + static constexpr uint8_t INTERFACE_ID = CLASS_ID::POOL_VARIABLE_IF; + static constexpr ReturnValue_t INVALID_READ_WRITE_MODE = MAKE_RETURN_CODE(0xA0); + + static constexpr bool VALID = 1; + static constexpr bool INVALID = 0; + static constexpr uint32_t NO_PARAMETER = 0xffffffff; + enum ReadWriteMode_t { VAR_READ, VAR_WRITE, VAR_READ_WRITE }; /** - * \brief This is an empty virtual destructor, as it is proposed for C++ interfaces. + * @brief This is an empty virtual destructor, + * as it is proposed for C++ interfaces. */ - virtual ~PoolVariableIF() { - } + virtual ~PoolVariableIF() {} /** - * \brief This method returns if the variable is write-only, read-write or read-only. + * @brief This method returns if the variable is write-only, + * read-write or read-only. */ virtual ReadWriteMode_t getReadWriteMode() const = 0; /** - * \brief This operation shall return the data pool id of the variable. + * @brief This operation shall return the data pool id of the variable. */ virtual uint32_t getDataPoolId() const = 0; /** - * \brief With this call, the valid information of the variable is returned. + * @brief With this call, the valid information of the + * variable is returned. */ virtual bool isValid() const = 0; /** - * \brief With this call, the valid information of the variable is set. + * @brief With this call, the valid information of the variable is set. */ - virtual void setValid(uint8_t validity) = 0; + virtual void setValid(bool validity) = 0; + /** + * @brief The commit call shall write back a newly calculated local + * value to the data pool. + * @details + * It is assumed that these calls are implemented in a thread-safe manner! + */ + virtual ReturnValue_t commit(uint32_t lockTimeout) = 0; + /** + * @brief The read call shall read the value of this parameter from + * the data pool and store the content locally. + * @details + * It is assumbed that these calls are implemented in a thread-safe manner! + */ + virtual ReturnValue_t read(uint32_t lockTimeout) = 0; + +protected: + + /** + * @brief Same as commit with the difference that comitting will be + * performed without a lock + * @return + * This can be used if the lock protection is handled externally + * to avoid the overhead of locking and unlocking consecutively. + * Declared protected to avoid free public usage. + */ + virtual ReturnValue_t readWithoutLock() = 0; + /** + * @brief Same as commit with the difference that comitting will be + * performed without a lock + * @return + * This can be used if the lock protection is handled externally + * to avoid the overhead of locking and unlocking consecutively. + * Declared protected to avoid free public usage. + */ + virtual ReturnValue_t commitWithoutLock() = 0; }; -#endif /* POOLVARIABLEIF_H_ */ +using pool_rwm_t = PoolVariableIF::ReadWriteMode_t; + +#endif /* FSFW_DATAPOOL_POOLVARIABLEIF_H_ */ diff --git a/datapool/PoolVector.h b/datapool/PoolVector.h deleted file mode 100644 index d4ca0842..00000000 --- a/datapool/PoolVector.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - * \file PoolVector.h - * - * \brief This file contains the PoolVector class, the header only class to handle data pool vectors. - * - * \date 10/23/2012 - * - * \author Bastian Baetz - */ - -#ifndef POOLVECTOR_H_ -#define POOLVECTOR_H_ - -#include "DataSetIF.h" -#include "PoolEntry.h" -#include "PoolVariableIF.h" -#include "../serialize/SerializeAdapter.h" -#include "../serviceinterface/ServiceInterfaceStream.h" - -/** - * \brief This is the access class for array-type data pool entries. - * - * \details To ensure safe usage of the data pool, operation is not done directly on the data pool - * entries, but on local copies. This class provides simple type- and length-safe access - * to vector-style data pool entries (i.e. entries with length > 1). - * The class can be instantiated as read-write and read only. - * It provides a commit-and-roll-back semantic, which means that no array entry in - * the data pool is changed until the commit call is executed. - * There are two template parameters: - * \tparam T This template parameter specifies the data type of an array entry. Currently, all - * plain data types are supported, but in principle any type is possible. - * \tparam vector_size This template parameter specifies the vector size of this entry. - * Using a template parameter for this is not perfect, but avoids dynamic memory allocation. - * \ingroup data_pool - */ -template -class PoolVector: public PoolVariableIF { -private: - /** - * \brief To access the correct data pool entry on read and commit calls, the data pool id - * is stored. - */ - uint32_t dataPoolId; - /** - * \brief The valid information as it was stored in the data pool is copied to this attribute. - */ - uint8_t valid; - /** - * \brief The information whether the class is read-write or read-only is stored here. - */ - ReadWriteMode_t readWriteMode; - -protected: - /** - * \brief This is a call to read the array's values from the global data pool. - * \details When executed, this operation tries to fetch the pool entry with matching - * data pool id from the global data pool and copies all array values and the valid - * information to its local attributes. In case of a failure (wrong type, size or - * pool id not found), the variable is set to zero and invalid. - * The operation does NOT provide any mutual exclusive protection by itself. - */ - ReturnValue_t read() { - PoolEntry* read_out = ::dataPool.getData(this->dataPoolId, - vector_size); - if (read_out != NULL) { - this->valid = read_out->valid; - memcpy(this->value, read_out->address, read_out->getByteSize()); - - return HasReturnvaluesIF::RETURN_OK; - - } else { - memset(this->value, 0, vector_size * sizeof(T)); - sif::error << "PoolVector: read of DP Variable 0x" << std::hex - << dataPoolId << std::dec << " failed." << std::endl; - this->valid = INVALID; - return HasReturnvaluesIF::RETURN_FAILED; - } - } - /** - * \brief The commit call copies the array values back to the data pool. - * \details It checks type and size, as well as if the variable is writable. If so, - * the value is copied and the valid flag is automatically set to "valid". - * The operation does NOT provide any mutual exclusive protection by itself. - * - */ - ReturnValue_t commit() { - PoolEntry* write_back = ::dataPool.getData(this->dataPoolId, - vector_size); - if ((write_back != NULL) && (this->readWriteMode != VAR_READ)) { - write_back->valid = valid; - memcpy(write_back->address, this->value, write_back->getByteSize()); - return HasReturnvaluesIF::RETURN_OK; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } - } -public: - /** - * \brief This is the local copy of the data pool entry. - * \detials The user can work on this attribute - * just like he would on a local array of this type. - */ - T value[vector_size]; - /** - * \brief In the constructor, the variable can register itself in a DataSet (if not NULL is - * passed). - * \details It DOES NOT fetch the current value from the data pool, but sets the value - * attribute to default (0). The value is fetched within the read() operation. - * \param set_id This is the id in the global data pool this instance of the access class - * corresponds to. - * \param dataSet The data set in which the variable shall register itself. If NULL, - * the variable is not registered. - * \param setWritable If this flag is set to true, changes in the value attribute can be - * written back to the data pool, otherwise not. - */ - PoolVector(uint32_t set_id, DataSetIF* set, - ReadWriteMode_t setReadWriteMode) : - dataPoolId(set_id), valid(false), readWriteMode(setReadWriteMode) { - memset(this->value, 0, vector_size * sizeof(T)); - if (set != NULL) { - set->registerVariable(this); - } - } - /** - * Copy ctor to copy classes containing Pool Variables. - */ -// PoolVector(const PoolVector& rhs) { -// PoolVector temp(rhs.dataPoolId, rhs.) -// memcpy(value, rhs.value, sizeof(T)*vector_size); -// } - /** - * \brief The classes destructor is empty. - * \details If commit() was not called, the local value is - * discarded and not written back to the data pool. - */ - ~PoolVector() { - } - ; - /** - * \brief The operation returns the number of array entries in this variable. - */ - uint8_t getSize() { - return vector_size; - } - /** - * \brief This operation returns the data pool id of the variable. - */ - uint32_t getDataPoolId() const { - return dataPoolId; - } - /** - * This operation sets the data pool id of the variable. - * The method is necessary to set id's of data pool member variables with bad initialization. - */ - void setDataPoolId(uint32_t poolId) { - dataPoolId = poolId; - } - /** - * This method returns if the variable is write-only, read-write or read-only. - */ - ReadWriteMode_t getReadWriteMode() const { - return readWriteMode; - } - ; - /** - * \brief With this call, the valid information of the variable is returned. - */ - bool isValid() const { - if (valid != INVALID) - return true; - else - return false; - } - - void setValid(uint8_t valid) { - this->valid = valid; - } - - uint8_t getValid() { - return valid; - } - - T &operator [](int i) { - return value[i]; - } - - const T &operator [](int i) const { - return value[i]; - } - - PoolVector &operator=( - PoolVector newPoolVector) { - - for (uint16_t i = 0; i < vector_size; i++) { - this->value[i] = newPoolVector.value[i]; - } - return *this; - } - - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, - size_t maxSize, Endianness streamEndianness) const { - uint16_t i; - ReturnValue_t result; - for (i = 0; i < vector_size; i++) { - result = SerializeAdapter::serialize(&(value[i]), buffer, size, - maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - } - return result; - } - - virtual size_t getSerializedSize() const { - return vector_size * SerializeAdapter::getSerializedSize(value); - } - - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) { - uint16_t i; - ReturnValue_t result; - for (i = 0; i < vector_size; i++) { - result = SerializeAdapter::deSerialize(&(value[i]), buffer, size, - streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - } - return result; - } -}; - -#endif /* POOLVECTOR_H_ */ diff --git a/datapool/SharedDataSetIF.h b/datapool/SharedDataSetIF.h new file mode 100644 index 00000000..b8d98794 --- /dev/null +++ b/datapool/SharedDataSetIF.h @@ -0,0 +1,14 @@ +#ifndef FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_ +#define FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_ +#include "PoolDataSetIF.h" + +class SharedDataSetIF: public PoolDataSetIF { +public: + virtual ~SharedDataSetIF() {}; + +private: + virtual ReturnValue_t lockDataset(dur_millis_t mutexTimeout) = 0; + virtual ReturnValue_t unlockDataset() = 0; +}; + +#endif /* FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_ */ diff --git a/datapool/ControllerSet.cpp b/datapoolglob/ControllerSet.cpp similarity index 79% rename from datapool/ControllerSet.cpp rename to datapoolglob/ControllerSet.cpp index 6339034c..54fc6e8c 100644 --- a/datapool/ControllerSet.cpp +++ b/datapoolglob/ControllerSet.cpp @@ -1,4 +1,4 @@ -#include "ControllerSet.h" +#include ControllerSet::ControllerSet() { diff --git a/datapoolglob/ControllerSet.h b/datapoolglob/ControllerSet.h new file mode 100644 index 00000000..5da11397 --- /dev/null +++ b/datapoolglob/ControllerSet.h @@ -0,0 +1,15 @@ +#ifndef FSFW_DATAPOOLGLOB_CONTROLLERSET_H_ +#define FSFW_DATAPOOLGLOB_CONTROLLERSET_H_ + +#include "../datapoolglob/GlobalDataSet.h" + +class ControllerSet :public GlobDataSet { +public: + ControllerSet(); + virtual ~ControllerSet(); + + virtual void setToDefault() = 0; + void setInvalid(); +}; + +#endif /* FSFW_DATAPOOLGLOB_CONTROLLERSET_H_ */ diff --git a/datapool/DataPoolAdmin.cpp b/datapoolglob/DataPoolAdmin.cpp similarity index 94% rename from datapool/DataPoolAdmin.cpp rename to datapoolglob/DataPoolAdmin.cpp index f298d530..6ede0841 100644 --- a/datapool/DataPoolAdmin.cpp +++ b/datapoolglob/DataPoolAdmin.cpp @@ -1,7 +1,8 @@ -#include "DataPool.h" #include "DataPoolAdmin.h" -#include "DataSet.h" +#include "GlobalDataSet.h" +#include "GlobalDataPool.h" #include "PoolRawAccess.h" + #include "../ipc/CommandMessage.h" #include "../ipc/QueueFactory.h" #include "../parameters/ParameterMessage.h" @@ -40,9 +41,9 @@ ReturnValue_t DataPoolAdmin::executeAction(ActionId_t actionId, uint8_t valid = data[4]; - uint32_t poolId = ::dataPool.PIDToDataPoolId(address); + uint32_t poolId = glob::dataPool.PIDToDataPoolId(address); - DataSet mySet; + GlobDataSet mySet; PoolRawAccess variable(poolId, 0, &mySet, PoolVariableIF::VAR_READ_WRITE); ReturnValue_t status = mySet.read(); if (status != RETURN_OK) { @@ -92,9 +93,9 @@ void DataPoolAdmin::handleCommand() { ReturnValue_t DataPoolAdmin::handleMemoryLoad(uint32_t address, const uint8_t* data, size_t size, uint8_t** dataPointer) { - uint32_t poolId = ::dataPool.PIDToDataPoolId(address); - uint8_t arrayIndex = ::dataPool.PIDToArrayIndex(address); - DataSet testSet; + uint32_t poolId = glob::dataPool.PIDToDataPoolId(address); + uint8_t arrayIndex = glob::dataPool.PIDToArrayIndex(address); + GlobDataSet testSet; PoolRawAccess varToGetSize(poolId, arrayIndex, &testSet, PoolVariableIF::VAR_READ); ReturnValue_t status = testSet.read(); @@ -113,7 +114,7 @@ ReturnValue_t DataPoolAdmin::handleMemoryLoad(uint32_t address, const uint8_t* readPosition = data; for (; size > 0; size -= typeSize) { - DataSet rawSet; + GlobDataSet rawSet; PoolRawAccess variable(poolId, arrayIndex, &rawSet, PoolVariableIF::VAR_READ_WRITE); status = rawSet.read(); @@ -131,9 +132,9 @@ ReturnValue_t DataPoolAdmin::handleMemoryLoad(uint32_t address, ReturnValue_t DataPoolAdmin::handleMemoryDump(uint32_t address, size_t size, uint8_t** dataPointer, uint8_t* copyHere) { - uint32_t poolId = ::dataPool.PIDToDataPoolId(address); - uint8_t arrayIndex = ::dataPool.PIDToArrayIndex(address); - DataSet testSet; + uint32_t poolId = glob::dataPool.PIDToDataPoolId(address); + uint8_t arrayIndex = glob::dataPool.PIDToArrayIndex(address); + GlobDataSet testSet; PoolRawAccess varToGetSize(poolId, arrayIndex, &testSet, PoolVariableIF::VAR_READ); ReturnValue_t status = testSet.read(); @@ -146,7 +147,7 @@ ReturnValue_t DataPoolAdmin::handleMemoryDump(uint32_t address, size_t size, } uint8_t* ptrToCopy = copyHere; for (; size > 0; size -= typeSize) { - DataSet rawSet; + GlobDataSet rawSet; PoolRawAccess variable(poolId, arrayIndex, &rawSet, PoolVariableIF::VAR_READ); status = rawSet.read(); diff --git a/datapool/DataPoolAdmin.h b/datapoolglob/DataPoolAdmin.h similarity index 92% rename from datapool/DataPoolAdmin.h rename to datapoolglob/DataPoolAdmin.h index e2d1e9e1..d8871b65 100644 --- a/datapool/DataPoolAdmin.h +++ b/datapoolglob/DataPoolAdmin.h @@ -1,15 +1,17 @@ -#ifndef DATAPOOLADMIN_H_ -#define DATAPOOLADMIN_H_ +#ifndef FSFW_DATAPOOLGLOB_DATAPOOLADMIN_H_ +#define FSFW_DATAPOOLGLOB_DATAPOOLADMIN_H_ + +#include "DataPoolParameterWrapper.h" -#include "../memory/MemoryHelper.h" -#include "../action/HasActionsIF.h" -#include "../action/SimpleActionHelper.h" #include "../objectmanager/SystemObject.h" #include "../returnvalues/HasReturnvaluesIF.h" #include "../tasks/ExecutableObjectIF.h" -#include "../parameters/ReceivesParameterMessagesIF.h" -#include "DataPoolParameterWrapper.h" +#include "../action/HasActionsIF.h" #include "../ipc/MessageQueueIF.h" +#include "../parameters/ReceivesParameterMessagesIF.h" +#include "../action/SimpleActionHelper.h" +#include "../memory/MemoryHelper.h" + class DataPoolAdmin: public HasActionsIF, public ExecutableObjectIF, @@ -55,4 +57,4 @@ private: Command_t initialCommand); }; -#endif /* DATAPOOLADMIN_H_ */ +#endif /* FSFW_DATAPOOLGLOB_DATAPOOLADMIN_H_ */ diff --git a/datapool/DataPoolParameterWrapper.cpp b/datapoolglob/DataPoolParameterWrapper.cpp similarity index 95% rename from datapool/DataPoolParameterWrapper.cpp rename to datapoolglob/DataPoolParameterWrapper.cpp index 79367405..3a57d90d 100644 --- a/datapool/DataPoolParameterWrapper.cpp +++ b/datapoolglob/DataPoolParameterWrapper.cpp @@ -1,10 +1,8 @@ -#include "DataPoolParameterWrapper.h" - -//for returncodes +#include "../datapoolglob/GlobalDataSet.h" +#include "../datapoolglob/DataPoolParameterWrapper.h" +#include "../datapoolglob/PoolRawAccess.h" #include "../parameters/HasParametersIF.h" -#include "DataSet.h" -#include "PoolRawAccess.h" DataPoolParameterWrapper::DataPoolParameterWrapper() : type(Type::UNKNOWN_TYPE), rows(0), columns(0), poolId( @@ -20,7 +18,7 @@ ReturnValue_t DataPoolParameterWrapper::set(uint8_t domainId, uint16_t parameterId) { poolId = (domainId << 16) + parameterId; - DataSet mySet; + GlobDataSet mySet; PoolRawAccess raw(poolId, 0, &mySet, PoolVariableIF::VAR_READ); ReturnValue_t status = mySet.read(); if (status != HasReturnvaluesIF::RETURN_OK) { @@ -57,7 +55,7 @@ ReturnValue_t DataPoolParameterWrapper::serialize(uint8_t** buffer, } for (uint8_t index = 0; index < rows; index++){ - DataSet mySet; + GlobDataSet mySet; PoolRawAccess raw(poolId, index, &mySet,PoolVariableIF::VAR_READ); mySet.read(); result = raw.serialize(buffer,size,maxSize,streamEndianness); @@ -94,7 +92,7 @@ ReturnValue_t DataPoolParameterWrapper::deSerializeData(uint8_t startingRow, for (uint8_t fromRow = 0; fromRow < fromRows; fromRow++) { - DataSet mySet; + GlobDataSet mySet; PoolRawAccess raw(poolId, startingRow + fromRow, &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); diff --git a/datapool/DataPoolParameterWrapper.h b/datapoolglob/DataPoolParameterWrapper.h similarity index 100% rename from datapool/DataPoolParameterWrapper.h rename to datapoolglob/DataPoolParameterWrapper.h diff --git a/datapoolglob/GlobalDataPool.cpp b/datapoolglob/GlobalDataPool.cpp new file mode 100644 index 00000000..afb27b77 --- /dev/null +++ b/datapoolglob/GlobalDataPool.cpp @@ -0,0 +1,133 @@ +#include "../datapoolglob/GlobalDataPool.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../ipc/MutexFactory.h" + +GlobalDataPool::GlobalDataPool( + void(*initFunction)(GlobPoolMap* pool_map)) { + mutex = MutexFactory::instance()->createMutex(); + if (initFunction != NULL ) { + initFunction( &this->globDataPool ); + } +} + +GlobalDataPool::~GlobalDataPool() { + MutexFactory::instance()->deleteMutex(mutex); + for(GlobPoolMapIter it = this->globDataPool.begin(); + it != this->globDataPool.end(); ++it ) + { + delete it->second; + } +} + +// The function checks PID, type and array length before returning a copy of +// the PoolEntry. In failure case, it returns a temp-Entry with size 0 and NULL-ptr. +template PoolEntry* GlobalDataPool::getData( uint32_t data_pool_id, + uint8_t sizeOrPosition ) { + GlobPoolMapIter it = this->globDataPool.find( data_pool_id ); + if ( it != this->globDataPool.end() ) { + PoolEntry* entry = dynamic_cast< PoolEntry* >( it->second ); + if (entry != nullptr ) { + if ( sizeOrPosition <= entry->length ) { + return entry; + } + } + } + return nullptr; +} + +PoolEntryIF* GlobalDataPool::getRawData( uint32_t data_pool_id ) { + GlobPoolMapIter it = this->globDataPool.find( data_pool_id ); + if ( it != this->globDataPool.end() ) { + return it->second; + } else { + return nullptr; + } +} + +ReturnValue_t GlobalDataPool::unlockDataPool() { + ReturnValue_t status = mutex->unlockMutex(); + if(status != RETURN_OK) { + sif::error << "DataPool::DataPool: unlock of mutex failed with" + " error code: " << status << std::endl; + } + return status; +} + +ReturnValue_t GlobalDataPool::lockDataPool(uint32_t timeoutMs) { + ReturnValue_t status = mutex->lockMutex(MutexIF::TimeoutType::WAITING, + timeoutMs); + if(status != RETURN_OK) { + sif::error << "DataPool::DataPool: lock of mutex failed " + "with error code: " << status << std::endl; + } + return status; +} + +void GlobalDataPool::print() { + sif::debug << "DataPool contains: " << std::endl; + std::map::iterator dataPoolIt; + dataPoolIt = this->globDataPool.begin(); + while( dataPoolIt != this->globDataPool.end() ) { + sif::debug << std::hex << dataPoolIt->first << std::dec << " |"; + dataPoolIt->second->print(); + dataPoolIt++; + } +} + +uint32_t GlobalDataPool::PIDToDataPoolId(uint32_t parameter_id) { + return (parameter_id >> 8) & 0x00FFFFFF; +} + +uint8_t GlobalDataPool::PIDToArrayIndex(uint32_t parameter_id) { + return (parameter_id & 0x000000FF); +} + +uint32_t GlobalDataPool::poolIdAndPositionToPid(uint32_t poolId, uint8_t index) { + return (poolId << 8) + index; +} + + +//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 GlobalDataPool::getType(uint32_t parameter_id, Type* type) { + GlobPoolMapIter it = this->globDataPool.find( PIDToDataPoolId(parameter_id)); + if ( it != this->globDataPool.end() ) { + *type = it->second->getType(); + return RETURN_OK; + } else { + *type = Type::UNKNOWN_TYPE; + return RETURN_FAILED; + } +} + +bool GlobalDataPool::exists(uint32_t parameterId) { + uint32_t poolId = PIDToDataPoolId(parameterId); + uint32_t index = PIDToArrayIndex(parameterId); + GlobPoolMapIter it = this->globDataPool.find( poolId ); + if (it != globDataPool.end()) { + if (it->second->getSize() >= index) { + return true; + } + } + return false; +} + +template PoolEntry* GlobalDataPool::getData( + uint32_t data_pool_id, uint8_t size ); +template PoolEntry* GlobalDataPool::getData( + uint32_t data_pool_id, uint8_t size ); +template PoolEntry* GlobalDataPool::getData( + uint32_t data_pool_id, uint8_t size ); +template PoolEntry* GlobalDataPool::getData( + uint32_t data_pool_id, uint8_t size); +template PoolEntry* GlobalDataPool::getData( + uint32_t data_pool_id, uint8_t size ); +template PoolEntry* GlobalDataPool::getData( + uint32_t data_pool_id, uint8_t size ); +template PoolEntry* GlobalDataPool::getData( + uint32_t data_pool_id, uint8_t size ); +template PoolEntry* GlobalDataPool::getData( + uint32_t data_pool_id, uint8_t size ); +template PoolEntry* GlobalDataPool::getData( + uint32_t data_pool_id, uint8_t size); diff --git a/datapoolglob/GlobalDataPool.h b/datapoolglob/GlobalDataPool.h new file mode 100644 index 00000000..ce5b132c --- /dev/null +++ b/datapoolglob/GlobalDataPool.h @@ -0,0 +1,149 @@ +#ifndef GLOBALDATAPOOL_H_ +#define GLOBALDATAPOOL_H_ + +#include "../datapool/PoolEntry.h" +#include "../globalfunctions/Type.h" +#include "../ipc/MutexIF.h" +#include + +/** + * @defgroup data_pool Global data pool + * This is the group, where all classes associated with global + * data pool handling belong to. + * This includes classes to access Data Pool variables. + */ + +/** + * Typedefs for the global pool representations + */ +using GlobPoolMap = std::map; +using GlobPoolMapIter = GlobPoolMap::iterator; + +/** + * @brief This class represents the OBSW global data-pool. + * + * @details + * All variables are registered and space is allocated in an initialization + * function, which is passed do the constructor. Space for the variables is + * allocated on the heap (with a new call). + * + * The data is found by a data pool id, which uniquely represents a variable. + * Data pool variables should be used with a blackboard logic in mind, + * which means read data is valid (if flagged so), + * but not necessarily up-to-date. + * + * Variables are either single values or arrays. + * @author Bastian Baetz + * @ingroup data_pool + */ +class GlobalDataPool : public HasReturnvaluesIF { +private: + /** + * @brief This is the actual data pool itself. + * @details It is represented by a map with the data pool id as index + * and a pointer to a single PoolEntry as value. + */ + GlobPoolMap globDataPool; + + /** + * @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. + */ + MutexIF* mutex; +public: + /** + * @brief In the classes constructor, + * the passed initialization function is called. + * @details + * To enable filling the pool, a pointer to the map is passed, + * allowing direct access to the pool's content. + * On runtime, adding or removing variables is forbidden. + */ + GlobalDataPool( void ( *initFunction )( GlobPoolMap* pool_map ) ); + + /** + * @brief The destructor iterates through the data_pool map and + * calls all entries destructors to clean up the heap. + */ + ~GlobalDataPool(); + + /** + * @brief This is the default call to access the pool. + * @details + * A pointer to the PoolEntry object is returned. + * The call checks data pool id, type and array size. + * Returns NULL in case of failure. + * @param data_pool_id The data pool id to search. + * @param sizeOrPosition The array size (not byte size!) of the pool entry, + * or the position the user wants to read. + * If smaller than the entry size, everything's ok. + */ + template PoolEntry* getData( uint32_t data_pool_id, + uint8_t sizeOrPosition ); + + /** + * @brief An alternative call to get a data pool entry in case the type is not implicitly known + * (i.e. in Housekeeping Telemetry). + * @details It returns a basic interface and does NOT perform + * a size check. The caller has to assure he does not copy too much data. + * Returns NULL in case the entry is not found. + * @param data_pool_id The data pool id to search. + */ + PoolEntryIF* getRawData( uint32_t data_pool_id ); + /** + * @brief This is a small helper function to facilitate locking the global data pool. + * @details It fetches the pool's mutex id and tries to acquire the mutex. + */ + ReturnValue_t lockDataPool(uint32_t timeoutMs = MutexIF::BLOCKING); + /** + * @brief This is a small helper function to facilitate unlocking the global data pool. + * @details It fetches the pool's mutex id and tries to free the mutex. + */ + ReturnValue_t unlockDataPool(); + /** + * @brief The print call is a simple debug method. + * @details It prints the current content of the data pool. + * It iterates through the data_pool map and calls each entry's print() method. + */ + void print(); + /** + * Extracts the data pool id from a SCOS 2000 PID. + * @param parameter_id The passed Parameter ID. + * @return The data pool id as used within the OBSW. + */ + static uint32_t PIDToDataPoolId( uint32_t parameter_id ); + /** + * Extracts an array index out of a SCOS 2000 PID. + * @param parameter_id The passed Parameter ID. + * @return The index of the corresponding data pool entry. + */ + static uint8_t PIDToArrayIndex( uint32_t parameter_id ); + /** + * Retransforms a data pool id and an array index to a SCOS 2000 PID. + */ + static uint32_t poolIdAndPositionToPid( uint32_t poolId, uint8_t index ); + + /** + * 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. + * @param parameterId The PID (not pool id!) of a parameter. + * @return true if exists, false else. + */ + bool exists(uint32_t parameterId); +}; + +//We assume someone globally instantiates a DataPool. +namespace glob { +extern GlobalDataPool dataPool; +} + +#endif /* DATAPOOL_H_ */ diff --git a/datapoolglob/GlobalDataSet.cpp b/datapoolglob/GlobalDataSet.cpp new file mode 100644 index 00000000..1e99f805 --- /dev/null +++ b/datapoolglob/GlobalDataSet.cpp @@ -0,0 +1,48 @@ +#include "../datapoolglob/GlobalDataPool.h" +#include "../datapoolglob/GlobalDataSet.h" +#include "../serviceinterface/ServiceInterfaceStream.h" + +GlobDataSet::GlobDataSet(): PoolDataSetBase( + reinterpret_cast(®isteredVariables), + DATA_SET_MAX_SIZE) {} + +// Don't do anything with your variables, they are dead already! +// (Destructor is already called) +GlobDataSet::~GlobDataSet() {} + +ReturnValue_t GlobDataSet::commit(bool valid, uint32_t lockTimeout) { + setEntriesValid(valid); + setSetValid(valid); + return commit(lockTimeout); +} + +ReturnValue_t GlobDataSet::commit(uint32_t lockTimeout) { + return PoolDataSetBase::commit(lockTimeout); +} + +bool GlobDataSet::isValid() const { + return this->valid; +} + +ReturnValue_t GlobDataSet::unlockDataPool() { + return glob::dataPool.unlockDataPool(); +} + +ReturnValue_t GlobDataSet::lockDataPool(uint32_t timeoutMs) { + return glob::dataPool.lockDataPool(timeoutMs); +} + +void GlobDataSet::setEntriesValid(bool valid) { + for (uint16_t count = 0; count < fillCount; count++) { + if (registeredVariables[count]->getReadWriteMode() + != PoolVariableIF::VAR_READ) { + registeredVariables[count]->setValid(valid); + } + } +} + +void GlobDataSet::setSetValid(bool valid) { + this->valid = valid; +} + + diff --git a/datapoolglob/GlobalDataSet.h b/datapoolglob/GlobalDataSet.h new file mode 100644 index 00000000..2f0edbd5 --- /dev/null +++ b/datapoolglob/GlobalDataSet.h @@ -0,0 +1,98 @@ +#ifndef FRAMEWORK_DATAPOOLGLOB_DATASET_H_ +#define FRAMEWORK_DATAPOOLGLOB_DATASET_H_ + +#include "../datapool/PoolDataSetBase.h" + +/** + * @brief The DataSet class manages a set of locally checked out variables + * for the global data pool. + * @details + * This class uses the read-commit() semantic provided by the DataSetBase class. + * It extends the base class by using the global data pool, + * having a valid state and implementing lock und unlock calls for the global + * datapool. + * + * For more information on how this class works, see the DataSetBase + * documentation. + * @author Bastian Baetz + * @ingroup data_pool + */ +class GlobDataSet: public PoolDataSetBase { +public: + + /** + * @brief Creates an empty GlobDataSet. Use registerVariable or + * supply a pointer to this dataset to PoolVariable + * initializations to register pool variables. + */ + GlobDataSet(); + + /** + * @brief The destructor automatically manages writing the valid + * information of variables. + * @details + * In case the data set was read out, but not committed(indicated by state), + * the destructor parses all variables that are still registered to the set. + * For each, the valid flag in the data pool is set to "invalid". + */ + ~GlobDataSet(); + + /** + * Variant of method above which sets validity of all elements of the set. + * @param valid Validity information from PoolVariableIF. + * @return - @c RETURN_OK if all variables were read successfully. + * - @c COMMITING_WITHOUT_READING if set was not read yet and + * contains non write-only variables + */ + ReturnValue_t commit(bool valid, uint32_t lockTimeout = MutexIF::BLOCKING); + ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; + + /** + * Set all entries + * @param valid + */ + void setSetValid(bool valid); + + bool isValid() const override; + + /** + * Set the valid information of all variables contained in the set which + * are not read-only + * + * @param valid Validity information from PoolVariableIF. + */ + void setEntriesValid(bool valid); + + //!< This definition sets the maximum number of variables to + //! register in one DataSet. + static const uint8_t DATA_SET_MAX_SIZE = 63; + +private: + /** + * If the valid state of a dataset is always relevant to the whole + * data set we can use this flag. + */ + bool valid = false; + + /** + * @brief This is a small helper function to facilitate locking + * the global data pool. + * @details + * It makes use of the lockDataPool method offered by the DataPool class. + */ + ReturnValue_t lockDataPool(uint32_t timeoutMs) override; + /** + * @brief This is a small helper function to facilitate + * unlocking the global data pool + * @details + * It makes use of the freeDataPoolLock method offered by the DataPool class. + */ + ReturnValue_t unlockDataPool() override; + + void handleAlreadyReadDatasetCommit(); + ReturnValue_t handleUnreadDatasetCommit(); + + PoolVariableIF* registeredVariables[DATA_SET_MAX_SIZE]; +}; + +#endif /* FRAMEWORK_DATAPOOLGLOB_DATASET_H_ */ diff --git a/datapoolglob/GlobalPoolVariable.h b/datapoolglob/GlobalPoolVariable.h new file mode 100644 index 00000000..a995bfaf --- /dev/null +++ b/datapoolglob/GlobalPoolVariable.h @@ -0,0 +1,213 @@ +#ifndef GLOBALPOOLVARIABLE_H_ +#define GLOBALPOOLVARIABLE_H_ + +#include "../datapool/DataSetIF.h" +#include "../datapoolglob/GlobalDataPool.h" +#include "../datapool/PoolVariableIF.h" +#include "../datapool/PoolEntry.h" +#include "../serialize/SerializeAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" + +template class PoolVarList; + + +/** + * @brief This is the access class for non-array data pool entries. + * + * @details + * To ensure safe usage of the data pool, operation is not done directly + * on the data pool entries, but on local copies. This class provides simple + * type-safe access to single data pool entries (i.e. entries with length = 1). + * The class can be instantiated as read-write and read only. + * It provides a commit-and-roll-back semantic, which means that the + * variable's value in the data pool is not changed until the + * commit call is executed. + * @tparam T The template parameter sets the type of the variable. + * Currently, all plain data types are supported, but in principle + * any type is possible. + * @ingroup data_pool + */ +template +class GlobPoolVar: public PoolVariableIF { + template friend class PoolVarList; + static_assert(not std::is_same::value, + "Do not use boolean for the PoolEntry type, use uint8_t instead!" + "There is no boolean type in CCSDS."); +public: + /** + * @brief In the constructor, the variable can register itself in a + * DataSet (if nullptr is not passed). + * @details + * It DOES NOT fetch the current value from the data pool, but + * sets the value attribute to default (0). + * The value is fetched within the read() operation. + * @param set_id This is the id in the global data pool + * this instance of the access class corresponds to. + * @param dataSet The data set in which the variable shall register + * itself. If NULL, the variable is not registered. + * @param setWritable If this flag is set to true, changes in the value + * attribute can be written back to the data pool, otherwise not. + */ + GlobPoolVar(uint32_t set_id, DataSetIF* dataSet, + ReadWriteMode_t setReadWriteMode); + + /** + * @brief This is the local copy of the data pool entry. + * @details The user can work on this attribute + * just like he would on a simple local variable. + */ + T value = 0; + + /** + * @brief Copy ctor to copy classes containing Pool Variables. + * (Robin): This only copies member variables, which is done + * by the default copy ctor. maybe we can ommit this ctor? + */ + GlobPoolVar(const GlobPoolVar& rhs); + + /** + * @brief The classes destructor is empty. + * @details If commit() was not called, the local value is + * discarded and not written back to the data pool. + */ + ~GlobPoolVar() {} + + /** + * @brief This is a call to read the value from the global data pool. + * @details + * When executed, this operation tries to fetch the pool entry with matching + * data pool id from the global data pool and copies the value and the valid + * information to its local attributes. In case of a failure (wrong type or + * pool id not found), the variable is set to zero and invalid. + * The read call is protected with a lock. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. + */ + ReturnValue_t read(uint32_t lockTimeout) override; + /** + * @brief The commit call writes back the variable's value to the data pool. + * @details + * It checks type and size, as well as if the variable is writable. If so, + * the value is copied and the valid flag is automatically set to "valid". + * The operation does NOT provide any mutual exclusive protection by itself. + * The commit call is protected with a lock. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. + */ + ReturnValue_t commit(uint32_t lockTimeout) override; + +protected: + /** + * @brief Like #read, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t readWithoutLock() override; + /** + * @brief Like #commit, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t commitWithoutLock() override; + /** + * @brief To access the correct data pool entry on read and commit calls, + * the data pool is stored. + */ + uint32_t dataPoolId; + + /** + * @brief The valid information as it was stored in the data pool is + * copied to this attribute. + */ + uint8_t valid; + + /** + * @brief The information whether the class is read-write or read-only + * is stored here. + */ + pool_rwm_t readWriteMode; + + /** + * Empty ctor for List initialization + */ + GlobPoolVar(); +public: + /** + * \brief This operation returns the data pool id of the variable. + */ + uint32_t getDataPoolId() const override; + + /** + * This method returns if the variable is write-only, read-write or read-only. + */ + ReadWriteMode_t getReadWriteMode() const override; + /** + * This operation sets the data pool id of the variable. + * The method is necessary to set id's of data pool member variables with bad initialization. + */ + void setDataPoolId(uint32_t poolId); + + /** + * \brief With this call, the valid information of the variable is returned. + */ + bool isValid() const override; + + uint8_t getValid(); + + void setValid(bool valid) override; + + operator T() { + return value; + } + + operator T() const { + return value; + } + + GlobPoolVar &operator=(T newValue) { + value = newValue; + return *this; + } + + GlobPoolVar &operator=(GlobPoolVar newPoolVariable) { + value = newPoolVariable.value; + return *this; + } + + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + const size_t max_size, + SerializeIF::Endianness streamEndianness) const override { + return SerializeAdapter::serialize(&value, buffer, size, max_size, + streamEndianness); + } + + virtual size_t getSerializedSize() const { + return SerializeAdapter::getSerializedSize(&value); + } + + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) { + return SerializeAdapter::deSerialize(&value, buffer, size, + streamEndianness); + } +}; + +#include "../datapoolglob/GlobalPoolVariable.tpp" + +typedef GlobPoolVar gp_bool_t; +typedef GlobPoolVar gp_uint8_t; +typedef GlobPoolVar gp_uint16_t; +typedef GlobPoolVar gp_uint32_t; +typedef GlobPoolVar gp_int8_t; +typedef GlobPoolVar gp_int16_t; +typedef GlobPoolVar gp_int32_t; +typedef GlobPoolVar gp_float_t; +typedef GlobPoolVar gp_double_t; + +#endif /* POOLVARIABLE_H_ */ diff --git a/datapoolglob/GlobalPoolVariable.tpp b/datapoolglob/GlobalPoolVariable.tpp new file mode 100644 index 00000000..d61d605d --- /dev/null +++ b/datapoolglob/GlobalPoolVariable.tpp @@ -0,0 +1,117 @@ +#ifndef GLOBALPOOLVARIABLE_TPP_ +#define GLOBALPOOLVARIABLE_TPP_ + +template +inline GlobPoolVar::GlobPoolVar(uint32_t set_id, + DataSetIF* dataSet, ReadWriteMode_t setReadWriteMode): + dataPoolId(set_id), valid(PoolVariableIF::INVALID), + readWriteMode(setReadWriteMode) +{ + if (dataSet != nullptr) { + dataSet->registerVariable(this); + } +} + +template +inline ReturnValue_t GlobPoolVar::read(uint32_t lockTimeout) { + ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = readWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "GlobPoolVar::read: Could not unlock global data pool" + << std::endl; + } + return result; +} + +template +inline ReturnValue_t GlobPoolVar::commit(uint32_t lockTimeout) { + ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = commitWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "GlobPoolVar::read: Could not unlock global data pool" + << std::endl; + } + return result; +} + +template +inline ReturnValue_t GlobPoolVar::readWithoutLock() { + PoolEntry* read_out = glob::dataPool.getData(dataPoolId, 1); + if (read_out != NULL) { + valid = read_out->valid; + value = *(read_out->address); + return HasReturnvaluesIF::RETURN_OK; + } else { + value = 0; + valid = false; + sif::error << "PoolVariable: read of DP Variable 0x" << std::hex + << dataPoolId << std::dec << " failed." << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +template +inline ReturnValue_t GlobPoolVar::commitWithoutLock() { + PoolEntry* write_back = glob::dataPool.getData(dataPoolId, 1); + if ((write_back != NULL) && (readWriteMode != VAR_READ)) { + write_back->valid = valid; + *(write_back->address) = value; + return HasReturnvaluesIF::RETURN_OK; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +template +inline GlobPoolVar::GlobPoolVar(): + dataPoolId(PoolVariableIF::NO_PARAMETER), + valid(PoolVariableIF::INVALID), + readWriteMode(VAR_READ), value(0) {} + +template +inline GlobPoolVar::GlobPoolVar(const GlobPoolVar& rhs) : + dataPoolId(rhs.dataPoolId), valid(rhs.valid), readWriteMode( + rhs.readWriteMode), value(rhs.value) {} + +template +inline pool_rwm_t GlobPoolVar::getReadWriteMode() const { + return readWriteMode; +} + +template +inline uint32_t GlobPoolVar::getDataPoolId() const { + return dataPoolId; +} + +template +inline void GlobPoolVar::setDataPoolId(uint32_t poolId) { + dataPoolId = poolId; +} + +template +inline bool GlobPoolVar::isValid() const { + if (valid) + return true; + else + return false; +} + +template +inline uint8_t GlobPoolVar::getValid() { + return valid; +} + +template +inline void GlobPoolVar::setValid(bool valid) { + this->valid = valid; +} + +#endif diff --git a/datapoolglob/GlobalPoolVector.h b/datapoolglob/GlobalPoolVector.h new file mode 100644 index 00000000..0f5daacd --- /dev/null +++ b/datapoolglob/GlobalPoolVector.h @@ -0,0 +1,185 @@ +#ifndef FSFW_DATAPOOLGLOB_GLOBALPOOLVECTOR_H_ +#define FSFW_DATAPOOLGLOB_GLOBALPOOLVECTOR_H_ + +#include "../datapool/DataSetIF.h" +#include "../datapool/PoolEntry.h" +#include "../datapool/PoolVariableIF.h" +#include "../serialize/SerializeAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" + +/** + * @brief This is the access class for array-type data pool entries. + * + * @details + * To ensure safe usage of the data pool, operation is not done directly on the + * data pool entries, but on local copies. This class provides simple type- + * and length-safe access to vector-style data pool entries (i.e. entries with + * length > 1). The class can be instantiated as read-write and read only. + * + * It provides a commit-and-roll-back semantic, which means that no array + * entry in the data pool is changed until the commit call is executed. + * There are two template parameters: + * @tparam T + * This template parameter specifies the data type of an array entry. Currently, + * all plain data types are supported, but in principle any type is possible. + * @tparam vector_size + * This template parameter specifies the vector size of this entry. Using a + * template parameter for this is not perfect, but avoids + * dynamic memory allocation. + * @ingroup data_pool + */ +template +class GlobPoolVector: public PoolVariableIF { +public: + /** + * @brief In the constructor, the variable can register itself in a + * DataSet (if no nullptr is passed). + * @details + * It DOES NOT fetch the current value from the data pool, but sets the + * value attribute to default (0). The value is fetched within the + * read() operation. + * @param set_id + * This is the id in the global data pool this instance of the access + * class corresponds to. + * @param dataSet + * The data set in which the variable shall register itself. If nullptr, + * the variable is not registered. + * @param setWritable + * If this flag is set to true, changes in the value attribute can be + * written back to the data pool, otherwise not. + */ + GlobPoolVector(uint32_t set_id, DataSetIF* set, + ReadWriteMode_t setReadWriteMode); + + /** + * @brief This is the local copy of the data pool entry. + * @details The user can work on this attribute + * just like he would on a local array of this type. + */ + T value[vectorSize]; + /** + * @brief The classes destructor is empty. + * @details If commit() was not called, the local value is + * discarded and not written back to the data pool. + */ + ~GlobPoolVector() {}; + /** + * @brief The operation returns the number of array entries + * in this variable. + */ + uint8_t getSize() { + return vectorSize; + } + /** + * @brief This operation returns the data pool id of the variable. + */ + uint32_t getDataPoolId() const { + return dataPoolId; + } + /** + * @brief This operation sets the data pool id of the variable. + * @details + * The method is necessary to set id's of data pool member variables + * with bad initialization. + */ + void setDataPoolId(uint32_t poolId) { + dataPoolId = poolId; + } + /** + * This method returns if the variable is write-only, read-write or read-only. + */ + ReadWriteMode_t getReadWriteMode() const { + return readWriteMode; + } + + + /** + * @brief With this call, the valid information of the variable is returned. + */ + bool isValid() const { + if (valid != INVALID) + return true; + else + return false; + } + void setValid(bool valid) {this->valid = valid;} + uint8_t getValid() {return valid;} + + T &operator [](int i) {return value[i];} + const T &operator [](int i) const {return value[i];} + + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t max_size, Endianness streamEndianness) const override; + virtual size_t getSerializedSize() const override; + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; + + /** + * @brief This is a call to read the array's values + * from the global data pool. + * @details + * When executed, this operation tries to fetch the pool entry with matching + * data pool id from the global data pool and copies all array values + * and the valid information to its local attributes. + * In case of a failure (wrong type, size or pool id not found), the + * variable is set to zero and invalid. + * The read call is protected by a lock of the global data pool. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. + */ + ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override; + /** + * @brief The commit call copies the array values back to the data pool. + * @details + * It checks type and size, as well as if the variable is writable. If so, + * the value is copied and the valid flag is automatically set to "valid". + * The commit call is protected by a lock of the global data pool. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. + */ + ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; + +protected: + /** + * @brief Like #read, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t readWithoutLock() override; + /** + * @brief Like #commit, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t commitWithoutLock() override; + +private: + /** + * @brief To access the correct data pool entry on read and commit calls, + * the data pool id is stored. + */ + uint32_t dataPoolId; + /** + * @brief The valid information as it was stored in the data pool + * is copied to this attribute. + */ + uint8_t valid; + /** + * @brief The information whether the class is read-write or + * read-only is stored here. + */ + ReadWriteMode_t readWriteMode; +}; + +#include "../datapoolglob/GlobalPoolVector.tpp" + +template +using gp_vec_t = GlobPoolVector; + +#endif /* FSFW_DATAPOOLGLOB_GLOBALPOOLVECTOR_H_ */ diff --git a/datapoolglob/GlobalPoolVector.tpp b/datapoolglob/GlobalPoolVector.tpp new file mode 100644 index 00000000..013a682a --- /dev/null +++ b/datapoolglob/GlobalPoolVector.tpp @@ -0,0 +1,117 @@ +#ifndef FSFW_DATAPOOLGLOB_GLOBALPOOLVECTOR_TPP_ +#define FSFW_DATAPOOLGLOB_GLOBALPOOLVECTOR_TPP_ + + +template +inline GlobPoolVector::GlobPoolVector(uint32_t set_id, + DataSetIF* set, ReadWriteMode_t setReadWriteMode) : + dataPoolId(set_id), valid(false), readWriteMode(setReadWriteMode) { + memset(this->value, 0, vectorSize * sizeof(T)); + if (set != nullptr) { + set->registerVariable(this); + } +} + + +template +inline ReturnValue_t GlobPoolVector::read(uint32_t lockTimeout) { + ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = readWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "GlobPoolVar::read: Could not unlock global data pool" + << std::endl; + } + return result; +} + +template +inline ReturnValue_t GlobPoolVector::commit( + uint32_t lockTimeout) { + ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = commitWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "GlobPoolVar::read: Could not unlock global data pool" + << std::endl; + } + return result; +} + +template +inline ReturnValue_t GlobPoolVector::readWithoutLock() { + PoolEntry* read_out = glob::dataPool.getData(this->dataPoolId, + vectorSize); + if (read_out != nullptr) { + this->valid = read_out->valid; + memcpy(this->value, read_out->address, read_out->getByteSize()); + + return HasReturnvaluesIF::RETURN_OK; + + } else { + memset(this->value, 0, vectorSize * sizeof(T)); + sif::error << "PoolVector: Read of DP Variable 0x" << std::hex + << std::setw(8) << std::setfill('0') << dataPoolId << + std::dec << " failed." << std::endl; + this->valid = INVALID; + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +template +inline ReturnValue_t GlobPoolVector::commitWithoutLock() { + PoolEntry* writeBack = glob::dataPool.getData(this->dataPoolId, + vectorSize); + if ((writeBack != nullptr) && (this->readWriteMode != VAR_READ)) { + writeBack->valid = valid; + memcpy(writeBack->address, this->value, writeBack->getByteSize()); + return HasReturnvaluesIF::RETURN_OK; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +template +inline ReturnValue_t GlobPoolVector::serialize(uint8_t** buffer, + size_t* size, size_t max_size, + SerializeIF::Endianness streamEndianness) const { + uint16_t i; + ReturnValue_t result; + for (i = 0; i < vectorSize; i++) { + result = SerializeAdapter::serialize(&(value[i]), buffer, size, + max_size, streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + return result; +} + +template +inline size_t GlobPoolVector::getSerializedSize() const { + return vectorSize * SerializeAdapter::getSerializedSize(value); +} + +template +inline ReturnValue_t GlobPoolVector::deSerialize( + const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) { + uint16_t i; + ReturnValue_t result; + for (i = 0; i < vectorSize; i++) { + result = SerializeAdapter::deSerialize(&(value[i]), buffer, size, + streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + return result; +} + +#endif diff --git a/datapool/PIDReader.h b/datapoolglob/PIDReader.h similarity index 77% rename from datapool/PIDReader.h rename to datapoolglob/PIDReader.h index 3b38b51d..9431e1d4 100644 --- a/datapool/PIDReader.h +++ b/datapoolglob/PIDReader.h @@ -1,9 +1,9 @@ #ifndef PIDREADER_H_ #define PIDREADER_H_ -#include "DataPool.h" -#include "DataSetIF.h" -#include "PoolEntry.h" -#include "PoolVariableIF.h" +#include "../datapool/DataSetIF.h" +#include "../datapoolglob/GlobalDataPool.h" +#include "../datapool/PoolEntry.h" +#include "../datapool/PoolVariableIF.h" #include "../serialize/SerializeAdapter.h" #include "../serviceinterface/ServiceInterfaceStream.h" @@ -15,10 +15,10 @@ class PIDReader: public PoolVariableIF { protected: uint32_t parameterId; uint8_t valid; - ReturnValue_t read() { - uint8_t arrayIndex = DataPool::PIDToArrayIndex(parameterId); - PoolEntry *read_out = ::dataPool.getData( - DataPool::PIDToDataPoolId(parameterId), arrayIndex); + ReturnValue_t readWithoutLock() { + uint8_t arrayIndex = GlobalDataPool::PIDToArrayIndex(parameterId); + PoolEntry *read_out = glob::dataPool.getData( + GlobalDataPool::PIDToDataPoolId(parameterId), arrayIndex); if (read_out != NULL) { valid = read_out->valid; value = read_out->address[arrayIndex]; @@ -36,9 +36,13 @@ protected: * Reason is the possibility to access a single DP vector element, but if we commit, * we set validity of the whole vector. */ - ReturnValue_t commit() { + ReturnValue_t commit(uint32_t lockTimeout) override { return HasReturnvaluesIF::RETURN_FAILED; } + ReturnValue_t commitWithoutLock() override { + return HasReturnvaluesIF::RETURN_FAILED; + } + /** * Empty ctor for List initialization */ @@ -72,6 +76,19 @@ public: } } + ReturnValue_t read(uint32_t lockTimeout) override { + ReturnValue_t result = glob::dataPool.lockDataPool(); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = readWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "PIDReader::read: Could not unlock data pool!" + << std::endl; + } + return result; + } /** * Copy ctor to copy classes containing Pool Variables. */ @@ -89,7 +106,7 @@ public: * \brief This operation returns the data pool id of the variable. */ uint32_t getDataPoolId() const { - return DataPool::PIDToDataPoolId(parameterId); + return GlobalDataPool::PIDToDataPoolId(parameterId); } uint32_t getParameterId() const { return parameterId; @@ -114,7 +131,7 @@ public: return valid; } - void setValid(uint8_t valid) { + void setValid(bool valid) { this->valid = valid; } diff --git a/datapool/PIDReaderList.h b/datapoolglob/PIDReaderList.h similarity index 68% rename from datapool/PIDReaderList.h rename to datapoolglob/PIDReaderList.h index 1f6aa99c..ae99f3aa 100644 --- a/datapool/PIDReaderList.h +++ b/datapoolglob/PIDReaderList.h @@ -1,8 +1,8 @@ -#ifndef FRAMEWORK_DATAPOOL_PIDREADERLIST_H_ -#define FRAMEWORK_DATAPOOL_PIDREADERLIST_H_ +#ifndef FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_ +#define FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_ -#include "PIDReader.h" -#include "PoolVariableIF.h" +#include "../datapool/PoolVariableIF.h" +#include "../datapoolglob/PIDReader.h" template class PIDReaderList { private: @@ -24,4 +24,4 @@ public: -#endif /* FRAMEWORK_DATAPOOL_PIDREADERLIST_H_ */ +#endif /* FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_ */ diff --git a/datapoolglob/PoolRawAccess.cpp b/datapoolglob/PoolRawAccess.cpp new file mode 100644 index 00000000..53706c6d --- /dev/null +++ b/datapoolglob/PoolRawAccess.cpp @@ -0,0 +1,239 @@ +#include "../datapoolglob/GlobalDataPool.h" +#include "../datapoolglob/PoolRawAccess.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../serialize/EndianConverter.h" + +#include + +PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry, + DataSetIF* dataSet, ReadWriteMode_t 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 (dataSet != nullptr) { + dataSet->registerVariable(this); + } +} + +PoolRawAccess::~PoolRawAccess() {} + +ReturnValue_t PoolRawAccess::read(uint32_t lockTimeout) { + ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = readWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "GlobPoolVar::read: Could not unlock global data pool" + << std::endl; + } + return result; +} + +ReturnValue_t PoolRawAccess::readWithoutLock() { + ReturnValue_t result = RETURN_FAILED; + PoolEntryIF* readOut = glob::dataPool.getRawData(dataPoolId); + if (readOut != nullptr) { + result = handleReadOut(readOut); + if(result == RETURN_OK) { + return result; + } + } else { + result = READ_ENTRY_NON_EXISTENT; + } + handleReadError(result); + return result; +} + +ReturnValue_t PoolRawAccess::handleReadOut(PoolEntryIF* readOut) { + ReturnValue_t result = RETURN_FAILED; + valid = readOut->getValid(); + if (readOut->getSize() > arrayEntry) { + arraySize = readOut->getSize(); + typeSize = readOut->getByteSize() / readOut->getSize(); + type = readOut->getType(); + if (typeSize <= sizeof(value)) { + uint16_t arrayPosition = arrayEntry * typeSize; + sizeTillEnd = readOut->getByteSize() - arrayPosition; + uint8_t* ptr = &((uint8_t*) readOut->getRawData())[arrayPosition]; + memcpy(value, ptr, typeSize); + return RETURN_OK; + } else { + result = READ_TYPE_TOO_LARGE; + } + } else { + //debug << "PoolRawAccess: Size: " << (int)read_out->getSize() << std::endl; + result = READ_INDEX_TOO_LARGE; + } + return result; +} + +void PoolRawAccess::handleReadError(ReturnValue_t result) { + sif::error << "PoolRawAccess: read of DP Variable 0x" << std::hex << dataPoolId + << std::dec << " failed, "; + if(result == READ_TYPE_TOO_LARGE) { + sif::error << "type too large." << std::endl; + } + else if(result == READ_INDEX_TOO_LARGE) { + sif::error << "index too large." << std::endl; + } + else if(result == READ_ENTRY_NON_EXISTENT) { + sif::error << "entry does not exist." << std::endl; + } + + valid = INVALID; + typeSize = 0; + sizeTillEnd = 0; + memset(value, 0, sizeof(value)); +} + +ReturnValue_t PoolRawAccess::commit(uint32_t lockTimeout) { + ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = commitWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "GlobPoolVar::read: Could not unlock global data pool" + << std::endl; + } + return result; +} + +ReturnValue_t PoolRawAccess::commitWithoutLock() { + PoolEntryIF* write_back = glob::dataPool.getRawData(dataPoolId); + if ((write_back != NULL) && (readWriteMode != VAR_READ)) { + write_back->setValid(valid); + uint8_t array_position = arrayEntry * typeSize; + uint8_t* ptr = &((uint8_t*) write_back->getRawData())[array_position]; + memcpy(ptr, value, typeSize); + return HasReturnvaluesIF::RETURN_OK; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +uint8_t* PoolRawAccess::getEntry() { + return value; +} + +ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer, + size_t* writtenBytes, size_t max_size) { + uint8_t* data_ptr = getEntry(); + // debug << "PoolRawAccess::getEntry: Array position: " << + // index * size_of_type << " Size of T: " << (int)size_of_type << + // " ByteSize: " << byte_size << " Position: " << *size << std::endl; + if (typeSize == 0) + return DATA_POOL_ACCESS_FAILED; + if (typeSize > max_size) + return INCORRECT_SIZE; + EndianConverter::convertBigEndian(buffer, data_ptr, typeSize); + *writtenBytes = typeSize; + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { + if (typeSize + *size <= maxSize) { + switch(streamEndianness) { + case(Endianness::BIG): + EndianConverter::convertBigEndian(*buffer, value, typeSize); + break; + case(Endianness::LITTLE): + EndianConverter::convertLittleEndian(*buffer, value, typeSize); + break; + case(Endianness::MACHINE): + default: + memcpy(*buffer, value, typeSize); + break; + } + *size += typeSize; + (*buffer) += typeSize; + return HasReturnvaluesIF::RETURN_OK; + } else { + return SerializeIF::BUFFER_TOO_SHORT; + } +} + + +Type PoolRawAccess::getType() { + return type; +} + +size_t PoolRawAccess::getSizeOfType() { + return typeSize; +} + +size_t PoolRawAccess::getArraySize(){ + return arraySize; +} + +uint32_t PoolRawAccess::getDataPoolId() const { + return dataPoolId; +} + +PoolVariableIF::ReadWriteMode_t PoolRawAccess::getReadWriteMode() const { + return readWriteMode; +} + +ReturnValue_t PoolRawAccess::setEntryFromBigEndian(const uint8_t *buffer, + size_t setSize) { + if (typeSize == setSize) { + EndianConverter::convertBigEndian(value, buffer, typeSize); + return HasReturnvaluesIF::RETURN_OK; + } else { + sif::error << "PoolRawAccess::setEntryFromBigEndian: Illegal sizes: " + "Internal" << (uint32_t) typeSize << ", Requested: " << setSize + << std::endl; + return INCORRECT_SIZE; + } +} + +bool PoolRawAccess::isValid() const { + if (valid != INVALID) + return true; + else + return false; +} + +void PoolRawAccess::setValid(bool valid) { + this->valid = valid; +} + +size_t PoolRawAccess::getSizeTillEnd() const { + return sizeTillEnd; +} + + +size_t PoolRawAccess::getSerializedSize() const { + return typeSize; +} + +ReturnValue_t PoolRawAccess::deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) { + + if (*size >= typeSize) { + switch(streamEndianness) { + case(Endianness::BIG): + EndianConverter::convertBigEndian(value, *buffer, typeSize); + break; + case(Endianness::LITTLE): + EndianConverter::convertLittleEndian(value, *buffer, typeSize); + break; + case(Endianness::MACHINE): + default: + memcpy(value, *buffer, typeSize); + break; + } + *size -= typeSize; + *buffer += typeSize; + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SerializeIF::STREAM_TOO_SHORT; + } +} diff --git a/datapoolglob/PoolRawAccess.h b/datapoolglob/PoolRawAccess.h new file mode 100644 index 00000000..15643a41 --- /dev/null +++ b/datapoolglob/PoolRawAccess.h @@ -0,0 +1,220 @@ +#ifndef POOLRAWACCESS_H_ +#define POOLRAWACCESS_H_ + +#include "../datapool/DataSetIF.h" +#include "../datapool/PoolEntryIF.h" +#include "../datapool/PoolVariableIF.h" +#include "../globalfunctions/Type.h" + +/** + * @brief This class allows accessing Data Pool variables as raw bytes. + * @details + * This is necessary to have an access method for HK data, as the PID's alone + * do not provide type information. Please note that the the raw pool access + * read() and commit() calls are not thread-safe. + * + * Please supply a data set and use the data set read(), commit() calls for + * thread-safe data pool access. + * @ingroup data_pool + */ +class PoolRawAccess: public PoolVariableIF, HasReturnvaluesIF { +public: + /** + * This constructor is used to access a data pool entry with a + * given ID if the target type is not known. A DataSet object is supplied + * and the data pool entry with the given ID is registered to that data set. + * Please note that a pool raw access buffer only has a buffer + * with a size of double. As such, for vector entries which have + * @param data_pool_id Target data pool entry ID + * @param arrayEntry + * @param data_set Dataset to register data pool entry to + * @param setReadWriteMode + * @param registerVectors If set to true, the constructor checks if + * there are multiple vector entries to registers + * and registers all of them recursively into the data_set + * + */ + PoolRawAccess(uint32_t data_pool_id, uint8_t arrayEntry, + DataSetIF* data_set, ReadWriteMode_t setReadWriteMode = + PoolVariableIF::VAR_READ); + + /** + * @brief This operation returns a pointer to the entry fetched. + * @details Return pointer to the buffer containing the raw data + * Size and number of data can be retrieved by other means. + */ + uint8_t* getEntry(); + /** + * @brief This operation returns the fetched entry from the data pool and + * flips the bytes, if necessary. + * @details It makes use of the getEntry call of this function, but additionally flips the + * bytes to big endian, which is the default for external communication (as House- + * keeping telemetry). To achieve this, the data is copied directly to the passed + * buffer, if it fits in the given max_size. + * @param buffer A pointer to a buffer to write to + * @param writtenBytes The number of bytes written is returned with this value. + * @param max_size The maximum size that the function may write to buffer. + * @return - @c RETURN_OK if entry could be acquired + * - @c RETURN_FAILED else. + */ + ReturnValue_t getEntryEndianSafe(uint8_t *buffer, size_t *size, + size_t maxSize); + + /** + * @brief Serialize raw pool entry into provided buffer directly + * @param buffer Provided buffer. Raw pool data will be copied here + * @param size [out] Increment provided size value by serialized size + * @param max_size Maximum allowed serialization size + * @param bigEndian Specify endianess + * @return - @c RETURN_OK if serialization was successfull + * - @c SerializeIF::BUFFER_TOO_SHORT if range check failed + */ + ReturnValue_t serialize(uint8_t **buffer, size_t *size, + size_t maxSize, Endianness streamEndianness) const override; + + size_t getSerializedSize() const override; + + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override; + + /** + * With this method, the content can be set from a big endian buffer safely. + * @param buffer Pointer to the data to set + * @param size Size of the data to write. Must fit this->size. + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + ReturnValue_t setEntryFromBigEndian(const uint8_t* buffer, + size_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. + */ + size_t getSizeOfType(); + /** + * + * @return the size of the datapool array + */ + size_t getArraySize(); + /** + * @brief This operation returns the data pool id of the variable. + */ + uint32_t getDataPoolId() const; + + 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); + static const ReturnValue_t READ_TYPE_TOO_LARGE = MAKE_RETURN_CODE(0x03); + static const ReturnValue_t READ_INDEX_TOO_LARGE = MAKE_RETURN_CODE(0x04); + static const ReturnValue_t READ_ENTRY_NON_EXISTENT = MAKE_RETURN_CODE(0x05); + static const uint8_t RAW_MAX_SIZE = sizeof(double); + uint8_t value[RAW_MAX_SIZE]; + + + /** + * @brief The classes destructor is empty. If commit() was not called, the local value is + * discarded and not written back to the data pool. + */ + ~PoolRawAccess(); + + /** + * This method returns if the variable is read-write or read-only. + */ + ReadWriteMode_t getReadWriteMode() const; + /** + * @brief With this call, the valid information of the variable is returned. + */ + bool isValid() const; + + void setValid(bool valid); + /** + * Getter for the remaining size. + */ + size_t getSizeTillEnd() const; + + /** + * @brief This is a call to read the value from the global data pool. + * @details + * When executed, this operation tries to fetch the pool entry with matching + * data pool id from the global data pool and copies the value and the valid + * information to its local attributes. In case of a failure (wrong type or + * pool id not found), the variable is set to zero and invalid. + * The call is protected by a lock of the global data pool. + * @return -@c RETURN_OK Read successfull + * -@c READ_TYPE_TOO_LARGE + * -@c READ_INDEX_TOO_LARGE + * -@c READ_ENTRY_NON_EXISTENT + */ + ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override; + /** + * @brief The commit call writes back the variable's value to the data pool. + * @details + * It checks type and size, as well as if the variable is writable. If so, + * the value is copied and the valid flag is automatically set to "valid". + * The call is protected by a lock of the global data pool. + * + */ + ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; + +protected: + /** + * @brief Like #read, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t readWithoutLock() override; + /** + * @brief Like #commit, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t commitWithoutLock() override; + + ReturnValue_t handleReadOut(PoolEntryIF* read_out); + void handleReadError(ReturnValue_t result); +private: + /** + * @brief To access the correct data pool entry on read and commit calls, the data pool id + * is stored. + */ + uint32_t dataPoolId; + /** + * @brief The array entry that is fetched from the data pool. + */ + uint8_t arrayEntry; + /** + * @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 type in bytes. + */ + size_t typeSize; + /** + * The size of the DP array (single values return 1) + */ + size_t arraySize; + /** + * The size (in bytes) from the selected entry till the end of this DataPool variable. + */ + size_t sizeTillEnd; + /** + * @brief The information whether the class is read-write or read-only is stored here. + */ + ReadWriteMode_t readWriteMode; +}; + +#endif /* POOLRAWACCESS_H_ */ From 790d3f14654cf1b7f937c36f9b1d02289dc596ce Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 6 Sep 2020 15:25:56 +0200 Subject: [PATCH 317/653] taken over all changes --- fsfw.mk | 16 ++++++++++++++ internalError/InternalErrorReporter.cpp | 19 ++++++++--------- monitoring/MonitorBase.h | 14 ++++++------- power/Fuse.cpp | 6 +++--- power/Fuse.h | 15 ++++++------- power/PowerSensor.h | 10 ++++----- thermal/CoreComponent.cpp | 12 +++++------ thermal/CoreComponent.h | 23 ++++++++++---------- thermal/ThermalComponent.cpp | 18 +++++++--------- thermal/ThermalComponent.h | 28 +++++++++++++++++++++++-- thermal/ThermalModule.cpp | 8 +++---- thermal/ThermalModule.h | 17 ++++++++------- 12 files changed, 114 insertions(+), 72 deletions(-) diff --git a/fsfw.mk b/fsfw.mk index c2c6e747..c5847554 100644 --- a/fsfw.mk +++ b/fsfw.mk @@ -9,6 +9,9 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/controller/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/coordinates/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datalinklayer/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapool/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoolglob/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoollocal/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/housekeeping/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/devicehandlers/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/eventmatching/*.cpp) @@ -28,12 +31,25 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/*.cpp) # select the OS ifeq ($(OS_FSFW),rtems) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/rtems/*.cpp) + else ifeq ($(OS_FSFW),linux) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/linux/*.cpp) + else ifeq ($(OS_FSFW),freeRTOS) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/FreeRTOS/*.cpp) + else ifeq ($(OS_FSFW),host) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/host/*.cpp) +ifeq ($(OS),Windows_NT) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/windows/*.cpp) +else +# For now, the linux UDP bridge sources needs to be included manually by upper makefile +# for host OS because we can't be sure the OS is linux. +# Following lines can be used to do this: +# CXXSRC += $(FRAMEWORK_PATH)/osal/linux/TcUnixUdpPollingTask.cpp +# CXXSRC += $(FRAMEWORK_PATH)/osal/linux/TmTcUnixUdpBridge.cpp +endif + else $(error invalid OS_FSFW specified, valid OS_FSFW are rtems, linux, freeRTOS, host) endif diff --git a/internalError/InternalErrorReporter.cpp b/internalError/InternalErrorReporter.cpp index 861e1595..3424266b 100644 --- a/internalError/InternalErrorReporter.cpp +++ b/internalError/InternalErrorReporter.cpp @@ -1,17 +1,16 @@ +#include "../datapoolglob/GlobalDataSet.h" #include "InternalErrorReporter.h" -#include "../datapool/DataSet.h" -#include "../datapool/PoolVariable.h" +#include "../datapoolglob/GlobalPoolVariable.h" #include "../ipc/MutexFactory.h" #include "../serviceinterface/ServiceInterfaceStream.h" InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t queuePoolId, uint32_t tmPoolId, uint32_t storePoolId) : - SystemObject(setObjectId), mutex(NULL), queuePoolId(queuePoolId), tmPoolId( - tmPoolId), storePoolId( - storePoolId), queueHits(0), tmHits(0), storeHits( - 0) { + SystemObject(setObjectId), mutex(NULL), queuePoolId(queuePoolId), + tmPoolId(tmPoolId),storePoolId(storePoolId), queueHits(0), tmHits(0), + storeHits(0) { mutex = MutexFactory::instance()->createMutex(); } @@ -21,13 +20,13 @@ InternalErrorReporter::~InternalErrorReporter() { ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) { - DataSet mySet; - PoolVariable queueHitsInPool(queuePoolId, &mySet, + GlobDataSet mySet; + gp_uint32_t queueHitsInPool(queuePoolId, &mySet, PoolVariableIF::VAR_READ_WRITE); - PoolVariable tmHitsInPool(tmPoolId, &mySet, + gp_uint32_t tmHitsInPool(tmPoolId, &mySet, PoolVariableIF::VAR_READ_WRITE); - PoolVariable storeHitsInPool(storePoolId, &mySet, + gp_uint32_t storeHitsInPool(storePoolId, &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); diff --git a/monitoring/MonitorBase.h b/monitoring/MonitorBase.h index b2d0e6cb..5173c479 100644 --- a/monitoring/MonitorBase.h +++ b/monitoring/MonitorBase.h @@ -1,12 +1,12 @@ #ifndef MONITORBASE_H_ #define MONITORBASE_H_ -#include "../datapool/DataSet.h" -#include "../datapool/PIDReader.h" -#include "LimitViolationReporter.h" -#include "MonitoringIF.h" -#include "MonitoringMessageContent.h" -#include "MonitorReporter.h" +#include "../datapoolglob/GlobalDataSet.h" +#include "../datapoolglob/PIDReader.h" +#include "../monitoring/LimitViolationReporter.h" +#include "../monitoring/MonitoringIF.h" +#include "../monitoring/MonitoringMessageContent.h" +#include "../monitoring/MonitorReporter.h" /** * Base class for monitoring of parameters. @@ -48,7 +48,7 @@ public: protected: virtual ReturnValue_t fetchSample(T* sample) { - DataSet mySet; + GlobDataSet mySet; PIDReader parameter(this->parameterId, &mySet); mySet.read(); if (!parameter.isValid()) { diff --git a/power/Fuse.cpp b/power/Fuse.cpp index 9986ab6b..3ea0b18c 100644 --- a/power/Fuse.cpp +++ b/power/Fuse.cpp @@ -1,7 +1,7 @@ #include "../monitoring/LimitViolationReporter.h" #include "../monitoring/MonitoringMessageContent.h" #include "../objectmanager/ObjectManagerIF.h" -#include "Fuse.h" +#include "../power/Fuse.h" #include "../serialize/SerialFixedArrayListAdapter.h" #include "../ipc/QueueFactory.h" @@ -12,7 +12,7 @@ Fuse::Fuse(object_id_t fuseObjectId, uint8_t fuseId, VariableIds ids, SystemObject(fuseObjectId), oldFuseState(0), fuseId(fuseId), powerIF( NULL), currentLimit(fuseObjectId, 1, ids.pidCurrent, confirmationCount, maxCurrent, FUSE_CURRENT_HIGH), powerMonitor(fuseObjectId, 2, - DataPool::poolIdAndPositionToPid(ids.poolIdPower, 0), + GlobalDataPool::poolIdAndPositionToPid(ids.poolIdPower, 0), confirmationCount), set(), voltage(ids.pidVoltage, &set), current( ids.pidCurrent, &set), state(ids.pidState, &set), power( ids.poolIdPower, &set, PoolVariableIF::VAR_READ_WRITE), commandQueue( @@ -109,7 +109,7 @@ size_t Fuse::getSerializedSize() const { } ReturnValue_t Fuse::deSerialize(const uint8_t** buffer, size_t* size, -Endianness streamEndianness) { + Endianness streamEndianness) { ReturnValue_t result = RETURN_FAILED; for (DeviceList::iterator iter = devices.begin(); iter != devices.end(); iter++) { diff --git a/power/Fuse.h b/power/Fuse.h index 279642be..dd8759f4 100644 --- a/power/Fuse.h +++ b/power/Fuse.h @@ -1,12 +1,13 @@ #ifndef FUSE_H_ #define FUSE_H_ -#include "../datapool/DataSet.h" -#include "../datapool/PIDReader.h" +#include "../datapoolglob/GlobalDataSet.h" +#include "../datapoolglob/GlobalPoolVariable.h" +#include "../datapoolglob/PIDReader.h" #include "../devicehandlers/HealthDevice.h" #include "../monitoring/AbsLimitMonitor.h" -#include "PowerComponentIF.h" -#include "PowerSwitchIF.h" +#include "../power/PowerComponentIF.h" +#include "../power/PowerSwitchIF.h" #include "../returnvalues/HasReturnvaluesIF.h" #include "../parameters/ParameterHelper.h" #include @@ -84,12 +85,12 @@ private: }; PowerMonitor powerMonitor; - DataSet set; + GlobDataSet set; PIDReader voltage; PIDReader current; PIDReader state; - db_float_t power; - MessageQueueIF *commandQueue; + gp_float_t power; + MessageQueueIF* commandQueue; ParameterHelper parameterHelper; HealthHelper healthHelper; static object_id_t powerSwitchId; diff --git a/power/PowerSensor.h b/power/PowerSensor.h index 0f973e45..da0bd8c7 100644 --- a/power/PowerSensor.h +++ b/power/PowerSensor.h @@ -1,9 +1,9 @@ #ifndef POWERSENSOR_H_ #define POWERSENSOR_H_ -#include "../datapool/DataSet.h" -#include "../datapool/PIDReader.h" -#include "../datapool/PoolVariable.h" +#include "../datapoolglob/GlobalDataSet.h" +#include "../datapoolglob/GlobalPoolVariable.h" +#include "../datapoolglob/PIDReader.h" #include "../devicehandlers/HealthDevice.h" #include "../monitoring/LimitMonitor.h" #include "../parameters/ParameterHelper.h" @@ -53,12 +53,12 @@ private: MessageQueueIF* commandQueue; ParameterHelper parameterHelper; HealthHelper healthHelper; - DataSet set; + GlobDataSet set; //Variables in PIDReader current; PIDReader voltage; //Variables out - db_float_t power; + gp_float_t power; static const uint8_t MODULE_ID_CURRENT = 1; static const uint8_t MODULE_ID_VOLTAGE = 2; diff --git a/thermal/CoreComponent.cpp b/thermal/CoreComponent.cpp index 304712ef..657e79cb 100644 --- a/thermal/CoreComponent.cpp +++ b/thermal/CoreComponent.cpp @@ -2,7 +2,7 @@ CoreComponent::CoreComponent(object_id_t reportingObjectId, uint8_t domainId, uint32_t temperaturePoolId, uint32_t targetStatePoolId, - uint32_t currentStatePoolId, uint32_t requestPoolId, DataSet* dataSet, + uint32_t currentStatePoolId, uint32_t requestPoolId, GlobDataSet* dataSet, AbstractTemperatureSensor* sensor, AbstractTemperatureSensor* firstRedundantSensor, AbstractTemperatureSensor* secondRedundantSensor, @@ -18,14 +18,14 @@ CoreComponent::CoreComponent(object_id_t reportingObjectId, uint8_t domainId, AbstractTemperatureSensor::ZERO_KELVIN_C), parameters( parameters), temperatureMonitor(reportingObjectId, domainId + 1, - DataPool::poolIdAndPositionToPid(temperaturePoolId, 0), + GlobalDataPool::poolIdAndPositionToPid(temperaturePoolId, 0), COMPONENT_TEMP_CONFIRMATION), domainId(domainId) { if (thermalModule != NULL) { thermalModule->registerComponent(this, priority); } //Set thermal state once, then leave to operator. - DataSet mySet; - PoolVariable writableTargetState(targetStatePoolId, &mySet, + GlobDataSet mySet; + gp_uint8_t writableTargetState(targetStatePoolId, &mySet, PoolVariableIF::VAR_WRITE); writableTargetState = initialTargetState; mySet.commit(PoolVariableIF::VALID); @@ -70,8 +70,8 @@ float CoreComponent::getLowerOpLimit() { } ReturnValue_t CoreComponent::setTargetState(int8_t newState) { - DataSet mySet; - PoolVariable writableTargetState(targetState.getDataPoolId(), + GlobDataSet mySet; + gp_uint8_t writableTargetState(targetState.getDataPoolId(), &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); if ((writableTargetState == STATE_REQUEST_OPERATIONAL) diff --git a/thermal/CoreComponent.h b/thermal/CoreComponent.h index 48a49f7d..8093711d 100644 --- a/thermal/CoreComponent.h +++ b/thermal/CoreComponent.h @@ -1,13 +1,14 @@ #ifndef MISSION_CONTROLLERS_TCS_CORECOMPONENT_H_ #define MISSION_CONTROLLERS_TCS_CORECOMPONENT_H_ -#include "../datapool/DataSet.h" -#include "../datapool/PoolVariable.h" -#include "ThermalComponentIF.h" -#include "AbstractTemperatureSensor.h" -#include "ThermalModule.h" -#include "ThermalMonitor.h" +#include "../datapoolglob/GlobalDataSet.h" +#include "../datapoolglob/GlobalPoolVariable.h" +#include "../thermal/ThermalComponentIF.h" +#include "../thermal/AbstractTemperatureSensor.h" +#include "../thermal/ThermalModule.h" +#include "../thermal/ThermalMonitor.h" +// TODO: Documentaiton, how to use this? only use Thermal Component, which inherits core component? class CoreComponent: public ThermalComponentIF { public: struct Parameters { @@ -22,7 +23,7 @@ public: CoreComponent(object_id_t reportingObjectId, uint8_t domainId, uint32_t temperaturePoolId, uint32_t targetStatePoolId, uint32_t currentStatePoolId, - uint32_t requestPoolId, DataSet *dataSet, + uint32_t requestPoolId, GlobDataSet *dataSet, AbstractTemperatureSensor *sensor, AbstractTemperatureSensor *firstRedundantSensor, AbstractTemperatureSensor *secondRedundantSensor, @@ -57,10 +58,10 @@ protected: AbstractTemperatureSensor *secondRedundantSensor; ThermalModuleIF *thermalModule; - db_float_t temperature; - db_int8_t targetState; - db_int8_t currentState; - db_uint8_t heaterRequest; + gp_float_t temperature; + gp_int8_t targetState; + gp_int8_t currentState; + gp_uint8_t heaterRequest; bool isHeating; diff --git a/thermal/ThermalComponent.cpp b/thermal/ThermalComponent.cpp index 5dcd0bc6..50786654 100644 --- a/thermal/ThermalComponent.cpp +++ b/thermal/ThermalComponent.cpp @@ -3,7 +3,7 @@ ThermalComponent::ThermalComponent(object_id_t reportingObjectId, uint8_t domainId, uint32_t temperaturePoolId, uint32_t targetStatePoolId, uint32_t currentStatePoolId, - uint32_t requestPoolId, DataSet* dataSet, + uint32_t requestPoolId, GlobDataSet* dataSet, AbstractTemperatureSensor* sensor, AbstractTemperatureSensor* firstRedundantSensor, AbstractTemperatureSensor* secondRedundantSensor, @@ -12,20 +12,18 @@ ThermalComponent::ThermalComponent(object_id_t reportingObjectId, CoreComponent(reportingObjectId, domainId, temperaturePoolId, targetStatePoolId, currentStatePoolId, requestPoolId, dataSet, sensor, firstRedundantSensor, secondRedundantSensor, - thermalModule, - { parameters.lowerOpLimit, parameters.upperOpLimit, - parameters.heaterOn, parameters.hysteresis, - parameters.heaterSwitchoff }, priority, - ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL), nopParameters( - { parameters.lowerNopLimit, parameters.upperNopLimit }) { + thermalModule,{ parameters.lowerOpLimit, parameters.upperOpLimit, + parameters.heaterOn, parameters.hysteresis, parameters.heaterSwitchoff }, + priority, ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL), + nopParameters({ parameters.lowerNopLimit, parameters.upperNopLimit }) { } ThermalComponent::~ThermalComponent() { } ReturnValue_t ThermalComponent::setTargetState(int8_t newState) { - DataSet mySet; - PoolVariable writableTargetState(targetState.getDataPoolId(), + GlobDataSet mySet; + gp_int8_t writableTargetState(targetState.getDataPoolId(), &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); if ((writableTargetState == STATE_REQUEST_OPERATIONAL) @@ -42,7 +40,7 @@ ReturnValue_t ThermalComponent::setTargetState(int8_t newState) { } } -ReturnValue_t ThermalComponent::setLimits(const uint8_t* data, uint32_t size) { +ReturnValue_t ThermalComponent::setLimits(const uint8_t* data, size_t size) { if (size != 4 * sizeof(parameters.lowerOpLimit)) { return MonitoringIF::INVALID_SIZE; } diff --git a/thermal/ThermalComponent.h b/thermal/ThermalComponent.h index 93243868..195f03b1 100644 --- a/thermal/ThermalComponent.h +++ b/thermal/ThermalComponent.h @@ -3,6 +3,9 @@ #include "CoreComponent.h" +/** + * What is it. How to use + */ class ThermalComponent: public CoreComponent { public: struct Parameters { @@ -14,13 +17,34 @@ public: float hysteresis; float heaterSwitchoff; }; + + /** + * Non-Operational Temperatures + */ struct NopParameters { float lowerNopLimit; float upperNopLimit; }; + + /** + * How to use. + * @param reportingObjectId + * @param domainId + * @param temperaturePoolId + * @param targetStatePoolId + * @param currentStatePoolId + * @param requestPoolId + * @param dataSet + * @param sensor + * @param firstRedundantSensor + * @param secondRedundantSensor + * @param thermalModule + * @param parameters + * @param priority + */ ThermalComponent(object_id_t reportingObjectId, uint8_t domainId, uint32_t temperaturePoolId, uint32_t targetStatePoolId, uint32_t currentStatePoolId, uint32_t requestPoolId, - DataSet *dataSet, AbstractTemperatureSensor *sensor, + GlobDataSet *dataSet, AbstractTemperatureSensor *sensor, AbstractTemperatureSensor *firstRedundantSensor, AbstractTemperatureSensor *secondRedundantSensor, ThermalModuleIF *thermalModule, Parameters parameters, @@ -29,7 +53,7 @@ public: ReturnValue_t setTargetState(int8_t newState); - virtual ReturnValue_t setLimits( const uint8_t* data, uint32_t size); + virtual ReturnValue_t setLimits( const uint8_t* data, size_t size); virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, ParameterWrapper *parameterWrapper, diff --git a/thermal/ThermalModule.cpp b/thermal/ThermalModule.cpp index c573008e..fbd6939e 100644 --- a/thermal/ThermalModule.cpp +++ b/thermal/ThermalModule.cpp @@ -6,7 +6,7 @@ ThermalModule::ThermalModule(uint32_t moduleTemperaturePoolId, uint32_t currentStatePoolId, uint32_t targetStatePoolId, - DataSet *dataSet, Parameters parameters, + GlobDataSet *dataSet, Parameters parameters, RedundantHeater::Parameters heaterParameters) : oldStrategy(ACTIVE_SINGLE), survivalTargetTemp(0), targetTemp(0), heating( false), parameters(parameters), moduleTemperature( @@ -16,7 +16,7 @@ ThermalModule::ThermalModule(uint32_t moduleTemperaturePoolId, heater = new RedundantHeater(heaterParameters); } -ThermalModule::ThermalModule(uint32_t moduleTemperaturePoolId, DataSet* dataSet) : +ThermalModule::ThermalModule(uint32_t moduleTemperaturePoolId, GlobDataSet* dataSet) : oldStrategy(ACTIVE_SINGLE), survivalTargetTemp(0), targetTemp(0), heating( false), parameters( { 0, 0 }), moduleTemperature( moduleTemperaturePoolId, dataSet, PoolVariableIF::VAR_WRITE), heater( @@ -250,8 +250,8 @@ bool ThermalModule::calculateModuleHeaterRequestAndSetModuleStatus( } void ThermalModule::setHeating(bool on) { - DataSet mySet; - PoolVariable writableTargetState(targetState.getDataPoolId(), + GlobDataSet mySet; + gp_int8_t writableTargetState(targetState.getDataPoolId(), &mySet, PoolVariableIF::VAR_WRITE); if (on) { writableTargetState = STATE_REQUEST_HEATING; diff --git a/thermal/ThermalModule.h b/thermal/ThermalModule.h index 19ab9a54..41be6baa 100644 --- a/thermal/ThermalModule.h +++ b/thermal/ThermalModule.h @@ -1,8 +1,8 @@ #ifndef THERMALMODULE_H_ #define THERMALMODULE_H_ -#include "../datapool/DataSet.h" -#include "../datapool/PoolVariable.h" +#include "../datapoolglob/GlobalDataSet.h" +#include "../datapoolglob/GlobalPoolVariable.h" #include "../devicehandlers/HealthDevice.h" #include "../events/EventReportingProxyIF.h" #include "ThermalModuleIF.h" @@ -11,6 +11,9 @@ #include "RedundantHeater.h" class PowerSwitchIF; +/** + * @brief Allows creation of different thermal control domains within a system. + */ class ThermalModule: public ThermalModuleIF { friend class ThermalController; public: @@ -20,10 +23,10 @@ public: }; ThermalModule(uint32_t moduleTemperaturePoolId, uint32_t currentStatePoolId, - uint32_t targetStatePoolId, DataSet *dataSet, Parameters parameters, + uint32_t targetStatePoolId, GlobDataSet *dataSet, Parameters parameters, RedundantHeater::Parameters heaterParameters); - ThermalModule(uint32_t moduleTemperaturePoolId, DataSet *dataSet); + ThermalModule(uint32_t moduleTemperaturePoolId, GlobDataSet *dataSet); virtual ~ThermalModule(); @@ -67,12 +70,12 @@ protected: Parameters parameters; - db_float_t moduleTemperature; + gp_float_t moduleTemperature; RedundantHeater *heater; - db_int8_t currentState; - db_int8_t targetState; + gp_int8_t currentState; + gp_int8_t targetState; std::list sensors; std::list components; From f61056eeb7213cf111c35dde65827e55b2cd8d0a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 6 Sep 2020 15:30:56 +0200 Subject: [PATCH 318/653] adapted DHB to renaming --- devicehandlers/DeviceHandlerBase.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 017ea8d2..6fcba64b 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -5,8 +5,8 @@ #include "../objectmanager/ObjectManager.h" #include "../storagemanager/StorageManagerIF.h" #include "../thermal/ThermalComponentIF.h" -#include "../datapool/DataSet.h" -#include "../datapool/PoolVariable.h" +#include "../datapoolglob/GlobalDataSet.h" +#include "../datapoolglob/GlobalPoolVariable.h" #include "../globalfunctions/CRC.h" #include "../subsystem/SubsystemBase.h" #include "../ipc/QueueFactory.h" @@ -186,8 +186,8 @@ ReturnValue_t DeviceHandlerBase::initialize() { fillCommandAndReplyMap(); //Set temperature target state to NON_OP. - DataSet mySet; - db_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, + GlobDataSet mySet; + gp_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_WRITE); mySet.read(); thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; @@ -469,8 +469,8 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) { Clock::getUptime(&timeoutStart); if (mode == MODE_OFF) { - DataSet mySet; - db_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, + GlobDataSet mySet; + gp_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { @@ -926,10 +926,10 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, if ((commandedMode == MODE_ON) && (mode == MODE_OFF) && (deviceThermalStatePoolId != PoolVariableIF::NO_PARAMETER)) { - DataSet mySet; - db_int8_t thermalState(deviceThermalStatePoolId, &mySet, + GlobDataSet mySet; + gp_int8_t thermalState(deviceThermalStatePoolId, &mySet, PoolVariableIF::VAR_READ); - db_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, + gp_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_READ); mySet.read(); if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { @@ -956,8 +956,8 @@ void DeviceHandlerBase::startTransition(Mode_t commandedMode, childTransitionDelay = getTransitionDelayMs(_MODE_START_UP, MODE_ON); triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode); - DataSet mySet; - db_int8_t thermalRequest(deviceThermalRequestPoolId, + GlobDataSet mySet; + gp_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { @@ -1185,7 +1185,7 @@ void DeviceHandlerBase::handleDeviceTM(SerializeIF* data, } //Try to cast to GlobDataSet and commit data. if (!neverInDataPool) { - DataSet* dataSet = dynamic_cast(data); + GlobDataSet* dataSet = dynamic_cast(data); if (dataSet != NULL) { dataSet->commit(PoolVariableIF::VALID); } From a9975f5aefe3698149b5f9b47e0b193007fb399a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 6 Sep 2020 15:46:49 +0200 Subject: [PATCH 319/653] added new windows udp bridge --- fsfw.mk | 16 +++ osal/windows/TcWinUdpPollingTask.cpp | 148 ++++++++++++++++++++++ osal/windows/TcWinUdpPollingTask.h | 67 ++++++++++ osal/windows/TmTcWinUdpBridge.cpp | 176 +++++++++++++++++++++++++++ osal/windows/TmTcWinUdpBridge.h | 49 ++++++++ 5 files changed, 456 insertions(+) create mode 100644 osal/windows/TcWinUdpPollingTask.cpp create mode 100644 osal/windows/TcWinUdpPollingTask.h create mode 100644 osal/windows/TmTcWinUdpBridge.cpp create mode 100644 osal/windows/TmTcWinUdpBridge.h diff --git a/fsfw.mk b/fsfw.mk index c2c6e747..c5847554 100644 --- a/fsfw.mk +++ b/fsfw.mk @@ -9,6 +9,9 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/controller/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/coordinates/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datalinklayer/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapool/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoolglob/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoollocal/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/housekeeping/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/devicehandlers/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/eventmatching/*.cpp) @@ -28,12 +31,25 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/*.cpp) # select the OS ifeq ($(OS_FSFW),rtems) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/rtems/*.cpp) + else ifeq ($(OS_FSFW),linux) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/linux/*.cpp) + else ifeq ($(OS_FSFW),freeRTOS) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/FreeRTOS/*.cpp) + else ifeq ($(OS_FSFW),host) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/host/*.cpp) +ifeq ($(OS),Windows_NT) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/windows/*.cpp) +else +# For now, the linux UDP bridge sources needs to be included manually by upper makefile +# for host OS because we can't be sure the OS is linux. +# Following lines can be used to do this: +# CXXSRC += $(FRAMEWORK_PATH)/osal/linux/TcUnixUdpPollingTask.cpp +# CXXSRC += $(FRAMEWORK_PATH)/osal/linux/TmTcUnixUdpBridge.cpp +endif + else $(error invalid OS_FSFW specified, valid OS_FSFW are rtems, linux, freeRTOS, host) endif diff --git a/osal/windows/TcWinUdpPollingTask.cpp b/osal/windows/TcWinUdpPollingTask.cpp new file mode 100644 index 00000000..7b54bb2c --- /dev/null +++ b/osal/windows/TcWinUdpPollingTask.cpp @@ -0,0 +1,148 @@ +#include "TcWinUdpPollingTask.h" +#include "../../globalfunctions/arrayprinter.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +#include +#include + +TcWinUdpPollingTask::TcWinUdpPollingTask(object_id_t objectId, + object_id_t tmtcUnixUdpBridge, size_t frameSize, + double timeoutSeconds): SystemObject(objectId), + tmtcBridgeId(tmtcUnixUdpBridge) { + if(frameSize > 0) { + this->frameSize = frameSize; + } + else { + this->frameSize = DEFAULT_MAX_FRAME_SIZE; + } + + // Set up reception buffer with specified frame size. + // For now, it is assumed that only one frame is held in the buffer! + receptionBuffer.reserve(this->frameSize); + receptionBuffer.resize(this->frameSize); + + if(timeoutSeconds == -1) { + receptionTimeout = DEFAULT_TIMEOUT; + } + else { + receptionTimeout = timevalOperations::toTimeval(timeoutSeconds); + } +} + +TcWinUdpPollingTask::~TcWinUdpPollingTask() {} + +ReturnValue_t TcWinUdpPollingTask::performOperation(uint8_t opCode) { + // Poll for new UDP datagrams in permanent loop. + while(true) { + //! Sender Address is cached here. + struct sockaddr_in senderAddress; + int senderAddressSize = sizeof(senderAddress); + ssize_t bytesReceived = recvfrom(serverUdpSocket, + reinterpret_cast(receptionBuffer.data()), frameSize, + receptionFlags, reinterpret_cast(&senderAddress), + &senderAddressSize); + if(bytesReceived == SOCKET_ERROR) { + // handle error + sif::error << "TcWinUdpPollingTask::performOperation: Reception" + " error." << std::endl; + handleReadError(); + continue; + } + //sif::debug << "TcWinUdpPollingTask::performOperation: " << bytesReceived + // << " bytes received" << std::endl; + + ReturnValue_t result = handleSuccessfullTcRead(bytesReceived); + if(result != HasReturnvaluesIF::RETURN_FAILED) { + + } + tmtcBridge->registerCommConnect(); + tmtcBridge->checkAndSetClientAddress(senderAddress); + } + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t TcWinUdpPollingTask::handleSuccessfullTcRead(size_t bytesRead) { + store_address_t storeId; + ReturnValue_t result = tcStore->addData(&storeId, + receptionBuffer.data(), bytesRead); + // arrayprinter::print(receptionBuffer.data(), bytesRead); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "TcSerialPollingTask::transferPusToSoftwareBus: Data " + "storage failed" << std::endl; + sif::error << "Packet size: " << bytesRead << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + TmTcMessage message(storeId); + + result = MessageQueueSenderIF::sendMessage(targetTcDestination, &message); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "Serial Polling: Sending message to queue failed" + << std::endl; + tcStore->deleteData(storeId); + } + return result; +} + +ReturnValue_t TcWinUdpPollingTask::initialize() { + tcStore = objectManager->get(objects::TC_STORE); + if (tcStore == nullptr) { + sif::error << "TcSerialPollingTask::initialize: TC Store uninitialized!" + << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + + tmtcBridge = objectManager->get(tmtcBridgeId); + if(tmtcBridge == nullptr) { + sif::error << "TcSocketPollingTask::TcSocketPollingTask: Invalid" + " TMTC bridge object!" << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + + serverUdpSocket = tmtcBridge->serverSocket; + //sif::info << "TcWinUdpPollingTask::initialize: Server UDP socket " + // << serverUdpSocket << std::endl; + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t TcWinUdpPollingTask::initializeAfterTaskCreation() { + // Initialize the destination after task creation. This ensures + // that the destination has already been set in the TMTC bridge. + targetTcDestination = tmtcBridge->getRequestQueue(); + return HasReturnvaluesIF::RETURN_OK; +} + +void TcWinUdpPollingTask::setTimeout(double timeoutSeconds) { + DWORD timeoutMs = timeoutSeconds * 1000.0; + int result = setsockopt(serverUdpSocket, SOL_SOCKET, SO_RCVTIMEO, + reinterpret_cast(&timeoutMs), sizeof(DWORD)); + if(result == -1) { + sif::error << "TcSocketPollingTask::TcSocketPollingTask: Setting " + "receive timeout failed with " << strerror(errno) << std::endl; + } +} + +void TcWinUdpPollingTask::handleReadError() { + int error = WSAGetLastError(); + switch(error) { + case(WSANOTINITIALISED): { + sif::info << "TmTcWinUdpBridge::handleReadError: WSANOTINITIALISED: " + << "WSAStartup(...) call " << "necessary" << std::endl; + break; + } + case(WSAEFAULT): { + sif::info << "TmTcWinUdpBridge::handleReadError: WSADEFAULT: " + << "Bad address " << std::endl; + break; + } + default: { + sif::info << "TmTcWinUdpBridge::handleReadError: Error code: " + << error << std::endl; + break; + } + } + // to prevent spam. + Sleep(1000); +} diff --git a/osal/windows/TcWinUdpPollingTask.h b/osal/windows/TcWinUdpPollingTask.h new file mode 100644 index 00000000..50d39d25 --- /dev/null +++ b/osal/windows/TcWinUdpPollingTask.h @@ -0,0 +1,67 @@ +#ifndef FSFW_OSAL_WINDOWS_TCSOCKETPOLLINGTASK_H_ +#define FSFW_OSAL_WINDOWS_TCSOCKETPOLLINGTASK_H_ + +#include "TmTcWinUdpBridge.h" +#include "../../objectmanager/SystemObject.h" +#include "../../tasks/ExecutableObjectIF.h" +#include "../../storagemanager/StorageManagerIF.h" + +#include + +/** + * @brief This class can be used to implement the polling of a Unix socket, + * using UDP for now. + * @details + * The task will be blocked while the specified number of bytes has not been + * received, so TC reception is handled inside a separate task. + * This class caches the IP address of the sender. It is assumed there + * is only one sender for now. + */ +class TcWinUdpPollingTask: public SystemObject, + public ExecutableObjectIF { + friend class TmTcWinUdpBridge; +public: + static constexpr size_t DEFAULT_MAX_FRAME_SIZE = 2048; + //! 0.5 default milliseconds timeout for now. + static constexpr timeval DEFAULT_TIMEOUT = {.tv_sec = 0, .tv_usec = 500}; + + TcWinUdpPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge, + size_t frameSize = 0, double timeoutSeconds = -1); + virtual~ TcWinUdpPollingTask(); + + /** + * Turn on optional timeout for UDP polling. In the default mode, + * the receive function will block until a packet is received. + * @param timeoutSeconds + */ + void setTimeout(double timeoutSeconds); + + virtual ReturnValue_t performOperation(uint8_t opCode) override; + virtual ReturnValue_t initialize() override; + virtual ReturnValue_t initializeAfterTaskCreation() override; + +protected: + StorageManagerIF* tcStore = nullptr; + +private: + //! TMTC bridge is cached. + object_id_t tmtcBridgeId = objects::NO_OBJECT; + TmTcWinUdpBridge* tmtcBridge = nullptr; + MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE; + //! Reception flags: https://linux.die.net/man/2/recvfrom. + int receptionFlags = 0; + + //! Server socket, which is member of TMTC bridge and is assigned in + //! constructor + SOCKET serverUdpSocket = 0; + + std::vector receptionBuffer; + + size_t frameSize = 0; + timeval receptionTimeout; + + ReturnValue_t handleSuccessfullTcRead(size_t bytesRead); + void handleReadError(); +}; + +#endif /* FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ */ diff --git a/osal/windows/TmTcWinUdpBridge.cpp b/osal/windows/TmTcWinUdpBridge.cpp new file mode 100644 index 00000000..7e283c2a --- /dev/null +++ b/osal/windows/TmTcWinUdpBridge.cpp @@ -0,0 +1,176 @@ +#include +#include "TmTcWinUdpBridge.h" + +TmTcWinUdpBridge::TmTcWinUdpBridge(object_id_t objectId, + object_id_t tcDestination, object_id_t tmStoreId, object_id_t tcStoreId, + uint16_t serverPort, uint16_t clientPort): + TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) { + mutex = MutexFactory::instance()->createMutex(); + + // Initiates Winsock DLL. + WSAData wsaData; + WORD wVersionRequested = MAKEWORD(2, 2); + int err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) { + /* Tell the user that we could not find a usable */ + /* Winsock DLL. */ + sif::error << "TmTcWinUdpBridge::TmTcWinUdpBridge:" + "WSAStartup failed with error: " << err << std::endl; + return; + } + + uint16_t setServerPort = DEFAULT_UDP_SERVER_PORT; + if(serverPort != 0xFFFF) { + setServerPort = serverPort; + } + + uint16_t setClientPort = DEFAULT_UDP_CLIENT_PORT; + if(clientPort != 0xFFFF) { + setClientPort = clientPort; + } + + // Set up UDP socket: https://man7.org/linux/man-pages/man7/ip.7.html + //clientSocket = socket(AF_INET, SOCK_DGRAM, 0); + serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if(serverSocket == INVALID_SOCKET) { + sif::error << "TmTcWinUdpBridge::TmTcWinUdpBridge: Could not open" + " UDP socket!" << std::endl; + handleSocketError(); + return; + } + + serverAddress.sin_family = AF_INET; + + // Accept packets from any interface. (potentially insecure). + serverAddress.sin_addr.s_addr = htonl(INADDR_ANY); + serverAddress.sin_port = htons(setServerPort); + serverAddressLen = sizeof(serverAddress); + setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, + reinterpret_cast(&serverSocketOptions), + sizeof(serverSocketOptions)); + + clientAddress.sin_family = AF_INET; + clientAddress.sin_addr.s_addr = htonl(INADDR_ANY); + clientAddress.sin_port = htons(setClientPort); + clientAddressLen = sizeof(clientAddress); + + int result = bind(serverSocket, + reinterpret_cast(&serverAddress), + serverAddressLen); + if(result != 0) { + sif::error << "TmTcWinUdpBridge::TmTcWinUdpBridge: Could not bind " + "local port " << setServerPort << " to server socket!" + << std::endl; + handleBindError(); + } +} + +TmTcWinUdpBridge::~TmTcWinUdpBridge() { + WSACleanup(); +} + +ReturnValue_t TmTcWinUdpBridge::sendTm(const uint8_t *data, size_t dataLen) { + int flags = 0; + + //clientAddress.sin_addr.s_addr = htons(INADDR_ANY); + //clientAddressLen = sizeof(serverAddress); + +// char ipAddress [15]; +// sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET, +// &clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; + + ssize_t bytesSent = sendto(serverSocket, + reinterpret_cast(data), dataLen, flags, + reinterpret_cast(&clientAddress), clientAddressLen); + if(bytesSent == SOCKET_ERROR) { + sif::error << "TmTcWinUdpBridge::sendTm: Send operation failed." + << std::endl; + handleSendError(); + } +// sif::debug << "TmTcUnixUdpBridge::sendTm: " << bytesSent << " bytes were" +// " sent." << std::endl; + return HasReturnvaluesIF::RETURN_OK; + return HasReturnvaluesIF::RETURN_OK; +} + +void TmTcWinUdpBridge::checkAndSetClientAddress(sockaddr_in newAddress) { + MutexHelper lock(mutex, MutexIF::TimeoutType::WAITING, 10); + +// char ipAddress [15]; +// sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET, +// &newAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; +// sif::debug << "IP Address Old: " << inet_ntop(AF_INET, +// &clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; + + // Set new IP address if it has changed. + if(clientAddress.sin_addr.s_addr != newAddress.sin_addr.s_addr) { + clientAddress.sin_addr.s_addr = newAddress.sin_addr.s_addr; + clientAddressLen = sizeof(clientAddress); + } +} + +void TmTcWinUdpBridge::handleSocketError() { + int errCode = WSAGetLastError(); + switch(errCode) { + case(WSANOTINITIALISED): { + sif::info << "TmTcWinUdpBridge::handleSocketError: WSANOTINITIALISED: " + << "WSAStartup(...) call " << "necessary" << std::endl; + break; + } + default: { + /* + https://docs.microsoft.com/en-us/windows/win32/winsock/ + windows-sockets-error-codes-2 + */ + sif::info << "TmTcWinUdpBridge::handleSocketError: Error code: " + << errCode << std::endl; + break; + } + } +} + +void TmTcWinUdpBridge::handleBindError() { + int errCode = WSAGetLastError(); + switch(errCode) { + case(WSANOTINITIALISED): { + sif::info << "TmTcWinUdpBridge::handleBindError: WSANOTINITIALISED: " + << "WSAStartup(...) call " << "necessary" << std::endl; + break; + } + default: { + /* + https://docs.microsoft.com/en-us/windows/win32/winsock/ + windows-sockets-error-codes-2 + */ + sif::info << "TmTcWinUdpBridge::handleBindError: Error code: " + << errCode << std::endl; + break; + } + } +} + +void TmTcWinUdpBridge::handleSendError() { + int errCode = WSAGetLastError(); + switch(errCode) { + case(WSANOTINITIALISED): { + sif::info << "TmTcWinUdpBridge::handleSendError: WSANOTINITIALISED: " + << "WSAStartup(...) call " << "necessary" << std::endl; + break; + } + case(WSAEADDRNOTAVAIL): { + sif::info << "TmTcWinUdpBridge::handleReadError: WSAEADDRNOTAVAIL: " + << "Check target address. " << std::endl; + break; + } + default: { + /* + https://docs.microsoft.com/en-us/windows/win32/winsock/ + windows-sockets-error-codes-2 + */ + sif::info << "TmTcWinUdpBridge::handleSendError: Error code: " + << errCode << std::endl; + break; + } + } +} + diff --git a/osal/windows/TmTcWinUdpBridge.h b/osal/windows/TmTcWinUdpBridge.h new file mode 100644 index 00000000..8188039c --- /dev/null +++ b/osal/windows/TmTcWinUdpBridge.h @@ -0,0 +1,49 @@ +#ifndef FSFW_OSAL_WINDOWS_TMTCWINUDPBRIDGE_H_ +#define FSFW_OSAL_WINDOWS_TMTCWINUDPBRIDGE_H_ + +#include "../../tmtcservices/TmTcBridge.h" + +#include +#include + +class TmTcWinUdpBridge: public TmTcBridge { + friend class TcWinUdpPollingTask; +public: + // The ports chosen here should not be used by any other process. + static constexpr uint16_t DEFAULT_UDP_SERVER_PORT = 7301; + static constexpr uint16_t DEFAULT_UDP_CLIENT_PORT = 7302; + + TmTcWinUdpBridge(object_id_t objectId, object_id_t tcDestination, + object_id_t tmStoreId, object_id_t tcStoreId, + uint16_t serverPort = 0xFFFF,uint16_t clientPort = 0xFFFF); + virtual~ TmTcWinUdpBridge(); + + void checkAndSetClientAddress(sockaddr_in clientAddress); + +protected: + virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override; + +private: + SOCKET serverSocket = 0; + + const int serverSocketOptions = 0; + + struct sockaddr_in clientAddress; + int clientAddressLen = 0; + + struct sockaddr_in serverAddress; + int serverAddressLen = 0; + + //! Access to the client address is mutex protected as it is set + //! by another task. + MutexIF* mutex; + + void handleSocketError(); + void handleBindError(); + void handleSendError(); +}; + + + +#endif /* FSFW_OSAL_HOST_TMTCWINUDPBRIDGE_H_ */ + From 2439ac455be631938c69fe6400ed025f7eaaaaa5 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 6 Sep 2020 15:48:30 +0200 Subject: [PATCH 320/653] tmtc bridge update, uses dynamic FIFO now --- tmtcservices/TmTcBridge.cpp | 108 ++++++++++++++++++++++-------------- tmtcservices/TmTcBridge.h | 20 +++++-- 2 files changed, 81 insertions(+), 47 deletions(-) diff --git a/tmtcservices/TmTcBridge.cpp b/tmtcservices/TmTcBridge.cpp index 021b0d7b..8c2f15e5 100644 --- a/tmtcservices/TmTcBridge.cpp +++ b/tmtcservices/TmTcBridge.cpp @@ -1,7 +1,7 @@ -#include "TmTcBridge.h" +#include "../tmtcservices/TmTcBridge.h" #include "../ipc/QueueFactory.h" -#include "AcceptsTelecommandsIF.h" +#include "../tmtcservices/AcceptsTelecommandsIF.h" #include "../serviceinterface/ServiceInterfaceStream.h" #include "../globalfunctions/arrayprinter.h" @@ -66,6 +66,8 @@ ReturnValue_t TmTcBridge::initialize() { return ObjectManagerIF::CHILD_INIT_FAILED; } + tmFifo = new DynamicFIFO(maxNumberOfPacketsStored); + tmTcReceptionQueue->setDefaultDestination(tcDistributor->getRequestQueue()); return RETURN_OK; } @@ -90,102 +92,122 @@ ReturnValue_t TmTcBridge::handleTc() { } ReturnValue_t TmTcBridge::handleTm() { + ReturnValue_t status = HasReturnvaluesIF::RETURN_OK; ReturnValue_t result = handleTmQueue(); if(result != RETURN_OK) { - sif::warning << "TmTcBridge: Reading TM Queue failed" << std::endl; - return RETURN_FAILED; + sif::error << "TmTcBridge::handleTm: Error handling TM queue!" + << std::endl; + status = result; } - if(tmStored and communicationLinkUp) { - result = handleStoredTm(); + if(tmStored and communicationLinkUp and + (packetSentCounter < sentPacketsPerCycle)) { + result = handleStoredTm(); + if(result != RETURN_OK) { + sif::error << "TmTcBridge::handleTm: Error handling stored TMs!" + << std::endl; + status = result; + } } - return result; - + packetSentCounter = 0; + return status; } ReturnValue_t TmTcBridge::handleTmQueue() { TmTcMessage message; const uint8_t* data = nullptr; size_t size = 0; + ReturnValue_t status = HasReturnvaluesIF::RETURN_OK; for (ReturnValue_t result = tmTcReceptionQueue->receiveMessage(&message); - result == RETURN_OK; result = tmTcReceptionQueue->receiveMessage(&message)) + result == HasReturnvaluesIF::RETURN_OK; + result = tmTcReceptionQueue->receiveMessage(&message)) { - if(communicationLinkUp == false) { - result = storeDownlinkData(&message); - return result; + //sif::info << (int) packetSentCounter << std::endl; + if(communicationLinkUp == false or + packetSentCounter >= sentPacketsPerCycle) { + storeDownlinkData(&message); + continue; } result = tmStore->getData(message.getStorageId(), &data, &size); if (result != HasReturnvaluesIF::RETURN_OK) { + status = result; continue; } result = sendTm(data, size); - if (result != RETURN_OK) { - sif::warning << "TmTcBridge: Could not send TM packet" << std::endl; - tmStore->deleteData(message.getStorageId()); - return result; - + if (result != HasReturnvaluesIF::RETURN_OK) { + status = result; + } + else { + tmStore->deleteData(message.getStorageId()); + packetSentCounter++; } - tmStore->deleteData(message.getStorageId()); } - return RETURN_OK; + return status; } ReturnValue_t TmTcBridge::storeDownlinkData(TmTcMessage *message) { store_address_t storeId = 0; - if(tmFifo.full()) { - sif::error << "TmTcBridge::storeDownlinkData: TM downlink max. number " - << "of stored packet IDs reached! " - << "Overwriting old data" << std::endl; - tmFifo.retrieve(&storeId); - tmStore->deleteData(storeId); + if(tmFifo->full()) { + sif::debug << "TmTcBridge::storeDownlinkData: TM downlink max. number " + << "of stored packet IDs reached! " << std::endl; + if(overwriteOld) { + tmFifo->retrieve(&storeId); + tmStore->deleteData(storeId); + } + else { + return HasReturnvaluesIF::RETURN_FAILED; + } } + storeId = message->getStorageId(); - tmFifo.insert(storeId); + tmFifo->insert(storeId); tmStored = true; return RETURN_OK; } ReturnValue_t TmTcBridge::handleStoredTm() { - uint8_t counter = 0; - ReturnValue_t result = RETURN_OK; - while(not tmFifo.empty() and counter < sentPacketsPerCycle) { - //info << "TMTC Bridge: Sending stored TM data. There are " - // << (int) fifo.size() << " left to send\r\n" << std::flush; + ReturnValue_t status = RETURN_OK; + while(not tmFifo->empty() and packetSentCounter < sentPacketsPerCycle) { + //sif::info << "TMTC Bridge: Sending stored TM data. There are " + // << (int) tmFifo->size() << " left to send\r\n" << std::flush; + store_address_t storeId; const uint8_t* data = nullptr; size_t size = 0; - tmFifo.retrieve(&storeId); - result = tmStore->getData(storeId, &data, &size); - - sendTm(data,size); + tmFifo->retrieve(&storeId); + ReturnValue_t result = tmStore->getData(storeId, &data, &size); + if(result != HasReturnvaluesIF::RETURN_OK) { + status = result; + } + result = sendTm(data,size); if(result != RETURN_OK) { sif::error << "TMTC Bridge: Could not send stored downlink data" << std::endl; - result = RETURN_FAILED; + status = result; } - counter ++; + packetSentCounter ++; - if(tmFifo.empty()) { + if(tmFifo->empty()) { tmStored = false; } tmStore->deleteData(storeId); } - return result; + return status; } void TmTcBridge::registerCommConnect() { if(not communicationLinkUp) { - //info << "TMTC Bridge: Registered Comm Link Connect" << std::endl; + //sif::info << "TMTC Bridge: Registered Comm Link Connect" << std::endl; communicationLinkUp = true; } } void TmTcBridge::registerCommDisconnect() { - //info << "TMTC Bridge: Registered Comm Link Disconnect" << std::endl; + //sif::info << "TMTC Bridge: Registered Comm Link Disconnect" << std::endl; if(communicationLinkUp) { communicationLinkUp = false; } @@ -209,3 +231,7 @@ MessageQueueId_t TmTcBridge::getRequestQueue() { // Default implementation: Relay TC messages to TC distributor directly. return tmTcReceptionQueue->getDefaultDestination(); } + +void TmTcBridge::setFifoToOverwriteOldData(bool overwriteOld) { + this->overwriteOld = overwriteOld; +} diff --git a/tmtcservices/TmTcBridge.h b/tmtcservices/TmTcBridge.h index 32eaf7f2..62cfdaac 100644 --- a/tmtcservices/TmTcBridge.h +++ b/tmtcservices/TmTcBridge.h @@ -1,15 +1,15 @@ #ifndef FRAMEWORK_TMTCSERVICES_TMTCBRIDGE_H_ #define FRAMEWORK_TMTCSERVICES_TMTCBRIDGE_H_ + #include "../objectmanager/SystemObject.h" -#include "AcceptsTelemetryIF.h" +#include "../tmtcservices/AcceptsTelemetryIF.h" #include "../tasks/ExecutableObjectIF.h" #include "../ipc/MessageQueueIF.h" #include "../storagemanager/StorageManagerIF.h" -#include "AcceptsTelecommandsIF.h" - -#include "../container/FIFO.h" -#include "TmTcMessage.h" +#include "../tmtcservices/AcceptsTelecommandsIF.h" +#include "../container/DynamicFIFO.h" +#include "../tmtcservices/TmTcMessage.h" class TmTcBridge : public AcceptsTelemetryIF, public AcceptsTelecommandsIF, @@ -46,6 +46,12 @@ public: */ ReturnValue_t setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored); + /** + * This will set up the bridge to overwrite old data in the FIFO. + * @param overwriteOld + */ + void setFifoToOverwriteOldData(bool overwriteOld); + virtual void registerCommConnect(); virtual void registerCommDisconnect(); @@ -86,6 +92,8 @@ protected: //! by default, so telemetry will be handled immediately. bool communicationLinkUp = true; bool tmStored = false; + bool overwriteOld = true; + uint8_t packetSentCounter = 0; /** * @brief Handle TC reception @@ -145,7 +153,7 @@ protected: * This fifo can be used to store downlink data * which can not be sent at the moment. */ - FIFO tmFifo; + DynamicFIFO* tmFifo = nullptr; uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE; uint8_t maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED; }; From 6c42189371dd76082fe93e7f832c509e8967b402 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 6 Sep 2020 15:49:32 +0200 Subject: [PATCH 321/653] some minor improvements --- osal/linux/TcUnixUdpPollingTask.cpp | 1 + osal/linux/TmTcUnixUdpBridge.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osal/linux/TcUnixUdpPollingTask.cpp b/osal/linux/TcUnixUdpPollingTask.cpp index 95910b02..670ba804 100644 --- a/osal/linux/TcUnixUdpPollingTask.cpp +++ b/osal/linux/TcUnixUdpPollingTask.cpp @@ -120,6 +120,7 @@ void TcUnixUdpPollingTask::setTimeout(double timeoutSeconds) { } } +// TODO: sleep after error detection to prevent spam void TcUnixUdpPollingTask::handleReadError() { switch(errno) { case(EAGAIN): { diff --git a/osal/linux/TmTcUnixUdpBridge.cpp b/osal/linux/TmTcUnixUdpBridge.cpp index 80d02b25..b55291b3 100644 --- a/osal/linux/TmTcUnixUdpBridge.cpp +++ b/osal/linux/TmTcUnixUdpBridge.cpp @@ -5,6 +5,7 @@ #include #include + TmTcUnixUdpBridge::TmTcUnixUdpBridge(object_id_t objectId, object_id_t tcDestination, object_id_t tmStoreId, object_id_t tcStoreId, uint16_t serverPort, uint16_t clientPort): @@ -100,8 +101,8 @@ void TmTcUnixUdpBridge::checkAndSetClientAddress(sockaddr_in newAddress) { } } -void TmTcUnixUdpBridge::handleSocketError() { +void TmTcUnixUdpBridge::handleSocketError() { // See: https://man7.org/linux/man-pages/man2/socket.2.html switch(errno) { case(EACCES): @@ -162,7 +163,8 @@ void TmTcUnixUdpBridge::handleBindError() { void TmTcUnixUdpBridge::handleSendError() { switch(errno) { default: - sif::error << "Error: " << strerror(errno) << std::endl; + sif::error << "TmTcUnixBridge::handleSendError: " + << strerror(errno) << std::endl; } } From 2a28114b49fc48d01e95bb350d8c52d299bcab5c Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Mon, 7 Sep 2020 15:43:48 +0200 Subject: [PATCH 322/653] Fixes for #190 and #189 --- container/DynamicFIFO.h | 16 ++++++++++++++-- container/FIFO.h | 12 ++++++++++++ container/FixedMap.h | 3 +++ tmtcservices/CommandingServiceBase.h | 17 +++++++++++++++-- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/container/DynamicFIFO.h b/container/DynamicFIFO.h index abb53330..8f5c5e40 100644 --- a/container/DynamicFIFO.h +++ b/container/DynamicFIFO.h @@ -27,14 +27,26 @@ public: /** * @brief Custom copy constructor which prevents setting the - * underlying pointer wrong. + * underlying pointer wrong. This function allocates memory! + * @details This is a very heavy operation so try to avoid this! + * */ DynamicFIFO(const DynamicFIFO& other): FIFOBase(other), fifoVector(other.maxCapacity) { this->setContainer(fifoVector.data()); } - + /** + * @brief Custom assignment operator + * @details This is a very heavy operation so try to avoid this! + * @param other DyamicFIFO to copy from + */ + DynamicFIFO& operator=(const DynamicFIFO& other){ + FIFOBase::operator=(other); + this->fifoVector = other.fifoVector; + this->setContainer(fifoVector.data()); + return *this; + } private: std::vector fifoVector; }; diff --git a/container/FIFO.h b/container/FIFO.h index 19f763fc..70113852 100644 --- a/container/FIFO.h +++ b/container/FIFO.h @@ -25,9 +25,21 @@ public: * @param other */ FIFO(const FIFO& other): FIFOBase(other) { + this->fifoArray = other.fifoArray; this->setContainer(fifoArray.data()); } + /** + * @brief Custom assignment operator + * @param other + */ + FIFO& operator=(const FIFO& other){ + FIFOBase::operator=(other); + this->fifoArray = other.fifoArray; + this->setContainer(fifoArray.data()); + return *this; + } + private: std::array fifoArray; }; diff --git a/container/FixedMap.h b/container/FixedMap.h index dc19ce53..65459631 100644 --- a/container/FixedMap.h +++ b/container/FixedMap.h @@ -4,12 +4,15 @@ #include "ArrayList.h" #include "../returnvalues/HasReturnvaluesIF.h" #include +#include /** * \ingroup container */ template class FixedMap: public SerializeIF { + static_assert (std::is_trivially_copyable::value or std::is_base_of::value, + "Types used in FixedMap must either be trivial copy-able or a derived Class from SerializeIF to be serialize-able"); public: static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP; static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01); diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index 864a0614..23b08acf 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -211,8 +211,7 @@ protected: virtual void doPeriodicOperation(); - - struct CommandInfo { + struct CommandInfo: public SerializeIF{ struct tcInfo { uint8_t ackFlags; uint16_t tcPacketId; @@ -225,6 +224,20 @@ protected: Command_t command; object_id_t objectId; FIFO fifo; + + virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, + size_t maxSize, Endianness streamEndianness) const override{ + return HasReturnvaluesIF::RETURN_FAILED; + }; + + virtual size_t getSerializedSize() const override { + return 0; + }; + + virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override{ + return HasReturnvaluesIF::RETURN_FAILED; + }; }; using CommandMapIter = FixedMap Date: Mon, 7 Sep 2020 15:49:28 +0200 Subject: [PATCH 323/653] Another fix in DynamicFIFO --- container/DynamicFIFO.h | 1 + 1 file changed, 1 insertion(+) diff --git a/container/DynamicFIFO.h b/container/DynamicFIFO.h index 8f5c5e40..86d43f7d 100644 --- a/container/DynamicFIFO.h +++ b/container/DynamicFIFO.h @@ -33,6 +33,7 @@ public: */ DynamicFIFO(const DynamicFIFO& other): FIFOBase(other), fifoVector(other.maxCapacity) { + this->fifoVector = other.fifoVector; this->setContainer(fifoVector.data()); } From b65789824cc103d8fbc46479e6eff0f09c6346d6 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Mon, 7 Sep 2020 18:06:08 +0200 Subject: [PATCH 324/653] Removed old hacks and replaced by standard c++ Added overflow check in SerializeAdapter --- container/IsDerivedFrom.h | 41 ------------------------------------ serialize/SerializeAdapter.h | 32 ++++++++++++++++------------ 2 files changed, 18 insertions(+), 55 deletions(-) delete mode 100644 container/IsDerivedFrom.h diff --git a/container/IsDerivedFrom.h b/container/IsDerivedFrom.h deleted file mode 100644 index 520033db..00000000 --- a/container/IsDerivedFrom.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef ISDERIVEDFROM_H_ -#define ISDERIVEDFROM_H_ - -template -class IsDerivedFrom { - class No { - }; - class Yes { - No no[3]; - }; - - static Yes Test(B*); // declared, but not defined - static No Test(... ); // declared, but not defined - -public: - enum { - Is = sizeof(Test(static_cast(0))) == sizeof(Yes) - }; -}; - -template -struct is_same { - static bool const value = false; -}; - -template -struct is_same { - static bool const value = true; -}; - - -template -struct enable_if { - typedef T type; -}; - -template -struct enable_if { }; - - -#endif /* ISDERIVEDFROM_H_ */ diff --git a/serialize/SerializeAdapter.h b/serialize/SerializeAdapter.h index af5ec116..cd6b6b06 100644 --- a/serialize/SerializeAdapter.h +++ b/serialize/SerializeAdapter.h @@ -1,11 +1,11 @@ #ifndef SERIALIZEADAPTER_H_ #define SERIALIZEADAPTER_H_ -#include "../container/IsDerivedFrom.h" #include "../returnvalues/HasReturnvaluesIF.h" #include "EndianConverter.h" #include "SerializeIF.h" #include +#include /** * \ingroup serialize @@ -15,34 +15,39 @@ class SerializeAdapter { public: template static ReturnValue_t serialize(const T *object, uint8_t **buffer, - size_t *size, size_t maxSize, SerializeIF::Endianness streamEndianness) { - InternalSerializeAdapter::Is> adapter; + size_t *size, size_t maxSize, + SerializeIF::Endianness streamEndianness) { + InternalSerializeAdapter::value> adapter; return adapter.serialize(object, buffer, size, maxSize, streamEndianness); } template static uint32_t getSerializedSize(const T *object) { - InternalSerializeAdapter::Is> adapter; + InternalSerializeAdapter::value> adapter; return adapter.getSerializedSize(object); } template static ReturnValue_t deSerialize(T *object, const uint8_t **buffer, size_t *size, SerializeIF::Endianness streamEndianness) { - InternalSerializeAdapter::Is> adapter; + InternalSerializeAdapter::value> adapter; return adapter.deSerialize(object, buffer, size, streamEndianness); } private: - template - class InternalSerializeAdapter { + template class InternalSerializeAdapter; + + template + class InternalSerializeAdapter { public: static ReturnValue_t serialize(const T *object, uint8_t **buffer, - size_t *size, size_t max_size, SerializeIF::Endianness streamEndianness) { + size_t *size, size_t max_size, + SerializeIF::Endianness streamEndianness) { size_t ignoredSize = 0; if (size == NULL) { size = &ignoredSize; } - //TODO check integer overflow of *size - if (sizeof(T) + *size <= max_size) { + //Check remaining size is large enough and check integer overflow of *size + size_t newSize = sizeof(T) + *size; + if ((newSize <= max_size) and (newSize > *size)) { T tmp; switch (streamEndianness) { case SerializeIF::Endianness::BIG: @@ -94,14 +99,13 @@ private: uint32_t getSerializedSize(const T *object) { return sizeof(T); } - }; template - class InternalSerializeAdapter { + class InternalSerializeAdapter { public: - ReturnValue_t serialize(const T *object, uint8_t **buffer, - size_t *size, size_t max_size, + ReturnValue_t serialize(const T *object, uint8_t **buffer, size_t *size, + size_t max_size, SerializeIF::Endianness streamEndianness) const { size_t ignoredSize = 0; if (size == NULL) { From 0258ce62f0ccb64be8f87e17321627171601f348 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Mon, 7 Sep 2020 18:35:25 +0200 Subject: [PATCH 325/653] Added documentation --- serialize/SerializeAdapter.h | 71 ++++++++++++++++++++++++++++++++---- serialize/SerializeIF.h | 2 +- 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/serialize/SerializeAdapter.h b/serialize/SerializeAdapter.h index cd6b6b06..a05b1791 100644 --- a/serialize/SerializeAdapter.h +++ b/serialize/SerializeAdapter.h @@ -1,10 +1,10 @@ -#ifndef SERIALIZEADAPTER_H_ -#define SERIALIZEADAPTER_H_ +#ifndef _FSFW_SERIALIZE_SERIALIZEADAPTER_H_ +#define _FSFW_SERIALIZE_SERIALIZEADAPTER_H_ #include "../returnvalues/HasReturnvaluesIF.h" #include "EndianConverter.h" #include "SerializeIF.h" -#include +#include #include /** @@ -13,6 +13,22 @@ class SerializeAdapter { public: + /*** + * This function can be used to serialize a trivial copy-able type or a child of SerializeIF. + * The right template to be called is determined in the function itself. + * For objects of non trivial copy-able type this function is almost never called by the user directly. + * Instead helpers for specific types like SerialArrayListAdapter or SerialLinkedListAdapter is the right choice here. + * + * @param[in] object Object to serialize, the used type is deduced from this pointer + * @param[in/out] buffer Buffer to serialize into. Will be moved by the function. + * @param[in/out] size Size of current written buffer. Will be incremented by the function. + * @param[in] maxSize Max size of Buffer + * @param[in] streamEndianness Endianness of serialized element as in according to SerializeIF::Endianness + * @return + * - @c BUFFER_TOO_SHORT The given buffer in is too short + * - @c RETURN_FAILED Generic Error + * - @c RETURN_OK Successful serialization + */ template static ReturnValue_t serialize(const T *object, uint8_t **buffer, size_t *size, size_t maxSize, @@ -21,11 +37,35 @@ public: return adapter.serialize(object, buffer, size, maxSize, streamEndianness); } + /** + * Function to return the serialized size of the object in the pointer. + * May be a trivially copy-able object or a Child of SerializeIF + * + * @param object Pointer to Object + * @return Serialized size of object + */ template - static uint32_t getSerializedSize(const T *object) { + static size_t getSerializedSize(const T *object){ InternalSerializeAdapter::value> adapter; return adapter.getSerializedSize(object); } + /** + * @brief + * Deserializes a object from a given buffer of given size. + * Object Must be trivially copy-able or a child of SerializeIF. + * + * @details + * Buffer will be moved to the current read location. Size will be decreased by the function. + * + * @param[in/out] buffer Buffer to deSerialize from. Will be moved by the function. + * @param[in/out] size Remaining size of the buffer to read from. Will be decreased by function. + * @param[in] streamEndianness Endianness as in according to SerializeIF::Endianness + * @return + * - @c STREAM_TOO_SHORT The input stream is too short to deSerialize the object + * - @c TOO_MANY_ELEMENTS The buffer has more inputs than expected + * - @c RETURN_FAILED Generic Error + * - @c RETURN_OK Successful deserialization + */ template static ReturnValue_t deSerialize(T *object, const uint8_t **buffer, size_t *size, SerializeIF::Endianness streamEndianness) { @@ -33,16 +73,26 @@ public: return adapter.deSerialize(object, buffer, size, streamEndianness); } private: + /** + * Internal template to deduce the right function calls at compile time + */ template class InternalSerializeAdapter; + /** + * Template to be used if T is not a child of SerializeIF + * + * @tparam T T must be trivially_copyable + */ template class InternalSerializeAdapter { + static_assert (std::is_trivially_copyable::value, + "If a type needs to be serialized it must be a child of SerializeIF or trivially copy-able"); public: static ReturnValue_t serialize(const T *object, uint8_t **buffer, size_t *size, size_t max_size, SerializeIF::Endianness streamEndianness) { size_t ignoredSize = 0; - if (size == NULL) { + if (size == nullptr) { size = &ignoredSize; } //Check remaining size is large enough and check integer overflow of *size @@ -101,6 +151,11 @@ private: } }; + /** + * Template for objects that inherit from SerializeIF + * + * @tparam T A child of SerializeIF + */ template class InternalSerializeAdapter { public: @@ -108,12 +163,12 @@ private: size_t max_size, SerializeIF::Endianness streamEndianness) const { size_t ignoredSize = 0; - if (size == NULL) { + if (size == nullptr) { size = &ignoredSize; } return object->serialize(buffer, size, max_size, streamEndianness); } - uint32_t getSerializedSize(const T *object) const { + size_t getSerializedSize(const T *object) const { return object->getSerializedSize(); } @@ -124,4 +179,4 @@ private: }; }; -#endif /* SERIALIZEADAPTER_H_ */ +#endif /* _FSFW_SERIALIZE_SERIALIZEADAPTER_H_ */ diff --git a/serialize/SerializeIF.h b/serialize/SerializeIF.h index 7f9ea9df..a701fe53 100644 --- a/serialize/SerializeIF.h +++ b/serialize/SerializeIF.h @@ -43,7 +43,7 @@ public: * @param[in] maxSize The size of the buffer that is allowed to be used for serialize. * @param[in] streamEndianness Endianness of the serialized data according to SerializeIF::Endianness * @return - * - @¢ BUFFER_TOO_SHORT The given buffer in is too short + * - @c BUFFER_TOO_SHORT The given buffer in is too short * - @c RETURN_FAILED Generic error * - @c RETURN_OK Successful serialization */ From 1635f16bc03d13edb09144eb5ed5e4575cbe88ac Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 10 Sep 2020 15:26:33 +0200 Subject: [PATCH 326/653] removed changes from datapool separation --- fsfw.mk | 2 -- 1 file changed, 2 deletions(-) diff --git a/fsfw.mk b/fsfw.mk index c5847554..bf95727c 100644 --- a/fsfw.mk +++ b/fsfw.mk @@ -9,8 +9,6 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/controller/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/coordinates/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datalinklayer/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapool/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoolglob/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoollocal/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/housekeeping/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/devicehandlers/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/*.cpp) From e7444912d5eb69dc701b12f7de5f94d730d2992d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20M=C3=BCller?= Date: Thu, 10 Sep 2020 15:29:19 +0200 Subject: [PATCH 327/653] corrected include guard --- container/FixedMap.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/container/FixedMap.h b/container/FixedMap.h index 56a6140a..d1cc31ff 100644 --- a/container/FixedMap.h +++ b/container/FixedMap.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_CONTAINER_FIXEDMAP_H_ -#define FRAMEWORK_CONTAINER_FIXEDMAP_H_ +#ifndef FSFW_CONTAINER_FIXEDMAP_H_ +#define FSFW_CONTAINER_FIXEDMAP_H_ #include "ArrayList.h" #include "../returnvalues/HasReturnvaluesIF.h" @@ -7,11 +7,9 @@ #include /** - * \ingroup container - * - * - * \warning Iterators return a non-const key_t in the pair. - * \warning A User is not allowed to change the key, otherwise the map is corrupted. + * @warning Iterators return a non-const key_t in the pair. + * @warning A User is not allowed to change the key, otherwise the map is corrupted. + * @ingroup container */ template class FixedMap: public SerializeIF { @@ -194,4 +192,4 @@ public: }; -#endif /* FIXEDMAP_H_ */ +#endif /* FSFW_CONTAINER_FIXEDMAP_H_ */ From d807ea3afe15a69efbc87a8da59d37052e277238 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 10 Sep 2020 16:42:11 +0200 Subject: [PATCH 328/653] using MessageQueueIF::NO_QUEUE now --- health/HealthHelper.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/health/HealthHelper.cpp b/health/HealthHelper.cpp index cced11d9..d574634d 100644 --- a/health/HealthHelper.cpp +++ b/health/HealthHelper.cpp @@ -71,7 +71,7 @@ void HealthHelper::setHealth(HasHealthIF::HealthState health) { void HealthHelper::informParent(HasHealthIF::HealthState health, HasHealthIF::HealthState oldHealth) { - if (parentQueue == MessageQueueMessageIF::NO_QUEUE) { + if (parentQueue == MessageQueueIF::NO_QUEUE) { return; } CommandMessage information; @@ -86,7 +86,7 @@ void HealthHelper::informParent(HasHealthIF::HealthState health, void HealthHelper::handleSetHealthCommand(CommandMessage* command) { ReturnValue_t result = owner->setHealth(HealthMessage::getHealth(command)); - if (command->getSender() == MessageQueueMessageIF::NO_QUEUE) { + if (command->getSender() == MessageQueueIF::NO_QUEUE) { return; } CommandMessage reply; From d83573cefc14ea6ff6f45e694a3f29d533117797 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 10 Sep 2020 16:47:01 +0200 Subject: [PATCH 329/653] additional IDs removed --- returnvalues/FwClassIds.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/returnvalues/FwClassIds.h b/returnvalues/FwClassIds.h index 781320e3..80df5741 100644 --- a/returnvalues/FwClassIds.h +++ b/returnvalues/FwClassIds.h @@ -65,9 +65,6 @@ enum { POOL_VARIABLE_IF, //PVA 59 HOUSEKEEPING_MANAGER, //HKM 60 DLE_ENCODER, //DLEE 61 - PUS_PARSER, //PUSP 62 - SERIAL_ANALYZER, //SERA 63 - PUS_SERVICE_9, // PUS9 64 FW_CLASS_ID_COUNT //is actually count + 1 ! }; From 4f48ed9756a520520277d2efe2ebc46ed881eefd Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 10 Sep 2020 19:53:52 +0200 Subject: [PATCH 330/653] added new periodic op divider --- globalfunctions/PeriodicOperationDivider.cpp | 34 ++++++++++++ globalfunctions/PeriodicOperationDivider.h | 55 ++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 globalfunctions/PeriodicOperationDivider.cpp create mode 100644 globalfunctions/PeriodicOperationDivider.h diff --git a/globalfunctions/PeriodicOperationDivider.cpp b/globalfunctions/PeriodicOperationDivider.cpp new file mode 100644 index 00000000..ad3b8bbd --- /dev/null +++ b/globalfunctions/PeriodicOperationDivider.cpp @@ -0,0 +1,34 @@ +#include "PeriodicOperationDivider.h" + + +PeriodicOperationDivider::PeriodicOperationDivider(uint32_t divider, + bool resetAutomatically): resetAutomatically(resetAutomatically), + counter(divider), divider(divider) { +} + +bool PeriodicOperationDivider::checkAndIncrement() { + if(counter >= divider) { + if(resetAutomatically) { + counter = 0; + } + return true; + } + counter ++; + return false; +} + +void PeriodicOperationDivider::resetCounter() { + counter = 0; +} + +void PeriodicOperationDivider::setDivider(uint32_t newDivider) { + divider = newDivider; +} + +uint32_t PeriodicOperationDivider::getCounter() const { + return counter; +} + +uint32_t PeriodicOperationDivider::getDivider() const { + return divider; +} diff --git a/globalfunctions/PeriodicOperationDivider.h b/globalfunctions/PeriodicOperationDivider.h new file mode 100644 index 00000000..dd970fb8 --- /dev/null +++ b/globalfunctions/PeriodicOperationDivider.h @@ -0,0 +1,55 @@ +#ifndef FSFW_GLOBALFUNCTIONS_PERIODICOPERATIONDIVIDER_H_ +#define FSFW_GLOBALFUNCTIONS_PERIODICOPERATIONDIVIDER_H_ + +#include + +/** + * @brief Lightweight helper class to facilitate periodic operation with + * decreased frequencies. + * @details + * This class is useful to perform operations which have to be performed + * with a reduced frequency, like debugging printouts in high periodic tasks + * or low priority operations. + */ +class PeriodicOperationDivider { +public: + /** + * Initialize with the desired divider and specify whether the internal + * counter will be reset automatically. + * @param divider + * @param resetAutomatically + */ + PeriodicOperationDivider(uint32_t divider, bool resetAutomatically = true); + + /** + * Check whether operation is necessary. + * If an operation is necessary and the class has been + * configured to be reset automatically, the counter will be reset. + * If not, the counter will be incremented. + * @return + * -@c true if the counter is larger or equal to the divider + * -@c false otherwise + */ + bool checkAndIncrement(); + + /** + * Can be used to reset the counter to 0 manually. + */ + void resetCounter(); + uint32_t getCounter() const; + + /** + * Can be used to set a new divider value. + * @param newDivider + */ + void setDivider(uint32_t newDivider); + uint32_t getDivider() const; +private: + bool resetAutomatically = true; + uint32_t counter = 0; + uint32_t divider = 0; +}; + + + +#endif /* FSFW_GLOBALFUNCTIONS_PERIODICOPERATIONDIVIDER_H_ */ From b4ca42f1fb080951b0df65669759e985328c2284 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 15 Sep 2020 15:28:05 +0200 Subject: [PATCH 331/653] ccsds time update --- timemanager/CCSDSTime.cpp | 9 +++------ timemanager/CCSDSTime.h | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/timemanager/CCSDSTime.cpp b/timemanager/CCSDSTime.cpp index 12ecf34a..f99f8fbb 100644 --- a/timemanager/CCSDSTime.cpp +++ b/timemanager/CCSDSTime.cpp @@ -1,11 +1,8 @@ #include "../timemanager/CCSDSTime.h" -#include -#include -#include +#include +#include +#include -#ifndef SCNu8 - #define SCNu8 "hhu" -#endif CCSDSTime::CCSDSTime() { } diff --git a/timemanager/CCSDSTime.h b/timemanager/CCSDSTime.h index 8563cf0f..89fcff92 100644 --- a/timemanager/CCSDSTime.h +++ b/timemanager/CCSDSTime.h @@ -5,7 +5,7 @@ #include "Clock.h" #include "../returnvalues/HasReturnvaluesIF.h" -#include +#include bool operator<(const timeval& lhs, const timeval& rhs); bool operator<=(const timeval& lhs, const timeval& rhs); From e96ab123121d5d0039e60f3069b4a8b226fa7751 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 15 Sep 2020 15:55:35 +0200 Subject: [PATCH 332/653] comment and calculation fix --- ipc/CommandMessage.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ipc/CommandMessage.h b/ipc/CommandMessage.h index ca7b817f..8f5daa04 100644 --- a/ipc/CommandMessage.h +++ b/ipc/CommandMessage.h @@ -8,7 +8,7 @@ /** * @brief Default command message used to pass command messages between tasks. * Primary message type for IPC. Contains sender, 2-byte command ID - * field, and 2 4-byte parameters. + * field, and 3 4-byte parameter * @details * It operates on an external memory which is contained inside a * class implementing MessageQueueMessageIF by taking its address. @@ -23,10 +23,11 @@ class CommandMessage: public MessageQueueMessage, public CommandMessageIF { public: /** - * Default size can accomodate 2 4-byte parameters. + * Default size can accomodate 3 4-byte parameters. */ static constexpr size_t DEFAULT_COMMAND_MESSAGE_SIZE = - CommandMessageIF::MINIMUM_COMMAND_MESSAGE_SIZE + sizeof(uint32_t); + CommandMessageIF::MINIMUM_COMMAND_MESSAGE_SIZE + + 3 * sizeof(uint32_t); /** * @brief Default Constructor, does not initialize anything. From 3fcbb988ae0c299b48ed632761d690467426ca23 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 15 Sep 2020 16:47:01 +0200 Subject: [PATCH 333/653] new file for typedef to avoid circular include --- ipc/MessageQueueMessageIF.h | 17 +++-------------- ipc/MessageQueueSenderIF.h | 23 ++++++----------------- ipc/messageQueueDefinitions.h | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+), 31 deletions(-) create mode 100644 ipc/messageQueueDefinitions.h diff --git a/ipc/MessageQueueMessageIF.h b/ipc/MessageQueueMessageIF.h index 91753ced..b5a30c08 100644 --- a/ipc/MessageQueueMessageIF.h +++ b/ipc/MessageQueueMessageIF.h @@ -1,24 +1,13 @@ #ifndef FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_ #define FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_ + +#include #include #include -/* - * TODO: Actually, the definition of this ID to be a uint32_t is not ideal and - * breaks layering. However, it is difficult to keep layering, as the ID is - * stored in many places and sent around in MessageQueueMessage. - * Ideally, one would use the (current) object_id_t only, however, doing a - * lookup of queueIDs for every call does not sound ideal. - * In a first step, I'll circumvent the issue by not touching it, - * maybe in a second step. This also influences Interface design - * (getCommandQueue) and some other issues.. - */ - -typedef uint32_t MessageQueueId_t; - class MessageQueueMessageIF { public: - static const MessageQueueId_t NO_QUEUE = -1; + /** * @brief This constants defines the size of the header, * which is added to every message. diff --git a/ipc/MessageQueueSenderIF.h b/ipc/MessageQueueSenderIF.h index d9692f54..beb27f50 100644 --- a/ipc/MessageQueueSenderIF.h +++ b/ipc/MessageQueueSenderIF.h @@ -1,37 +1,26 @@ #ifndef FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ #define FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ +#include "../ipc/MessageQueueIF.h" +#include "../ipc/MessageQueueMessageIF.h" #include "../objectmanager/ObjectManagerIF.h" -class MessageQueueMessage; - - -//TODO: Actually, the definition of this ID to be a uint32_t is not ideal and breaks layering. -//However, it is difficult to keep layering, as the ID is stored in many places and sent around in -//MessageQueueMessage. -//Ideally, one would use the (current) object_id_t only, however, doing a lookup of queueIDs for every -//call does not sound ideal. -//In a first step, I'll circumvent the issue by not touching it, maybe in a second step. -//This also influences Interface design (getCommandQueue) and some other issues.. -typedef uint32_t MessageQueueId_t; class MessageQueueSenderIF { public: - static const MessageQueueId_t NO_QUEUE = 0; virtual ~MessageQueueSenderIF() {} /** - * Allows sending messages without actually "owing" a message queue. + * Allows sending messages without actually "owning" a message queue. * Not sure whether this is actually a good idea. - * Must be implemented by a subclass. */ static ReturnValue_t sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom = - MessageQueueSenderIF::NO_QUEUE, bool ignoreFault=false); + MessageQueueMessageIF* message, + MessageQueueId_t sentFrom = MessageQueueIF::NO_QUEUE, + bool ignoreFault = false); private: MessageQueueSenderIF() {} }; - #endif /* FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ */ diff --git a/ipc/messageQueueDefinitions.h b/ipc/messageQueueDefinitions.h new file mode 100644 index 00000000..d30e6984 --- /dev/null +++ b/ipc/messageQueueDefinitions.h @@ -0,0 +1,18 @@ +#ifndef FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ +#define FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ + +#include + +/* + * TODO: Actually, the definition of this ID to be a uint32_t is not ideal and + * breaks layering. However, it is difficult to keep layering, as the ID is + * stored in many places and sent around in MessageQueueMessage. + * Ideally, one would use the (current) object_id_t only, however, doing a + * lookup of queueIDs for every call does not sound ideal. + * In a first step, I'll circumvent the issue by not touching it, + * maybe in a second step. This also influences Interface design + * (getCommandQueue) and some other issues.. + */ +using MessageQueueId_t = uint32_t; + +#endif /* FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ */ From 21346e40a54e93a3753042fd4259ddc4154d9622 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 15 Sep 2020 16:58:38 +0200 Subject: [PATCH 334/653] some improvements --- action/ActionHelper.cpp | 1 + datalinklayer/MapPacketExtraction.cpp | 2 +- ipc/MessageQueueIF.h | 10 +++++----- ipc/MessageQueueMessage.h | 1 - ipc/MessageQueueSenderIF.h | 8 ++++---- ipc/messageQueueDefinitions.h | 1 + modes/ModeHelper.cpp | 8 ++++---- osal/FreeRTOS/MessageQueue.cpp | 4 +++- osal/FreeRTOS/QueueFactory.cpp | 7 +++++-- 9 files changed, 24 insertions(+), 18 deletions(-) diff --git a/action/ActionHelper.cpp b/action/ActionHelper.cpp index b43c676d..361f7dc3 100644 --- a/action/ActionHelper.cpp +++ b/action/ActionHelper.cpp @@ -1,5 +1,6 @@ #include "ActionHelper.h" #include "HasActionsIF.h" +#include "../ipc/MessageQueueSenderIF.h" #include "../objectmanager/ObjectManagerIF.h" ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue) : diff --git a/datalinklayer/MapPacketExtraction.cpp b/datalinklayer/MapPacketExtraction.cpp index cb12b321..d64348e1 100644 --- a/datalinklayer/MapPacketExtraction.cpp +++ b/datalinklayer/MapPacketExtraction.cpp @@ -18,7 +18,7 @@ MapPacketExtraction::MapPacketExtraction(uint8_t setMapId, object_id_t setPacketDestination) : lastSegmentationFlag(NO_SEGMENTATION), mapId(setMapId), packetLength(0), bufferPosition( packetBuffer), packetDestination(setPacketDestination), packetStore( - NULL), tcQueueId(MessageQueueSenderIF::NO_QUEUE) { + NULL), tcQueueId(MessageQueueIF::NO_QUEUE) { memset(packetBuffer, 0, sizeof(packetBuffer)); } diff --git a/ipc/MessageQueueIF.h b/ipc/MessageQueueIF.h index 9fff5287..b0347db9 100644 --- a/ipc/MessageQueueIF.h +++ b/ipc/MessageQueueIF.h @@ -1,15 +1,15 @@ -#ifndef FRAMEWORK_IPC_MESSAGEQUEUEIF_H_ -#define FRAMEWORK_IPC_MESSAGEQUEUEIF_H_ +#ifndef FSFW_IPC_MESSAGEQUEUEIF_H_ +#define FSFW_IPC_MESSAGEQUEUEIF_H_ // COULDDO: We could support blocking calls +#include "messageQueueDefinitions.h" #include "MessageQueueMessage.h" -#include "MessageQueueSenderIF.h" #include "../returnvalues/HasReturnvaluesIF.h" + class MessageQueueIF { public: - - static const MessageQueueId_t NO_QUEUE = MessageQueueSenderIF::NO_QUEUE; //!< Ugly hack. + static const MessageQueueId_t NO_QUEUE = 0; static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF; /** diff --git a/ipc/MessageQueueMessage.h b/ipc/MessageQueueMessage.h index f68e9b9f..5234f64f 100644 --- a/ipc/MessageQueueMessage.h +++ b/ipc/MessageQueueMessage.h @@ -2,7 +2,6 @@ #define FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ #include "../ipc/MessageQueueMessageIF.h" -#include "../ipc/MessageQueueSenderIF.h" #include /** diff --git a/ipc/MessageQueueSenderIF.h b/ipc/MessageQueueSenderIF.h index beb27f50..7eea5146 100644 --- a/ipc/MessageQueueSenderIF.h +++ b/ipc/MessageQueueSenderIF.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ -#define FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ +#ifndef FSFW_IPC_MESSAGEQUEUESENDERIF_H_ +#define FSFW_IPC_MESSAGEQUEUESENDERIF_H_ #include "../ipc/MessageQueueIF.h" #include "../ipc/MessageQueueMessageIF.h" @@ -15,7 +15,7 @@ public: * Not sure whether this is actually a good idea. */ static ReturnValue_t sendMessage(MessageQueueId_t sendTo, - MessageQueueMessageIF* message, + MessageQueueMessage* message, MessageQueueId_t sentFrom = MessageQueueIF::NO_QUEUE, bool ignoreFault = false); private: @@ -23,4 +23,4 @@ private: }; -#endif /* FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ */ +#endif /* FSFW_IPC_MESSAGEQUEUESENDERIF_H_ */ diff --git a/ipc/messageQueueDefinitions.h b/ipc/messageQueueDefinitions.h index d30e6984..60c09b05 100644 --- a/ipc/messageQueueDefinitions.h +++ b/ipc/messageQueueDefinitions.h @@ -15,4 +15,5 @@ */ using MessageQueueId_t = uint32_t; + #endif /* FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ */ diff --git a/modes/ModeHelper.cpp b/modes/ModeHelper.cpp index cb62c468..f464a743 100644 --- a/modes/ModeHelper.cpp +++ b/modes/ModeHelper.cpp @@ -36,7 +36,7 @@ ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* message) { commandedMode = mode; commandedSubmode = submode; - if ((parentQueueId != MessageQueueSenderIF::NO_QUEUE) + if ((parentQueueId != MessageQueueIF::NO_QUEUE) && (theOneWhoCommandedAMode != parentQueueId)) { owner->setToExternalControl(); } @@ -74,7 +74,7 @@ ReturnValue_t ModeHelper::initialize(MessageQueueId_t parentQueueId) { void ModeHelper::modeChanged(Mode_t mode, Submode_t submode) { forced = false; CommandMessage reply; - if (theOneWhoCommandedAMode != MessageQueueSenderIF::NO_QUEUE) { + if (theOneWhoCommandedAMode != MessageQueueIF::NO_QUEUE) { if ((mode != commandedMode) || (submode != commandedSubmode)) { ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_WRONG_MODE_REPLY, mode, submode); @@ -86,12 +86,12 @@ void ModeHelper::modeChanged(Mode_t mode, Submode_t submode) { owner->getCommandQueue()); } if (theOneWhoCommandedAMode != parentQueueId - && parentQueueId != MessageQueueSenderIF::NO_QUEUE) { + && parentQueueId != MessageQueueIF::NO_QUEUE) { ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_INFO, mode, submode); MessageQueueSenderIF::sendMessage(parentQueueId, &reply, owner->getCommandQueue()); } - theOneWhoCommandedAMode = MessageQueueSenderIF::NO_QUEUE; + theOneWhoCommandedAMode = MessageQueueIF::NO_QUEUE; } void ModeHelper::startTimer(uint32_t timeoutMs) { diff --git a/osal/FreeRTOS/MessageQueue.cpp b/osal/FreeRTOS/MessageQueue.cpp index 3bbd4d9d..6c8e1de9 100644 --- a/osal/FreeRTOS/MessageQueue.cpp +++ b/osal/FreeRTOS/MessageQueue.cpp @@ -1,5 +1,6 @@ #include "MessageQueue.h" +#include "../../objectmanager/ObjectManagerIF.h" #include "../../serviceinterface/ServiceInterfaceStream.h" // TODO I guess we should have a way of checking if we are in an ISR and then use the "fromISR" versions of all calls @@ -101,7 +102,8 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, reinterpret_cast(message->getBuffer()), 0); if (result != pdPASS) { if (!ignoreFault) { - InternalErrorReporterIF* internalErrorReporter = objectManager->get( + InternalErrorReporterIF* internalErrorReporter = + objectManager->get( objects::INTERNAL_ERROR_REPORTER); if (internalErrorReporter != NULL) { internalErrorReporter->queueMessageNotSent(); diff --git a/osal/FreeRTOS/QueueFactory.cpp b/osal/FreeRTOS/QueueFactory.cpp index e639179a..0de6ad4f 100644 --- a/osal/FreeRTOS/QueueFactory.cpp +++ b/osal/FreeRTOS/QueueFactory.cpp @@ -1,3 +1,4 @@ +#include "../../ipc/MessageQueueSenderIF.h" #include "../../ipc/QueueFactory.h" #include "MessageQueue.h" @@ -7,8 +8,10 @@ QueueFactory* QueueFactory::factoryInstance = NULL; ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom,bool ignoreFault) { - return MessageQueue::sendMessageFromMessageQueue(sendTo,message,sentFrom,ignoreFault); + MessageQueueMessage* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + return MessageQueue::sendMessageFromMessageQueue(sendTo, message, + sentFrom, ignoreFault); } QueueFactory* QueueFactory::instance() { From a5c6be9dd94cc213c752936634a991545a5ffa7e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 16 Sep 2020 19:05:25 +0200 Subject: [PATCH 335/653] added srv17 --- events/fwSubsystemIdRanges.h | 7 +++--- pus/Service17Test.cpp | 41 +++++++++++++++++++++++++++++++++ pus/Service17Test.h | 44 ++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 pus/Service17Test.cpp create mode 100644 pus/Service17Test.h diff --git a/events/fwSubsystemIdRanges.h b/events/fwSubsystemIdRanges.h index a05652c2..e21d16b8 100644 --- a/events/fwSubsystemIdRanges.h +++ b/events/fwSubsystemIdRanges.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_EVENTS_FWSUBSYSTEMIDRANGES_H_ -#define FRAMEWORK_EVENTS_FWSUBSYSTEMIDRANGES_H_ +#ifndef FSFW_EVENTS_FWSUBSYSTEMIDRANGES_H_ +#define FSFW_EVENTS_FWSUBSYSTEMIDRANGES_H_ namespace SUBSYSTEM_ID { enum { @@ -19,10 +19,11 @@ enum { SYSTEM_MANAGER_1 = 75, SYSTEM_1 = 79, PUS_SERVICE_1 = 80, + PUS_SERVICE_17 = 97, FW_SUBSYSTEM_ID_RANGE }; } -#endif /* FRAMEWORK_EVENTS_FWSUBSYSTEMIDRANGES_H_ */ +#endif /* FSFW_EVENTS_FWSUBSYSTEMIDRANGES_H_ */ diff --git a/pus/Service17Test.cpp b/pus/Service17Test.cpp new file mode 100644 index 00000000..2ef44490 --- /dev/null +++ b/pus/Service17Test.cpp @@ -0,0 +1,41 @@ +#include "Service17Test.h" + +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../objectmanager/SystemObject.h" +#include "../tmtcpacket/pus/TmPacketStored.h" + + +Service17Test::Service17Test(object_id_t objectId, + uint16_t apid, uint8_t serviceId): + PusServiceBase(objectId, apid, serviceId), + packetSubCounter(0) { +} + +Service17Test::~Service17Test() { +} + +ReturnValue_t Service17Test::handleRequest(uint8_t subservice) { + switch(subservice){ + case Subservice::CONNECTION_TEST: { + TmPacketStored connectionPacket(apid, serviceId, + Subservice::CONNECTION_TEST_REPORT, packetSubCounter++); + connectionPacket.sendPacket(requestQueue->getDefaultDestination(), + requestQueue->getId()); + return HasReturnvaluesIF::RETURN_OK; + } + case Subservice::EVENT_TRIGGER_TEST: { + TmPacketStored connectionPacket(apid, serviceId, + Subservice::CONNECTION_TEST_REPORT, packetSubCounter++); + connectionPacket.sendPacket(requestQueue->getDefaultDestination(), + requestQueue->getId()); + triggerEvent(TEST, 1234, 5678); + return RETURN_OK; + } + default: + return AcceptsTelecommandsIF::INVALID_SUBSERVICE; + } +} + +ReturnValue_t Service17Test::performService() { + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/pus/Service17Test.h b/pus/Service17Test.h new file mode 100644 index 00000000..e2681865 --- /dev/null +++ b/pus/Service17Test.h @@ -0,0 +1,44 @@ +#ifndef FSFW_PUS_SERVICE17TEST_H_ +#define FSFW_PUS_SERVICE17TEST_H_ + +#include "../tmtcservices/PusServiceBase.h" +#include "../objectmanager/SystemObject.h" + +/** + * @brief Test Service + * Full Documentation: ECSS-E70-41A p.167 + * + * The test service provides the capability to activate test functions + * implemented on-board and to report the results of such tests. + * Service capability: + * - TC[17,1]: Perform connection test + * - TM[17,2]: Send Connection Test Report + * - TC[17,128]: Perform connection test and trigger event + * + * @ingroup pus_services + */ +class Service17Test: public PusServiceBase { +public: + // Custom events which can be triggered + static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_17; + static constexpr Event TEST = MAKE_EVENT(0, SEVERITY::INFO); + + enum Subservice: uint8_t { + //! [EXPORT] : [COMMAND] Perform connection test + CONNECTION_TEST = 1, + //! [EXPORT] : [REPLY] Connection test reply + CONNECTION_TEST_REPORT = 2, + //! [EXPORT] : [COMMAND] Trigger test reply and test event + EVENT_TRIGGER_TEST = 128, + }; + + Service17Test(object_id_t objectId, uint16_t apid, uint8_t serviceId); + virtual ~Service17Test(); + virtual ReturnValue_t handleRequest(uint8_t subservice) override; + virtual ReturnValue_t performService() override; + +protected: + uint16_t packetSubCounter = 0; +}; + +#endif /* FSFW_PUS_SERVICE17TEST_H_ */ From ae426c50baf54d7c8f6b022da434dbc510fcef0c Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 16 Sep 2020 19:09:51 +0200 Subject: [PATCH 336/653] space replaced by tab --- events/fwSubsystemIdRanges.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/events/fwSubsystemIdRanges.h b/events/fwSubsystemIdRanges.h index e21d16b8..5e086f0e 100644 --- a/events/fwSubsystemIdRanges.h +++ b/events/fwSubsystemIdRanges.h @@ -19,7 +19,7 @@ enum { SYSTEM_MANAGER_1 = 75, SYSTEM_1 = 79, PUS_SERVICE_1 = 80, - PUS_SERVICE_17 = 97, + PUS_SERVICE_17 = 97, FW_SUBSYSTEM_ID_RANGE }; } From b31bee4fdac61bc103b62fb881b617b808840129 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 16 Sep 2020 19:11:50 +0200 Subject: [PATCH 337/653] added srv9 --- pus/Service9TimeManagement.cpp | 58 ++++++++++++++++++++++++++++ pus/Service9TimeManagement.h | 42 ++++++++++++++++++++ pus/servicepackets/Service9Packets.h | 32 +++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 pus/Service9TimeManagement.cpp create mode 100644 pus/Service9TimeManagement.h create mode 100644 pus/servicepackets/Service9Packets.h diff --git a/pus/Service9TimeManagement.cpp b/pus/Service9TimeManagement.cpp new file mode 100644 index 00000000..5625bdd8 --- /dev/null +++ b/pus/Service9TimeManagement.cpp @@ -0,0 +1,58 @@ +#include "Service9TimeManagement.h" +#include "servicepackets/Service9Packets.h" + +#include "../timemanager/CCSDSTime.h" +#include "../events/EventManagerIF.h" +#include "../serviceinterface/ServiceInterfaceStream.h" + + +Service9TimeManagement::Service9TimeManagement(object_id_t objectId, + uint16_t apid, uint8_t serviceId) : + PusServiceBase(objectId, apid , serviceId) { +} + +Service9TimeManagement::~Service9TimeManagement() {} + +ReturnValue_t Service9TimeManagement::performService() { + return RETURN_OK; +} + +ReturnValue_t Service9TimeManagement::handleRequest(uint8_t subservice) { + switch(subservice){ + case SUBSERVICE::SET_TIME:{ + return setTime(); + } + default: + return AcceptsTelecommandsIF::INVALID_SUBSERVICE; + } +} + +ReturnValue_t Service9TimeManagement::setTime() { + Clock::TimeOfDay_t timeToSet; + TimePacket timePacket(currentPacket.getApplicationData(), + currentPacket.getApplicationDataSize()); + ReturnValue_t result = CCSDSTime::convertFromCcsds(&timeToSet, + timePacket.getTime(), timePacket.getTimeSize()); + if(result != RETURN_OK) { + triggerEvent(CLOCK_SET_FAILURE, result, 0); + return result; + } + + uint32_t formerUptime; + Clock::getUptime(&formerUptime); + result = Clock::setClock(&timeToSet); + + if(result == RETURN_OK) { + uint32_t newUptime; + Clock::getUptime(&newUptime); + triggerEvent(CLOCK_SET,newUptime,formerUptime); + return RETURN_OK; + } + else { + triggerEvent(CLOCK_SET_FAILURE, result, 0); + return RETURN_FAILED; + } +} + + + diff --git a/pus/Service9TimeManagement.h b/pus/Service9TimeManagement.h new file mode 100644 index 00000000..4ad6be6e --- /dev/null +++ b/pus/Service9TimeManagement.h @@ -0,0 +1,42 @@ +#ifndef FSFW_PUS_SERVICE9TIMEMANAGEMENT_H_ +#define FSFW_PUS_SERVICE9TIMEMANAGEMENT_H_ + +#include + +class Service9TimeManagement: public PusServiceBase { +public: + + static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9; + static constexpr Event CLOCK_SET = MAKE_EVENT(0, SEVERITY::INFO); //!< Clock has been set. P1: New Uptime. P2: Old Uptime + static constexpr Event CLOCK_SET_FAILURE = MAKE_EVENT(1, SEVERITY::LOW); //!< Clock could not be set. P1: Returncode. + + static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9; + + /** + * @brief This service provides the capability to set the on-board time. + */ + Service9TimeManagement(object_id_t objectId, uint16_t apid, + uint8_t serviceId); + + virtual ~Service9TimeManagement(); + + virtual ReturnValue_t performService() override; + + /** + * @brief Sets the onboard-time by retrieving the time to set from TC[9,128]. + */ + virtual ReturnValue_t handleRequest(uint8_t subservice) override; + + virtual ReturnValue_t setTime(); +private: + + enum SUBSERVICE { + SET_TIME = 128 //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format + }; + + void setIsisClock(Clock::TimeOfDay_t& timeOfDay); +}; + + + +#endif /* FSFW_PUS_SERVICE9TIMEMANAGEMENT_H_ */ diff --git a/pus/servicepackets/Service9Packets.h b/pus/servicepackets/Service9Packets.h new file mode 100644 index 00000000..11bd2600 --- /dev/null +++ b/pus/servicepackets/Service9Packets.h @@ -0,0 +1,32 @@ +#ifndef FSFW_PUS_SERVICEPACKETS_SERVICE9PACKETS_H_ +#define FSFW_PUS_SERVICEPACKETS_SERVICE9PACKETS_H_ + +#include "../../serialize/SerialLinkedListAdapter.h" + +/** + * @brief Subservice 128 + * @details + * It only contains the time encoded as ASCII, CRC, CUC or CDS + * @ingroup spacepackets + */ +class TimePacket : SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 128 +public: + TimePacket(const uint8_t * timeBuffer_, uint32_t timeSize_) { + timeBuffer = timeBuffer_; + timeSize = timeSize_; + } + const uint8_t* getTime() { + return timeBuffer; + } + + uint32_t getTimeSize() const { + return timeSize; + } + +private: + TimePacket(const TimePacket &command); + const uint8_t * timeBuffer; + uint32_t timeSize; //!< [EXPORT] : [IGNORE] +}; + +#endif /* FSFW_PUS_SERVICEPACKETS_SERVICE9PACKETS_H_ */ From 85d6e81881f22037176c2f3e457bbd35733d9035 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 16 Sep 2020 19:17:00 +0200 Subject: [PATCH 338/653] added srv9 to class IDs --- returnvalues/FwClassIds.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/returnvalues/FwClassIds.h b/returnvalues/FwClassIds.h index 80df5741..e547025b 100644 --- a/returnvalues/FwClassIds.h +++ b/returnvalues/FwClassIds.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_RETURNVALUES_FWCLASSIDS_H_ -#define FRAMEWORK_RETURNVALUES_FWCLASSIDS_H_ +#ifndef FSFW_RETURNVALUES_FWCLASSIDS_H_ +#define FSFW_RETURNVALUES_FWCLASSIDS_H_ namespace CLASS_ID { enum { @@ -65,9 +65,10 @@ enum { POOL_VARIABLE_IF, //PVA 59 HOUSEKEEPING_MANAGER, //HKM 60 DLE_ENCODER, //DLEE 61 + PUS_SERVICE_9, //PUS9 62 FW_CLASS_ID_COUNT //is actually count + 1 ! }; } -#endif /* FRAMEWORK_RETURNVALUES_FWCLASSIDS_H_ */ +#endif /* FSFW_RETURNVALUES_FWCLASSIDS_H_ */ From 963015513f8e8825deaa95a7cabafd878d4811f4 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 16 Sep 2020 19:36:15 +0200 Subject: [PATCH 339/653] added time stamper to framework --- timemanager/TimeStamper.cpp | 23 +++++++++++++++++++++++ timemanager/TimeStamper.h | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 timemanager/TimeStamper.cpp create mode 100644 timemanager/TimeStamper.h diff --git a/timemanager/TimeStamper.cpp b/timemanager/TimeStamper.cpp new file mode 100644 index 00000000..07c3530c --- /dev/null +++ b/timemanager/TimeStamper.cpp @@ -0,0 +1,23 @@ +#include +#include +#include + +TimeStamper::TimeStamper(object_id_t objectId): SystemObject(objectId) {} + + +ReturnValue_t TimeStamper::addTimeStamp(uint8_t* buffer, + const uint8_t maxSize) { + if(maxSize < TimeStamperIF::MISSION_TIMESTAMP_SIZE){ + return HasReturnvaluesIF::RETURN_FAILED; + } + + timeval now; + Clock::getClock_timeval(&now); + CCSDSTime::CDS_short cds; + ReturnValue_t result = CCSDSTime::convertToCcsds(&cds,&now); + if(result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + memcpy(buffer,&cds,sizeof(cds)); + return result; +} diff --git a/timemanager/TimeStamper.h b/timemanager/TimeStamper.h new file mode 100644 index 00000000..80139c50 --- /dev/null +++ b/timemanager/TimeStamper.h @@ -0,0 +1,36 @@ +#ifndef FSFW_TIMEMANAGER_TIMESTAMPER_H_ +#define FSFW_TIMEMANAGER_TIMESTAMPER_H_ + +#include +#include +#include + +/** + * @brief Time stamper which can be used to add any timestamp to a + * given buffer. + * @details + * This time stamper uses the CCSDS CDC short timestamp as a fault timestamp. + * This timestamp has a size of 8 bytes. A custom timestamp can be used by + * overriding the #addTimeStamp function. + * @ingroup utility + */ +class TimeStamper: public TimeStamperIF, public SystemObject { +public: + /** + * @brief Default constructor which also registers the time stamper as a + * system object so it can be found with the #objectManager. + * @param objectId + */ + TimeStamper(object_id_t objectId); + + /** + * Adds a CCSDS CDC short 8 byte timestamp to the given buffer. + * This function can be overriden to use a custom timestamp. + * @param buffer + * @param maxSize + * @return + */ + virtual ReturnValue_t addTimeStamp(uint8_t* buffer, const uint8_t maxSize); +}; + +#endif /* FSFW_TIMEMANAGER_TIMESTAMPER_H_ */ From b0a816490e89c639e34849587eb4bc11d619b99f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 16 Sep 2020 19:37:17 +0200 Subject: [PATCH 340/653] fixed includes --- timemanager/TimeStamper.cpp | 6 +++--- timemanager/TimeStamper.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/timemanager/TimeStamper.cpp b/timemanager/TimeStamper.cpp index 07c3530c..d9f0f2f3 100644 --- a/timemanager/TimeStamper.cpp +++ b/timemanager/TimeStamper.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "TimeStamper.h" +#include "Clock.h" #include TimeStamper::TimeStamper(object_id_t objectId): SystemObject(objectId) {} @@ -18,6 +18,6 @@ ReturnValue_t TimeStamper::addTimeStamp(uint8_t* buffer, if(result != HasReturnvaluesIF::RETURN_OK){ return result; } - memcpy(buffer,&cds,sizeof(cds)); + std::memcpy(buffer,&cds,sizeof(cds)); return result; } diff --git a/timemanager/TimeStamper.h b/timemanager/TimeStamper.h index 80139c50..6895c14b 100644 --- a/timemanager/TimeStamper.h +++ b/timemanager/TimeStamper.h @@ -1,9 +1,9 @@ #ifndef FSFW_TIMEMANAGER_TIMESTAMPER_H_ #define FSFW_TIMEMANAGER_TIMESTAMPER_H_ -#include -#include -#include +#include "TimeStamperIF.h" +#include "CCSDSTime.h" +#include "../objectmanager/SystemObject.h" /** * @brief Time stamper which can be used to add any timestamp to a From 53723b0795f703cc1c2e004df37882d2a6da5424 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 16 Sep 2020 19:38:43 +0200 Subject: [PATCH 341/653] include fix --- pus/Service9TimeManagement.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pus/Service9TimeManagement.h b/pus/Service9TimeManagement.h index 4ad6be6e..9eed12ca 100644 --- a/pus/Service9TimeManagement.h +++ b/pus/Service9TimeManagement.h @@ -1,7 +1,7 @@ #ifndef FSFW_PUS_SERVICE9TIMEMANAGEMENT_H_ #define FSFW_PUS_SERVICE9TIMEMANAGEMENT_H_ -#include +#include "../tmtcservices/PusServiceBase.h" class Service9TimeManagement: public PusServiceBase { public: From 0f0ddfc37553fa2b922696ba373c2450d7cbb45d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 18 Sep 2020 12:27:40 +0200 Subject: [PATCH 342/653] stopwatch update --- osal/linux/Clock.cpp | 27 +++++++++------------------ timemanager/Clock.h | 3 +-- timemanager/Stopwatch.cpp | 15 +++++++++------ timemanager/Stopwatch.h | 13 ++++++------- 4 files changed, 25 insertions(+), 33 deletions(-) diff --git a/osal/linux/Clock.cpp b/osal/linux/Clock.cpp index 5f764a6f..b3b09923 100644 --- a/osal/linux/Clock.cpp +++ b/osal/linux/Clock.cpp @@ -75,24 +75,15 @@ timeval Clock::getUptime() { } ReturnValue_t Clock::getUptime(timeval* uptime) { - //TODO This is not posix compatible and delivers only seconds precision - struct sysinfo sysInfo; - int result = sysinfo(&sysInfo); - if(result != 0){ - return HasReturnvaluesIF::RETURN_FAILED; - } - uptime->tv_sec = sysInfo.uptime; - uptime->tv_usec = 0; - - - //Linux specific file read but more precise -// double uptimeSeconds; -// if(std::ifstream("/proc/uptime",std::ios::in) >> uptimeSeconds){ -// uptime->tv_sec = uptimeSeconds; -// uptime->tv_usec = uptimeSeconds *(double) 1e6 - (uptime->tv_sec *1e6); -// } - - return HasReturnvaluesIF::RETURN_OK; + //TODO This is not posix compatible and delivers only seconds precision + // is the OS not called Linux? + //Linux specific file read but more precise + double uptimeSeconds; + if(std::ifstream("/proc/uptime",std::ios::in) >> uptimeSeconds){ + uptime->tv_sec = uptimeSeconds; + uptime->tv_usec = uptimeSeconds *(double) 1e6 - (uptime->tv_sec *1e6); + } + return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) { diff --git a/timemanager/Clock.h b/timemanager/Clock.h index 6f6a97da..acb68e2e 100644 --- a/timemanager/Clock.h +++ b/timemanager/Clock.h @@ -9,8 +9,7 @@ #include //! Don't use these for time points, type is not large enough for UNIX epoch. -typedef uint32_t dur_millis_t; -typedef double dur_seconds_t; +using dur_millis_t = uint32_t; class Clock { public: diff --git a/timemanager/Stopwatch.cpp b/timemanager/Stopwatch.cpp index 00373bd7..2cd31969 100644 --- a/timemanager/Stopwatch.cpp +++ b/timemanager/Stopwatch.cpp @@ -1,4 +1,4 @@ -#include "Stopwatch.h" +#include "../timemanager/Stopwatch.h" #include "../serviceinterface/ServiceInterfaceStream.h" #include @@ -6,19 +6,22 @@ Stopwatch::Stopwatch(bool displayOnDestruction, StopwatchDisplayMode displayMode): displayOnDestruction( displayOnDestruction), displayMode(displayMode) { // Measures start time on initialization. - Clock::getClock_timeval(&startTime); + Clock::getUptime(&startTime); } void Stopwatch::start() { - Clock::getClock_timeval(&startTime); + Clock::getUptime(&startTime); } -dur_millis_t Stopwatch::stop() { +dur_millis_t Stopwatch::stop(bool display) { stopInternal(); + if(display) { + this->display(); + } return elapsedTime.tv_sec * 1000 + elapsedTime.tv_usec / 1000; } -dur_seconds_t Stopwatch::stopSeconds() { +double Stopwatch::stopSeconds() { stopInternal(); return timevalOperations::toDouble(elapsedTime); } @@ -52,6 +55,6 @@ StopwatchDisplayMode Stopwatch::getDisplayMode() const { void Stopwatch::stopInternal() { timeval endTime; - Clock::getClock_timeval(&endTime); + Clock::getUptime(&endTime); elapsedTime = endTime - startTime; } diff --git a/timemanager/Stopwatch.h b/timemanager/Stopwatch.h index f216b7e1..ea72c66e 100644 --- a/timemanager/Stopwatch.h +++ b/timemanager/Stopwatch.h @@ -1,5 +1,6 @@ -#ifndef FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ -#define FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ +#ifndef FSFW_TIMEMANAGER_STOPWATCH_H_ +#define FSFW_TIMEMANAGER_STOPWATCH_H_ + #include "Clock.h" enum class StopwatchDisplayMode { @@ -40,12 +41,12 @@ public: * Calculates the elapsed time since start and returns it * @return elapsed time in milliseconds (rounded) */ - dur_millis_t stop(); + dur_millis_t stop(bool display = false); /** * Calculates the elapsed time since start and returns it * @return elapsed time in seconds (double precision) */ - dur_seconds_t stopSeconds(); + double stopSeconds(); /** * Displays the elapsed times on the osstream, depending on internal display @@ -66,6 +67,4 @@ private: }; - - -#endif /* FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ */ +#endif /* FSFW_TIMEMANAGER_STOPWATCH_H_ */ From ad8c6f3528a27dcc1153264e9e1fb7fd8d687c04 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 18 Sep 2020 12:58:38 +0200 Subject: [PATCH 343/653] commented out code added back --- osal/linux/Clock.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osal/linux/Clock.cpp b/osal/linux/Clock.cpp index b3b09923..b14f2a97 100644 --- a/osal/linux/Clock.cpp +++ b/osal/linux/Clock.cpp @@ -83,6 +83,16 @@ ReturnValue_t Clock::getUptime(timeval* uptime) { uptime->tv_sec = uptimeSeconds; uptime->tv_usec = uptimeSeconds *(double) 1e6 - (uptime->tv_sec *1e6); } + + //TODO This is not posix compatible and delivers only seconds precision + // I suggest this is moved into another clock function which will + // deliver second precision later. +// struct sysinfo sysInfo; +// int result = sysinfo(&sysInfo); +// if(result != 0){ +// return HasReturnvaluesIF::RETURN_FAILED; +// } +// return sysInfo.uptime; return HasReturnvaluesIF::RETURN_OK; } From 56ff2aef26209d7c5db76ab2794df4517b0ca35d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 18 Sep 2020 13:03:48 +0200 Subject: [PATCH 344/653] include replacement --- timemanager/Stopwatch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/timemanager/Stopwatch.cpp b/timemanager/Stopwatch.cpp index 2cd31969..302e2ac0 100644 --- a/timemanager/Stopwatch.cpp +++ b/timemanager/Stopwatch.cpp @@ -1,4 +1,4 @@ -#include "../timemanager/Stopwatch.h" +#include "Stopwatch.h" #include "../serviceinterface/ServiceInterfaceStream.h" #include From 386f3475741bd07af46a313b78dd77882a697f76 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 18 Sep 2020 13:15:14 +0200 Subject: [PATCH 345/653] renormalized files --- contrib/sgp4/sgp4unit.cpp | 4180 ++++++++++----------- contrib/sgp4/sgp4unit.h | 234 +- globalfunctions/timevalOperations.cpp | 198 +- osal/FreeRTOS/BinSemaphUsingTask.cpp | 190 +- osal/FreeRTOS/BinSemaphUsingTask.h | 152 +- osal/FreeRTOS/BinarySemaphore.cpp | 216 +- osal/FreeRTOS/BinarySemaphore.h | 214 +- osal/FreeRTOS/CountingSemaphUsingTask.cpp | 228 +- osal/FreeRTOS/CountingSemaphUsingTask.h | 204 +- osal/FreeRTOS/CountingSemaphore.cpp | 86 +- osal/FreeRTOS/CountingSemaphore.h | 68 +- osal/FreeRTOS/SemaphoreFactory.cpp | 118 +- osal/FreeRTOS/TaskManagement.cpp | 48 +- osal/FreeRTOS/TaskManagement.h | 128 +- osal/linux/BinarySemaphore.cpp | 298 +- osal/linux/BinarySemaphore.h | 162 +- osal/linux/CountingSemaphore.cpp | 108 +- osal/linux/CountingSemaphore.h | 74 +- osal/linux/SemaphoreFactory.cpp | 66 +- serialize/SerialBufferAdapter.cpp | 258 +- serialize/SerialBufferAdapter.h | 156 +- tasks/SemaphoreFactory.h | 100 +- tasks/SemaphoreIF.h | 136 +- 23 files changed, 3811 insertions(+), 3811 deletions(-) diff --git a/contrib/sgp4/sgp4unit.cpp b/contrib/sgp4/sgp4unit.cpp index 24d63aa9..b707a7a2 100644 --- a/contrib/sgp4/sgp4unit.cpp +++ b/contrib/sgp4/sgp4unit.cpp @@ -1,2090 +1,2090 @@ -/* ---------------------------------------------------------------- -* -* sgp4unit.cpp -* -* this file contains the sgp4 procedures for analytical propagation -* of a satellite. the code was originally released in the 1980 and 1986 -* spacetrack papers. a detailed discussion of the theory and history -* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, -* and kelso. -* -* companion code for -* fundamentals of astrodynamics and applications -* 2007 -* by david vallado -* -* (w) 719-573-2600, email dvallado@agi.com -* -* current : -* 16 nov 07 david vallado -* misc fixes for better compliance -* changes : -* 20 apr 07 david vallado -* misc fixes for constants -* 11 aug 06 david vallado -* chg lyddane choice back to strn3, constants, misc doc -* 15 dec 05 david vallado -* misc fixes -* 26 jul 05 david vallado -* fixes for paper -* note that each fix is preceded by a -* comment with "sgp4fix" and an explanation of -* what was changed -* 10 aug 04 david vallado -* 2nd printing baseline working -* 14 may 01 david vallado -* 2nd edition baseline -* 80 norad -* original baseline -* ---------------------------------------------------------------- */ - -#include "sgp4unit.h" - -const char help = 'n'; -FILE *dbgfile; - -#define pi 3.14159265358979323846 - - -/* ----------- local functions - only ever used internally by sgp4 ---------- */ -static void dpper - ( - double e3, double ee2, double peo, double pgho, double pho, - double pinco, double plo, double se2, double se3, double sgh2, - double sgh3, double sgh4, double sh2, double sh3, double si2, - double si3, double sl2, double sl3, double sl4, double t, - double xgh2, double xgh3, double xgh4, double xh2, double xh3, - double xi2, double xi3, double xl2, double xl3, double xl4, - double zmol, double zmos, double inclo, - char init, - double& ep, double& inclp, double& nodep, double& argpp, double& mp - ); - -static void dscom - ( - double epoch, double ep, double argpp, double tc, double inclp, - double nodep, double np, - double& snodm, double& cnodm, double& sinim, double& cosim, double& sinomm, - double& cosomm,double& day, double& e3, double& ee2, double& em, - double& emsq, double& gam, double& peo, double& pgho, double& pho, - double& pinco, double& plo, double& rtemsq, double& se2, double& se3, - double& sgh2, double& sgh3, double& sgh4, double& sh2, double& sh3, - double& si2, double& si3, double& sl2, double& sl3, double& sl4, - double& s1, double& s2, double& s3, double& s4, double& s5, - double& s6, double& s7, double& ss1, double& ss2, double& ss3, - double& ss4, double& ss5, double& ss6, double& ss7, double& sz1, - double& sz2, double& sz3, double& sz11, double& sz12, double& sz13, - double& sz21, double& sz22, double& sz23, double& sz31, double& sz32, - double& sz33, double& xgh2, double& xgh3, double& xgh4, double& xh2, - double& xh3, double& xi2, double& xi3, double& xl2, double& xl3, - double& xl4, double& nm, double& z1, double& z2, double& z3, - double& z11, double& z12, double& z13, double& z21, double& z22, - double& z23, double& z31, double& z32, double& z33, double& zmol, - double& zmos - ); - -static void dsinit - ( - gravconsttype whichconst, - double cosim, double emsq, double argpo, double s1, double s2, - double s3, double s4, double s5, double sinim, double ss1, - double ss2, double ss3, double ss4, double ss5, double sz1, - double sz3, double sz11, double sz13, double sz21, double sz23, - double sz31, double sz33, double t, double tc, double gsto, - double mo, double mdot, double no, double nodeo, double nodedot, - double xpidot, double z1, double z3, double z11, double z13, - double z21, double z23, double z31, double z33, double ecco, - double eccsq, double& em, double& argpm, double& inclm, double& mm, - double& nm, double& nodem, - int& irez, - double& atime, double& d2201, double& d2211, double& d3210, double& d3222, - double& d4410, double& d4422, double& d5220, double& d5232, double& d5421, - double& d5433, double& dedt, double& didt, double& dmdt, double& dndt, - double& dnodt, double& domdt, double& del1, double& del2, double& del3, - double& xfact, double& xlamo, double& xli, double& xni - ); - -static void dspace - ( - int irez, - double d2201, double d2211, double d3210, double d3222, double d4410, - double d4422, double d5220, double d5232, double d5421, double d5433, - double dedt, double del1, double del2, double del3, double didt, - double dmdt, double dnodt, double domdt, double argpo, double argpdot, - double t, double tc, double gsto, double xfact, double xlamo, - double no, - double& atime, double& em, double& argpm, double& inclm, double& xli, - double& mm, double& xni, double& nodem, double& dndt, double& nm - ); - -static void initl - ( - int satn, gravconsttype whichconst, - double ecco, double epoch, double inclo, double& no, - char& method, - double& ainv, double& ao, double& con41, double& con42, double& cosio, - double& cosio2,double& eccsq, double& omeosq, double& posq, - double& rp, double& rteosq,double& sinio , double& gsto - ); - -/* ----------------------------------------------------------------------------- -* -* procedure dpper -* -* this procedure provides deep space long period periodic contributions -* to the mean elements. by design, these periodics are zero at epoch. -* this used to be dscom which included initialization, but it's really a -* recurring function. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* e3 - -* ee2 - -* peo - -* pgho - -* pho - -* pinco - -* plo - -* se2 , se3 , sgh2, sgh3, sgh4, sh2, sh3, si2, si3, sl2, sl3, sl4 - -* t - -* xh2, xh3, xi2, xi3, xl2, xl3, xl4 - -* zmol - -* zmos - -* ep - eccentricity 0.0 - 1.0 -* inclo - inclination - needed for lyddane modification -* nodep - right ascension of ascending node -* argpp - argument of perigee -* mp - mean anomaly -* -* outputs : -* ep - eccentricity 0.0 - 1.0 -* inclp - inclination -* nodep - right ascension of ascending node -* argpp - argument of perigee -* mp - mean anomaly -* -* locals : -* alfdp - -* betdp - -* cosip , sinip , cosop , sinop , -* dalf - -* dbet - -* dls - -* f2, f3 - -* pe - -* pgh - -* ph - -* pinc - -* pl - -* sel , ses , sghl , sghs , shl , shs , sil , sinzf , sis , -* sll , sls -* xls - -* xnoh - -* zf - -* zm - -* -* coupling : -* none. -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void dpper - ( - double e3, double ee2, double peo, double pgho, double pho, - double pinco, double plo, double se2, double se3, double sgh2, - double sgh3, double sgh4, double sh2, double sh3, double si2, - double si3, double sl2, double sl3, double sl4, double t, - double xgh2, double xgh3, double xgh4, double xh2, double xh3, - double xi2, double xi3, double xl2, double xl3, double xl4, - double zmol, double zmos, double inclo, - char init, - double& ep, double& inclp, double& nodep, double& argpp, double& mp - ) -{ - /* --------------------- local variables ------------------------ */ - const double twopi = 2.0 * pi; - double alfdp, betdp, cosip, cosop, dalf, dbet, dls, - f2, f3, pe, pgh, ph, pinc, pl , - sel, ses, sghl, sghs, shll, shs, sil, - sinip, sinop, sinzf, sis, sll, sls, xls, - xnoh, zf, zm, zel, zes, znl, zns; - - /* ---------------------- constants ----------------------------- */ - zns = 1.19459e-5; - zes = 0.01675; - znl = 1.5835218e-4; - zel = 0.05490; - - /* --------------- calculate time varying periodics ----------- */ - zm = zmos + zns * t; - // be sure that the initial call has time set to zero - if (init == 'y') - zm = zmos; - zf = zm + 2.0 * zes * sin(zm); - sinzf = sin(zf); - f2 = 0.5 * sinzf * sinzf - 0.25; - f3 = -0.5 * sinzf * cos(zf); - ses = se2* f2 + se3 * f3; - sis = si2 * f2 + si3 * f3; - sls = sl2 * f2 + sl3 * f3 + sl4 * sinzf; - sghs = sgh2 * f2 + sgh3 * f3 + sgh4 * sinzf; - shs = sh2 * f2 + sh3 * f3; - zm = zmol + znl * t; - if (init == 'y') - zm = zmol; - zf = zm + 2.0 * zel * sin(zm); - sinzf = sin(zf); - f2 = 0.5 * sinzf * sinzf - 0.25; - f3 = -0.5 * sinzf * cos(zf); - sel = ee2 * f2 + e3 * f3; - sil = xi2 * f2 + xi3 * f3; - sll = xl2 * f2 + xl3 * f3 + xl4 * sinzf; - sghl = xgh2 * f2 + xgh3 * f3 + xgh4 * sinzf; - shll = xh2 * f2 + xh3 * f3; - pe = ses + sel; - pinc = sis + sil; - pl = sls + sll; - pgh = sghs + sghl; - ph = shs + shll; - - if (init == 'n') - { - pe = pe - peo; - pinc = pinc - pinco; - pl = pl - plo; - pgh = pgh - pgho; - ph = ph - pho; - inclp = inclp + pinc; - ep = ep + pe; - sinip = sin(inclp); - cosip = cos(inclp); - - /* ----------------- apply periodics directly ------------ */ - // sgp4fix for lyddane choice - // strn3 used original inclination - this is technically feasible - // gsfc used perturbed inclination - also technically feasible - // probably best to readjust the 0.2 limit value and limit discontinuity - // 0.2 rad = 11.45916 deg - // use next line for original strn3 approach and original inclination - // if (inclo >= 0.2) - // use next line for gsfc version and perturbed inclination - if (inclp >= 0.2) - { - ph = ph / sinip; - pgh = pgh - cosip * ph; - argpp = argpp + pgh; - nodep = nodep + ph; - mp = mp + pl; - } - else - { - /* ---- apply periodics with lyddane modification ---- */ - sinop = sin(nodep); - cosop = cos(nodep); - alfdp = sinip * sinop; - betdp = sinip * cosop; - dalf = ph * cosop + pinc * cosip * sinop; - dbet = -ph * sinop + pinc * cosip * cosop; - alfdp = alfdp + dalf; - betdp = betdp + dbet; - nodep = fmod(nodep, twopi); - // sgp4fix for afspc written intrinsic functions - // nodep used without a trigonometric function ahead - if (nodep < 0.0) - nodep = nodep + twopi; - xls = mp + argpp + cosip * nodep; - dls = pl + pgh - pinc * nodep * sinip; - xls = xls + dls; - xnoh = nodep; - nodep = atan2(alfdp, betdp); - // sgp4fix for afspc written intrinsic functions - // nodep used without a trigonometric function ahead - if (nodep < 0.0) - nodep = nodep + twopi; - if (fabs(xnoh - nodep) > pi){ - if (nodep < xnoh) - nodep = nodep + twopi; - else - nodep = nodep - twopi; - } - mp = mp + pl; - argpp = xls - mp - cosip * nodep; - } - } // if init == 'n' - -//#include "debug1.cpp" -} // end dpper - -/*----------------------------------------------------------------------------- -* -* procedure dscom -* -* this procedure provides deep space common items used by both the secular -* and periodics subroutines. input is provided as shown. this routine -* used to be called dpper, but the functions inside weren't well organized. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* epoch - -* ep - eccentricity -* argpp - argument of perigee -* tc - -* inclp - inclination -* nodep - right ascension of ascending node -* np - mean motion -* -* outputs : -* sinim , cosim , sinomm , cosomm , snodm , cnodm -* day - -* e3 - -* ee2 - -* em - eccentricity -* emsq - eccentricity squared -* gam - -* peo - -* pgho - -* pho - -* pinco - -* plo - -* rtemsq - -* se2, se3 - -* sgh2, sgh3, sgh4 - -* sh2, sh3, si2, si3, sl2, sl3, sl4 - -* s1, s2, s3, s4, s5, s6, s7 - -* ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3 - -* sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33 - -* xgh2, xgh3, xgh4, xh2, xh3, xi2, xi3, xl2, xl3, xl4 - -* nm - mean motion -* z1, z2, z3, z11, z12, z13, z21, z22, z23, z31, z32, z33 - -* zmol - -* zmos - -* -* locals : -* a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 - -* betasq - -* cc - -* ctem, stem - -* x1, x2, x3, x4, x5, x6, x7, x8 - -* xnodce - -* xnoi - -* zcosg , zsing , zcosgl , zsingl , zcosh , zsinh , zcoshl , zsinhl , -* zcosi , zsini , zcosil , zsinil , -* zx - -* zy - -* -* coupling : -* none. -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void dscom - ( - double epoch, double ep, double argpp, double tc, double inclp, - double nodep, double np, - double& snodm, double& cnodm, double& sinim, double& cosim, double& sinomm, - double& cosomm,double& day, double& e3, double& ee2, double& em, - double& emsq, double& gam, double& peo, double& pgho, double& pho, - double& pinco, double& plo, double& rtemsq, double& se2, double& se3, - double& sgh2, double& sgh3, double& sgh4, double& sh2, double& sh3, - double& si2, double& si3, double& sl2, double& sl3, double& sl4, - double& s1, double& s2, double& s3, double& s4, double& s5, - double& s6, double& s7, double& ss1, double& ss2, double& ss3, - double& ss4, double& ss5, double& ss6, double& ss7, double& sz1, - double& sz2, double& sz3, double& sz11, double& sz12, double& sz13, - double& sz21, double& sz22, double& sz23, double& sz31, double& sz32, - double& sz33, double& xgh2, double& xgh3, double& xgh4, double& xh2, - double& xh3, double& xi2, double& xi3, double& xl2, double& xl3, - double& xl4, double& nm, double& z1, double& z2, double& z3, - double& z11, double& z12, double& z13, double& z21, double& z22, - double& z23, double& z31, double& z32, double& z33, double& zmol, - double& zmos - ) -{ - /* -------------------------- constants ------------------------- */ - const double zes = 0.01675; - const double zel = 0.05490; - const double c1ss = 2.9864797e-6; - const double c1l = 4.7968065e-7; - const double zsinis = 0.39785416; - const double zcosis = 0.91744867; - const double zcosgs = 0.1945905; - const double zsings = -0.98088458; - const double twopi = 2.0 * pi; - - /* --------------------- local variables ------------------------ */ - int lsflg; - double a1 , a2 , a3 , a4 , a5 , a6 , a7 , - a8 , a9 , a10 , betasq, cc , ctem , stem , - x1 , x2 , x3 , x4 , x5 , x6 , x7 , - x8 , xnodce, xnoi , zcosg , zcosgl, zcosh , zcoshl, - zcosi , zcosil, zsing , zsingl, zsinh , zsinhl, zsini , - zsinil, zx , zy; - - nm = np; - em = ep; - snodm = sin(nodep); - cnodm = cos(nodep); - sinomm = sin(argpp); - cosomm = cos(argpp); - sinim = sin(inclp); - cosim = cos(inclp); - emsq = em * em; - betasq = 1.0 - emsq; - rtemsq = sqrt(betasq); - - /* ----------------- initialize lunar solar terms --------------- */ - peo = 0.0; - pinco = 0.0; - plo = 0.0; - pgho = 0.0; - pho = 0.0; - day = epoch + 18261.5 + tc / 1440.0; - xnodce = fmod(4.5236020 - 9.2422029e-4 * day, twopi); - stem = sin(xnodce); - ctem = cos(xnodce); - zcosil = 0.91375164 - 0.03568096 * ctem; - zsinil = sqrt(1.0 - zcosil * zcosil); - zsinhl = 0.089683511 * stem / zsinil; - zcoshl = sqrt(1.0 - zsinhl * zsinhl); - gam = 5.8351514 + 0.0019443680 * day; - zx = 0.39785416 * stem / zsinil; - zy = zcoshl * ctem + 0.91744867 * zsinhl * stem; - zx = atan2(zx, zy); - zx = gam + zx - xnodce; - zcosgl = cos(zx); - zsingl = sin(zx); - - /* ------------------------- do solar terms --------------------- */ - zcosg = zcosgs; - zsing = zsings; - zcosi = zcosis; - zsini = zsinis; - zcosh = cnodm; - zsinh = snodm; - cc = c1ss; - xnoi = 1.0 / nm; - - for (lsflg = 1; lsflg <= 2; lsflg++) - { - a1 = zcosg * zcosh + zsing * zcosi * zsinh; - a3 = -zsing * zcosh + zcosg * zcosi * zsinh; - a7 = -zcosg * zsinh + zsing * zcosi * zcosh; - a8 = zsing * zsini; - a9 = zsing * zsinh + zcosg * zcosi * zcosh; - a10 = zcosg * zsini; - a2 = cosim * a7 + sinim * a8; - a4 = cosim * a9 + sinim * a10; - a5 = -sinim * a7 + cosim * a8; - a6 = -sinim * a9 + cosim * a10; - - x1 = a1 * cosomm + a2 * sinomm; - x2 = a3 * cosomm + a4 * sinomm; - x3 = -a1 * sinomm + a2 * cosomm; - x4 = -a3 * sinomm + a4 * cosomm; - x5 = a5 * sinomm; - x6 = a6 * sinomm; - x7 = a5 * cosomm; - x8 = a6 * cosomm; - - z31 = 12.0 * x1 * x1 - 3.0 * x3 * x3; - z32 = 24.0 * x1 * x2 - 6.0 * x3 * x4; - z33 = 12.0 * x2 * x2 - 3.0 * x4 * x4; - z1 = 3.0 * (a1 * a1 + a2 * a2) + z31 * emsq; - z2 = 6.0 * (a1 * a3 + a2 * a4) + z32 * emsq; - z3 = 3.0 * (a3 * a3 + a4 * a4) + z33 * emsq; - z11 = -6.0 * a1 * a5 + emsq * (-24.0 * x1 * x7-6.0 * x3 * x5); - z12 = -6.0 * (a1 * a6 + a3 * a5) + emsq * - (-24.0 * (x2 * x7 + x1 * x8) - 6.0 * (x3 * x6 + x4 * x5)); - z13 = -6.0 * a3 * a6 + emsq * (-24.0 * x2 * x8 - 6.0 * x4 * x6); - z21 = 6.0 * a2 * a5 + emsq * (24.0 * x1 * x5 - 6.0 * x3 * x7); - z22 = 6.0 * (a4 * a5 + a2 * a6) + emsq * - (24.0 * (x2 * x5 + x1 * x6) - 6.0 * (x4 * x7 + x3 * x8)); - z23 = 6.0 * a4 * a6 + emsq * (24.0 * x2 * x6 - 6.0 * x4 * x8); - z1 = z1 + z1 + betasq * z31; - z2 = z2 + z2 + betasq * z32; - z3 = z3 + z3 + betasq * z33; - s3 = cc * xnoi; - s2 = -0.5 * s3 / rtemsq; - s4 = s3 * rtemsq; - s1 = -15.0 * em * s4; - s5 = x1 * x3 + x2 * x4; - s6 = x2 * x3 + x1 * x4; - s7 = x2 * x4 - x1 * x3; - - /* ----------------------- do lunar terms ------------------- */ - if (lsflg == 1) - { - ss1 = s1; - ss2 = s2; - ss3 = s3; - ss4 = s4; - ss5 = s5; - ss6 = s6; - ss7 = s7; - sz1 = z1; - sz2 = z2; - sz3 = z3; - sz11 = z11; - sz12 = z12; - sz13 = z13; - sz21 = z21; - sz22 = z22; - sz23 = z23; - sz31 = z31; - sz32 = z32; - sz33 = z33; - zcosg = zcosgl; - zsing = zsingl; - zcosi = zcosil; - zsini = zsinil; - zcosh = zcoshl * cnodm + zsinhl * snodm; - zsinh = snodm * zcoshl - cnodm * zsinhl; - cc = c1l; - } - } - - zmol = fmod(4.7199672 + 0.22997150 * day - gam, twopi); - zmos = fmod(6.2565837 + 0.017201977 * day, twopi); - - /* ------------------------ do solar terms ---------------------- */ - se2 = 2.0 * ss1 * ss6; - se3 = 2.0 * ss1 * ss7; - si2 = 2.0 * ss2 * sz12; - si3 = 2.0 * ss2 * (sz13 - sz11); - sl2 = -2.0 * ss3 * sz2; - sl3 = -2.0 * ss3 * (sz3 - sz1); - sl4 = -2.0 * ss3 * (-21.0 - 9.0 * emsq) * zes; - sgh2 = 2.0 * ss4 * sz32; - sgh3 = 2.0 * ss4 * (sz33 - sz31); - sgh4 = -18.0 * ss4 * zes; - sh2 = -2.0 * ss2 * sz22; - sh3 = -2.0 * ss2 * (sz23 - sz21); - - /* ------------------------ do lunar terms ---------------------- */ - ee2 = 2.0 * s1 * s6; - e3 = 2.0 * s1 * s7; - xi2 = 2.0 * s2 * z12; - xi3 = 2.0 * s2 * (z13 - z11); - xl2 = -2.0 * s3 * z2; - xl3 = -2.0 * s3 * (z3 - z1); - xl4 = -2.0 * s3 * (-21.0 - 9.0 * emsq) * zel; - xgh2 = 2.0 * s4 * z32; - xgh3 = 2.0 * s4 * (z33 - z31); - xgh4 = -18.0 * s4 * zel; - xh2 = -2.0 * s2 * z22; - xh3 = -2.0 * s2 * (z23 - z21); - -//#include "debug2.cpp" -} // end dscom - -/*----------------------------------------------------------------------------- -* -* procedure dsinit -* -* this procedure provides deep space contributions to mean motion dot due -* to geopotential resonance with half day and one day orbits. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* cosim, sinim- -* emsq - eccentricity squared -* argpo - argument of perigee -* s1, s2, s3, s4, s5 - -* ss1, ss2, ss3, ss4, ss5 - -* sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33 - -* t - time -* tc - -* gsto - greenwich sidereal time rad -* mo - mean anomaly -* mdot - mean anomaly dot (rate) -* no - mean motion -* nodeo - right ascension of ascending node -* nodedot - right ascension of ascending node dot (rate) -* xpidot - -* z1, z3, z11, z13, z21, z23, z31, z33 - -* eccm - eccentricity -* argpm - argument of perigee -* inclm - inclination -* mm - mean anomaly -* xn - mean motion -* nodem - right ascension of ascending node -* -* outputs : -* em - eccentricity -* argpm - argument of perigee -* inclm - inclination -* mm - mean anomaly -* nm - mean motion -* nodem - right ascension of ascending node -* irez - flag for resonance 0-none, 1-one day, 2-half day -* atime - -* d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 - -* dedt - -* didt - -* dmdt - -* dndt - -* dnodt - -* domdt - -* del1, del2, del3 - -* ses , sghl , sghs , sgs , shl , shs , sis , sls -* theta - -* xfact - -* xlamo - -* xli - -* xni -* -* locals : -* ainv2 - -* aonv - -* cosisq - -* eoc - -* f220, f221, f311, f321, f322, f330, f441, f442, f522, f523, f542, f543 - -* g200, g201, g211, g300, g310, g322, g410, g422, g520, g521, g532, g533 - -* sini2 - -* temp - -* temp1 - -* theta - -* xno2 - -* -* coupling : -* getgravconst -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void dsinit - ( - gravconsttype whichconst, - double cosim, double emsq, double argpo, double s1, double s2, - double s3, double s4, double s5, double sinim, double ss1, - double ss2, double ss3, double ss4, double ss5, double sz1, - double sz3, double sz11, double sz13, double sz21, double sz23, - double sz31, double sz33, double t, double tc, double gsto, - double mo, double mdot, double no, double nodeo, double nodedot, - double xpidot, double z1, double z3, double z11, double z13, - double z21, double z23, double z31, double z33, double ecco, - double eccsq, double& em, double& argpm, double& inclm, double& mm, - double& nm, double& nodem, - int& irez, - double& atime, double& d2201, double& d2211, double& d3210, double& d3222, - double& d4410, double& d4422, double& d5220, double& d5232, double& d5421, - double& d5433, double& dedt, double& didt, double& dmdt, double& dndt, - double& dnodt, double& domdt, double& del1, double& del2, double& del3, - double& xfact, double& xlamo, double& xli, double& xni - ) -{ - /* --------------------- local variables ------------------------ */ - const double twopi = 2.0 * pi; - - double ainv2 , aonv=0.0, cosisq, eoc, f220 , f221 , f311 , - f321 , f322 , f330 , f441 , f442 , f522 , f523 , - f542 , f543 , g200 , g201 , g211 , g300 , g310 , - g322 , g410 , g422 , g520 , g521 , g532 , g533 , - ses , sgs , sghl , sghs , shs , shll , sis , - sini2 , sls , temp , temp1 , theta , xno2 , q22 , - q31 , q33 , root22, root44, root54, rptim , root32, - root52, x2o3 , xke , znl , emo , zns , emsqo, - tumin, mu, radiusearthkm, j2, j3, j4, j3oj2; - - q22 = 1.7891679e-6; - q31 = 2.1460748e-6; - q33 = 2.2123015e-7; - root22 = 1.7891679e-6; - root44 = 7.3636953e-9; - root54 = 2.1765803e-9; - rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec - root32 = 3.7393792e-7; - root52 = 1.1428639e-7; - x2o3 = 2.0 / 3.0; - znl = 1.5835218e-4; - zns = 1.19459e-5; - - // sgp4fix identify constants and allow alternate values - getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); - - /* -------------------- deep space initialization ------------ */ - irez = 0; - if ((nm < 0.0052359877) && (nm > 0.0034906585)) - irez = 1; - if ((nm >= 8.26e-3) && (nm <= 9.24e-3) && (em >= 0.5)) - irez = 2; - - /* ------------------------ do solar terms ------------------- */ - ses = ss1 * zns * ss5; - sis = ss2 * zns * (sz11 + sz13); - sls = -zns * ss3 * (sz1 + sz3 - 14.0 - 6.0 * emsq); - sghs = ss4 * zns * (sz31 + sz33 - 6.0); - shs = -zns * ss2 * (sz21 + sz23); - // sgp4fix for 180 deg incl - if ((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2)) - shs = 0.0; - if (sinim != 0.0) - shs = shs / sinim; - sgs = sghs - cosim * shs; - - /* ------------------------- do lunar terms ------------------ */ - dedt = ses + s1 * znl * s5; - didt = sis + s2 * znl * (z11 + z13); - dmdt = sls - znl * s3 * (z1 + z3 - 14.0 - 6.0 * emsq); - sghl = s4 * znl * (z31 + z33 - 6.0); - shll = -znl * s2 * (z21 + z23); - // sgp4fix for 180 deg incl - if ((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2)) - shll = 0.0; - domdt = sgs + sghl; - dnodt = shs; - if (sinim != 0.0) - { - domdt = domdt - cosim / sinim * shll; - dnodt = dnodt + shll / sinim; - } - - /* ----------- calculate deep space resonance effects -------- */ - dndt = 0.0; - theta = fmod(gsto + tc * rptim, twopi); - em = em + dedt * t; - inclm = inclm + didt * t; - argpm = argpm + domdt * t; - nodem = nodem + dnodt * t; - mm = mm + dmdt * t; - // sgp4fix for negative inclinations - // the following if statement should be commented out - //if (inclm < 0.0) - // { - // inclm = -inclm; - // argpm = argpm - pi; - // nodem = nodem + pi; - // } - - /* -------------- initialize the resonance terms ------------- */ - if (irez != 0) - { - aonv = pow(nm / xke, x2o3); - - /* ---------- geopotential resonance for 12 hour orbits ------ */ - if (irez == 2) - { - cosisq = cosim * cosim; - emo = em; - em = ecco; - emsqo = emsq; - emsq = eccsq; - eoc = em * emsq; - g201 = -0.306 - (em - 0.64) * 0.440; - - if (em <= 0.65) - { - g211 = 3.616 - 13.2470 * em + 16.2900 * emsq; - g310 = -19.302 + 117.3900 * em - 228.4190 * emsq + 156.5910 * eoc; - g322 = -18.9068 + 109.7927 * em - 214.6334 * emsq + 146.5816 * eoc; - g410 = -41.122 + 242.6940 * em - 471.0940 * emsq + 313.9530 * eoc; - g422 = -146.407 + 841.8800 * em - 1629.014 * emsq + 1083.4350 * eoc; - g520 = -532.114 + 3017.977 * em - 5740.032 * emsq + 3708.2760 * eoc; - } - else - { - g211 = -72.099 + 331.819 * em - 508.738 * emsq + 266.724 * eoc; - g310 = -346.844 + 1582.851 * em - 2415.925 * emsq + 1246.113 * eoc; - g322 = -342.585 + 1554.908 * em - 2366.899 * emsq + 1215.972 * eoc; - g410 = -1052.797 + 4758.686 * em - 7193.992 * emsq + 3651.957 * eoc; - g422 = -3581.690 + 16178.110 * em - 24462.770 * emsq + 12422.520 * eoc; - if (em > 0.715) - g520 =-5149.66 + 29936.92 * em - 54087.36 * emsq + 31324.56 * eoc; - else - g520 = 1464.74 - 4664.75 * em + 3763.64 * emsq; - } - if (em < 0.7) - { - g533 = -919.22770 + 4988.6100 * em - 9064.7700 * emsq + 5542.21 * eoc; - g521 = -822.71072 + 4568.6173 * em - 8491.4146 * emsq + 5337.524 * eoc; - g532 = -853.66600 + 4690.2500 * em - 8624.7700 * emsq + 5341.4 * eoc; - } - else - { - g533 =-37995.780 + 161616.52 * em - 229838.20 * emsq + 109377.94 * eoc; - g521 =-51752.104 + 218913.95 * em - 309468.16 * emsq + 146349.42 * eoc; - g532 =-40023.880 + 170470.89 * em - 242699.48 * emsq + 115605.82 * eoc; - } - - sini2= sinim * sinim; - f220 = 0.75 * (1.0 + 2.0 * cosim+cosisq); - f221 = 1.5 * sini2; - f321 = 1.875 * sinim * (1.0 - 2.0 * cosim - 3.0 * cosisq); - f322 = -1.875 * sinim * (1.0 + 2.0 * cosim - 3.0 * cosisq); - f441 = 35.0 * sini2 * f220; - f442 = 39.3750 * sini2 * sini2; - f522 = 9.84375 * sinim * (sini2 * (1.0 - 2.0 * cosim- 5.0 * cosisq) + - 0.33333333 * (-2.0 + 4.0 * cosim + 6.0 * cosisq) ); - f523 = sinim * (4.92187512 * sini2 * (-2.0 - 4.0 * cosim + - 10.0 * cosisq) + 6.56250012 * (1.0+2.0 * cosim - 3.0 * cosisq)); - f542 = 29.53125 * sinim * (2.0 - 8.0 * cosim+cosisq * - (-12.0 + 8.0 * cosim + 10.0 * cosisq)); - f543 = 29.53125 * sinim * (-2.0 - 8.0 * cosim+cosisq * - (12.0 + 8.0 * cosim - 10.0 * cosisq)); - xno2 = nm * nm; - ainv2 = aonv * aonv; - temp1 = 3.0 * xno2 * ainv2; - temp = temp1 * root22; - d2201 = temp * f220 * g201; - d2211 = temp * f221 * g211; - temp1 = temp1 * aonv; - temp = temp1 * root32; - d3210 = temp * f321 * g310; - d3222 = temp * f322 * g322; - temp1 = temp1 * aonv; - temp = 2.0 * temp1 * root44; - d4410 = temp * f441 * g410; - d4422 = temp * f442 * g422; - temp1 = temp1 * aonv; - temp = temp1 * root52; - d5220 = temp * f522 * g520; - d5232 = temp * f523 * g532; - temp = 2.0 * temp1 * root54; - d5421 = temp * f542 * g521; - d5433 = temp * f543 * g533; - xlamo = fmod(mo + nodeo + nodeo-theta - theta, twopi); - xfact = mdot + dmdt + 2.0 * (nodedot + dnodt - rptim) - no; - em = emo; - emsq = emsqo; - } - - /* ---------------- synchronous resonance terms -------------- */ - if (irez == 1) - { - g200 = 1.0 + emsq * (-2.5 + 0.8125 * emsq); - g310 = 1.0 + 2.0 * emsq; - g300 = 1.0 + emsq * (-6.0 + 6.60937 * emsq); - f220 = 0.75 * (1.0 + cosim) * (1.0 + cosim); - f311 = 0.9375 * sinim * sinim * (1.0 + 3.0 * cosim) - 0.75 * (1.0 + cosim); - f330 = 1.0 + cosim; - f330 = 1.875 * f330 * f330 * f330; - del1 = 3.0 * nm * nm * aonv * aonv; - del2 = 2.0 * del1 * f220 * g200 * q22; - del3 = 3.0 * del1 * f330 * g300 * q33 * aonv; - del1 = del1 * f311 * g310 * q31 * aonv; - xlamo = fmod(mo + nodeo + argpo - theta, twopi); - xfact = mdot + xpidot - rptim + dmdt + domdt + dnodt - no; - } - - /* ------------ for sgp4, initialize the integrator ---------- */ - xli = xlamo; - xni = no; - atime = 0.0; - nm = no + dndt; - } - -//#include "debug3.cpp" -} // end dsinit - -/*----------------------------------------------------------------------------- -* -* procedure dspace -* -* this procedure provides deep space contributions to mean elements for -* perturbing third body. these effects have been averaged over one -* revolution of the sun and moon. for earth resonance effects, the -* effects have been averaged over no revolutions of the satellite. -* (mean motion) -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 - -* dedt - -* del1, del2, del3 - -* didt - -* dmdt - -* dnodt - -* domdt - -* irez - flag for resonance 0-none, 1-one day, 2-half day -* argpo - argument of perigee -* argpdot - argument of perigee dot (rate) -* t - time -* tc - -* gsto - gst -* xfact - -* xlamo - -* no - mean motion -* atime - -* em - eccentricity -* ft - -* argpm - argument of perigee -* inclm - inclination -* xli - -* mm - mean anomaly -* xni - mean motion -* nodem - right ascension of ascending node -* -* outputs : -* atime - -* em - eccentricity -* argpm - argument of perigee -* inclm - inclination -* xli - -* mm - mean anomaly -* xni - -* nodem - right ascension of ascending node -* dndt - -* nm - mean motion -* -* locals : -* delt - -* ft - -* theta - -* x2li - -* x2omi - -* xl - -* xldot - -* xnddt - -* xndt - -* xomi - -* -* coupling : -* none - -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void dspace - ( - int irez, - double d2201, double d2211, double d3210, double d3222, double d4410, - double d4422, double d5220, double d5232, double d5421, double d5433, - double dedt, double del1, double del2, double del3, double didt, - double dmdt, double dnodt, double domdt, double argpo, double argpdot, - double t, double tc, double gsto, double xfact, double xlamo, - double no, - double& atime, double& em, double& argpm, double& inclm, double& xli, - double& mm, double& xni, double& nodem, double& dndt, double& nm - ) -{ - const double twopi = 2.0 * pi; - int iretn , iret; - double delt, ft, theta, x2li, x2omi, xl, xldot , xnddt, xndt, xomi, g22, g32, - g44, g52, g54, fasx2, fasx4, fasx6, rptim , step2, stepn , stepp; - - ft = 0.0; - fasx2 = 0.13130908; - fasx4 = 2.8843198; - fasx6 = 0.37448087; - g22 = 5.7686396; - g32 = 0.95240898; - g44 = 1.8014998; - g52 = 1.0508330; - g54 = 4.4108898; - rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec - stepp = 720.0; - stepn = -720.0; - step2 = 259200.0; - - /* ----------- calculate deep space resonance effects ----------- */ - dndt = 0.0; - theta = fmod(gsto + tc * rptim, twopi); - em = em + dedt * t; - - inclm = inclm + didt * t; - argpm = argpm + domdt * t; - nodem = nodem + dnodt * t; - mm = mm + dmdt * t; - - // sgp4fix for negative inclinations - // the following if statement should be commented out - // if (inclm < 0.0) - // { - // inclm = -inclm; - // argpm = argpm - pi; - // nodem = nodem + pi; - // } - - /* - update resonances : numerical (euler-maclaurin) integration - */ - /* ------------------------- epoch restart ---------------------- */ - // sgp4fix for propagator problems - // the following integration works for negative time steps and periods - // the specific changes are unknown because the original code was so convoluted - - ft = 0.0; - atime = 0.0; - if (irez != 0) - { - if ((atime == 0.0) || ((t >= 0.0) && (atime < 0.0)) || - ((t < 0.0) && (atime >= 0.0))) - { - if (t >= 0.0) - delt = stepp; - else - delt = stepn; - atime = 0.0; - xni = no; - xli = xlamo; - } - iretn = 381; // added for do loop - iret = 0; // added for loop - while (iretn == 381) - { - if ((fabs(t) < fabs(atime)) || (iret == 351)) - { - if (t >= 0.0) - delt = stepn; - else - delt = stepp; - iret = 351; - iretn = 381; - } - else - { - if (t > 0.0) // error if prev if has atime:=0.0 and t:=0.0 (ge) - delt = stepp; - else - delt = stepn; - if (fabs(t - atime) >= stepp) - { - iret = 0; - iretn = 381; - } - else - { - ft = t - atime; - iretn = 0; - } - } - - /* ------------------- dot terms calculated ------------- */ - /* ----------- near - synchronous resonance terms ------- */ - if (irez != 2) - { - xndt = del1 * sin(xli - fasx2) + del2 * sin(2.0 * (xli - fasx4)) + - del3 * sin(3.0 * (xli - fasx6)); - xldot = xni + xfact; - xnddt = del1 * cos(xli - fasx2) + - 2.0 * del2 * cos(2.0 * (xli - fasx4)) + - 3.0 * del3 * cos(3.0 * (xli - fasx6)); - xnddt = xnddt * xldot; - } - else - { - /* --------- near - half-day resonance terms -------- */ - xomi = argpo + argpdot * atime; - x2omi = xomi + xomi; - x2li = xli + xli; - xndt = d2201 * sin(x2omi + xli - g22) + d2211 * sin(xli - g22) + - d3210 * sin(xomi + xli - g32) + d3222 * sin(-xomi + xli - g32)+ - d4410 * sin(x2omi + x2li - g44)+ d4422 * sin(x2li - g44) + - d5220 * sin(xomi + xli - g52) + d5232 * sin(-xomi + xli - g52)+ - d5421 * sin(xomi + x2li - g54) + d5433 * sin(-xomi + x2li - g54); - xldot = xni + xfact; - xnddt = d2201 * cos(x2omi + xli - g22) + d2211 * cos(xli - g22) + - d3210 * cos(xomi + xli - g32) + d3222 * cos(-xomi + xli - g32) + - d5220 * cos(xomi + xli - g52) + d5232 * cos(-xomi + xli - g52) + - 2.0 * (d4410 * cos(x2omi + x2li - g44) + - d4422 * cos(x2li - g44) + d5421 * cos(xomi + x2li - g54) + - d5433 * cos(-xomi + x2li - g54)); - xnddt = xnddt * xldot; - } - - /* ----------------------- integrator ------------------- */ - if (iretn == 381) - { - xli = xli + xldot * delt + xndt * step2; - xni = xni + xndt * delt + xnddt * step2; - atime = atime + delt; - } - } // while iretn = 381 - - nm = xni + xndt * ft + xnddt * ft * ft * 0.5; - xl = xli + xldot * ft + xndt * ft * ft * 0.5; - if (irez != 1) - { - mm = xl - 2.0 * nodem + 2.0 * theta; - dndt = nm - no; - } - else - { - mm = xl - nodem - argpm + theta; - dndt = nm - no; - } - nm = no + dndt; - } - -//#include "debug4.cpp" -} // end dsspace - -/*----------------------------------------------------------------------------- -* -* procedure initl -* -* this procedure initializes the spg4 propagator. all the initialization is -* consolidated here instead of having multiple loops inside other routines. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* ecco - eccentricity 0.0 - 1.0 -* epoch - epoch time in days from jan 0, 1950. 0 hr -* inclo - inclination of satellite -* no - mean motion of satellite -* satn - satellite number -* -* outputs : -* ainv - 1.0 / a -* ao - semi major axis -* con41 - -* con42 - 1.0 - 5.0 cos(i) -* cosio - cosine of inclination -* cosio2 - cosio squared -* eccsq - eccentricity squared -* method - flag for deep space 'd', 'n' -* omeosq - 1.0 - ecco * ecco -* posq - semi-parameter squared -* rp - radius of perigee -* rteosq - square root of (1.0 - ecco*ecco) -* sinio - sine of inclination -* gsto - gst at time of observation rad -* no - mean motion of satellite -* -* locals : -* ak - -* d1 - -* del - -* adel - -* po - -* -* coupling : -* getgravconst -* gstime - find greenwich sidereal time from the julian date -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void initl - ( - int satn, gravconsttype whichconst, - double ecco, double epoch, double inclo, double& no, - char& method, - double& ainv, double& ao, double& con41, double& con42, double& cosio, - double& cosio2,double& eccsq, double& omeosq, double& posq, - double& rp, double& rteosq,double& sinio , double& gsto - ) -{ - /* --------------------- local variables ------------------------ */ - double ak, d1, del, adel, po, x2o3, j2, xke, - tumin, mu, radiusearthkm, j3, j4, j3oj2; - - // sgp4fix use old way of finding gst - int ids70; - double ts70, ds70, tfrac, c1, thgr70, fk5r, c1p2p; - const double twopi = 2.0 * pi; - - /* ----------------------- earth constants ---------------------- */ - // sgp4fix identify constants and allow alternate values - getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); - x2o3 = 2.0 / 3.0; - - /* ------------- calculate auxillary epoch quantities ---------- */ - eccsq = ecco * ecco; - omeosq = 1.0 - eccsq; - rteosq = sqrt(omeosq); - cosio = cos(inclo); - cosio2 = cosio * cosio; - - /* ------------------ un-kozai the mean motion ----------------- */ - ak = pow(xke / no, x2o3); - d1 = 0.75 * j2 * (3.0 * cosio2 - 1.0) / (rteosq * omeosq); - del = d1 / (ak * ak); - adel = ak * (1.0 - del * del - del * - (1.0 / 3.0 + 134.0 * del * del / 81.0)); - del = d1/(adel * adel); - no = no / (1.0 + del); - - ao = pow(xke / no, x2o3); - sinio = sin(inclo); - po = ao * omeosq; - con42 = 1.0 - 5.0 * cosio2; - con41 = -con42-cosio2-cosio2; - ainv = 1.0 / ao; - posq = po * po; - rp = ao * (1.0 - ecco); - method = 'n'; - - // sgp4fix modern approach to finding sidereal timew - // gsto = gstime(epoch + 2433281.5); - - // sgp4fix use old way of finding gst - // count integer number of days from 0 jan 1970 - ts70 = epoch - 7305.0; - ids70 = floor(ts70 + 1.0e-8); - ds70 = ids70; - tfrac = ts70 - ds70; - // find greenwich location at epoch - c1 = 1.72027916940703639e-2; - thgr70= 1.7321343856509374; - fk5r = 5.07551419432269442e-15; - c1p2p = c1 + twopi; - gsto = fmod( thgr70 + c1*ds70 + c1p2p*tfrac + ts70*ts70*fk5r, twopi); - if ( gsto < 0.0 ) - gsto = gsto + twopi; - -//#include "debug5.cpp" -} // end initl - -/*----------------------------------------------------------------------------- -* -* procedure sgp4init -* -* this procedure initializes variables for sgp4. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* satn - satellite number -* bstar - sgp4 type drag coefficient kg/m2er -* ecco - eccentricity -* epoch - epoch time in days from jan 0, 1950. 0 hr -* argpo - argument of perigee (output if ds) -* inclo - inclination -* mo - mean anomaly (output if ds) -* no - mean motion -* nodeo - right ascension of ascending node -* -* outputs : -* satrec - common values for subsequent calls -* return code - non-zero on error. -* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er -* 2 - mean motion less than 0.0 -* 3 - pert elements, ecc < 0.0 or ecc > 1.0 -* 4 - semi-latus rectum < 0.0 -* 5 - epoch elements are sub-orbital -* 6 - satellite has decayed -* -* locals : -* cnodm , snodm , cosim , sinim , cosomm , sinomm -* cc1sq , cc2 , cc3 -* coef , coef1 -* cosio4 - -* day - -* dndt - -* em - eccentricity -* emsq - eccentricity squared -* eeta - -* etasq - -* gam - -* argpm - argument of perigee -* nodem - -* inclm - inclination -* mm - mean anomaly -* nm - mean motion -* perige - perigee -* pinvsq - -* psisq - -* qzms24 - -* rtemsq - -* s1, s2, s3, s4, s5, s6, s7 - -* sfour - -* ss1, ss2, ss3, ss4, ss5, ss6, ss7 - -* sz1, sz2, sz3 -* sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33 - -* tc - -* temp - -* temp1, temp2, temp3 - -* tsi - -* xpidot - -* xhdot1 - -* z1, z2, z3 - -* z11, z12, z13, z21, z22, z23, z31, z32, z33 - -* -* coupling : -* getgravconst- -* initl - -* dscom - -* dpper - -* dsinit - -* sgp4 - -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -int sgp4init - ( - gravconsttype whichconst, const int satn, const double epoch, - const double xbstar, const double xecco, const double xargpo, - const double xinclo, const double xmo, const double xno, - const double xnodeo, elsetrec& satrec - ) -{ - /* --------------------- local variables ------------------------ */ - double ao, ainv, con42, cosio, sinio, cosio2, eccsq, - omeosq, posq, rp, rteosq, - cnodm , snodm , cosim , sinim , cosomm, sinomm, cc1sq , - cc2 , cc3 , coef , coef1 , cosio4, day , dndt , - em , emsq , eeta , etasq , gam , argpm , nodem , - inclm , mm , nm , perige, pinvsq, psisq , qzms24, - rtemsq, s1 , s2 , s3 , s4 , s5 , s6 , - s7 , sfour , ss1 = 0 , ss2 = 0 , ss3 = 0 , ss4 = 0 , ss5 = 0 , - ss6 = 0 , ss7 = 0 , sz1 = 0 , sz2 = 0 , sz3 = 0 , sz11 = 0 , sz12 = 0 , - sz13 = 0 , sz21 = 0 , sz22 = 0 , sz23 = 0 , sz31 = 0 , sz32 = 0 , sz33 = 0 , - tc , temp , temp1 , temp2 , temp3 , tsi , xpidot, - xhdot1, z1 , z2 , z3 , z11 , z12 , z13 , - z21 , z22 , z23 , z31 , z32 , z33, - qzms2t, ss, j2, j3oj2, j4, x2o3, r[3], v[3], - tumin, mu, radiusearthkm, xke, j3; - - /* ------------------------ initialization --------------------- */ - // sgp4fix divisor for divide by zero check on inclination - const double temp4 = 1.0 + cos(pi-1.0e-9); - - /* ----------- set all near earth variables to zero ------------ */ - satrec.isimp = 0; satrec.method = 'n'; satrec.aycof = 0.0; - satrec.con41 = 0.0; satrec.cc1 = 0.0; satrec.cc4 = 0.0; - satrec.cc5 = 0.0; satrec.d2 = 0.0; satrec.d3 = 0.0; - satrec.d4 = 0.0; satrec.delmo = 0.0; satrec.eta = 0.0; - satrec.argpdot = 0.0; satrec.omgcof = 0.0; satrec.sinmao = 0.0; - satrec.t = 0.0; satrec.t2cof = 0.0; satrec.t3cof = 0.0; - satrec.t4cof = 0.0; satrec.t5cof = 0.0; satrec.x1mth2 = 0.0; - satrec.x7thm1 = 0.0; satrec.mdot = 0.0; satrec.nodedot = 0.0; - satrec.xlcof = 0.0; satrec.xmcof = 0.0; satrec.nodecf = 0.0; - - /* ----------- set all deep space variables to zero ------------ */ - satrec.irez = 0; satrec.d2201 = 0.0; satrec.d2211 = 0.0; - satrec.d3210 = 0.0; satrec.d3222 = 0.0; satrec.d4410 = 0.0; - satrec.d4422 = 0.0; satrec.d5220 = 0.0; satrec.d5232 = 0.0; - satrec.d5421 = 0.0; satrec.d5433 = 0.0; satrec.dedt = 0.0; - satrec.del1 = 0.0; satrec.del2 = 0.0; satrec.del3 = 0.0; - satrec.didt = 0.0; satrec.dmdt = 0.0; satrec.dnodt = 0.0; - satrec.domdt = 0.0; satrec.e3 = 0.0; satrec.ee2 = 0.0; - satrec.peo = 0.0; satrec.pgho = 0.0; satrec.pho = 0.0; - satrec.pinco = 0.0; satrec.plo = 0.0; satrec.se2 = 0.0; - satrec.se3 = 0.0; satrec.sgh2 = 0.0; satrec.sgh3 = 0.0; - satrec.sgh4 = 0.0; satrec.sh2 = 0.0; satrec.sh3 = 0.0; - satrec.si2 = 0.0; satrec.si3 = 0.0; satrec.sl2 = 0.0; - satrec.sl3 = 0.0; satrec.sl4 = 0.0; satrec.gsto = 0.0; - satrec.xfact = 0.0; satrec.xgh2 = 0.0; satrec.xgh3 = 0.0; - satrec.xgh4 = 0.0; satrec.xh2 = 0.0; satrec.xh3 = 0.0; - satrec.xi2 = 0.0; satrec.xi3 = 0.0; satrec.xl2 = 0.0; - satrec.xl3 = 0.0; satrec.xl4 = 0.0; satrec.xlamo = 0.0; - satrec.zmol = 0.0; satrec.zmos = 0.0; satrec.atime = 0.0; - satrec.xli = 0.0; satrec.xni = 0.0; - - // sgp4fix - note the following variables are also passed directly via satrec. - // it is possible to streamline the sgp4init call by deleting the "x" - // variables, but the user would need to set the satrec.* values first. we - // include the additional assignments in case twoline2rv is not used. - satrec.bstar = xbstar; - satrec.ecco = xecco; - satrec.argpo = xargpo; - satrec.inclo = xinclo; - satrec.mo = xmo; - satrec.no = xno; - satrec.nodeo = xnodeo; - - /* ------------------------ earth constants ----------------------- */ - // sgp4fix identify constants and allow alternate values - getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); - ss = 78.0 / radiusearthkm + 1.0; - qzms2t = pow(((120.0 - 78.0) / radiusearthkm), 4); - x2o3 = 2.0 / 3.0; - - satrec.init = 'y'; - satrec.t = 0.0; - - initl - ( - satn, whichconst, satrec.ecco, epoch, satrec.inclo, satrec.no, satrec.method, - ainv, ao, satrec.con41, con42, cosio, cosio2, eccsq, omeosq, - posq, rp, rteosq, sinio, satrec.gsto - ); - satrec.error = 0; - - if (rp < 1.0) - { -// printf("# *** satn%d epoch elts sub-orbital ***\n", satn); - satrec.error = 5; - } - - if ((omeosq >= 0.0 ) || ( satrec.no >= 0.0)) - { - satrec.isimp = 0; - if (rp < (220.0 / radiusearthkm + 1.0)) - satrec.isimp = 1; - sfour = ss; - qzms24 = qzms2t; - perige = (rp - 1.0) * radiusearthkm; - - /* - for perigees below 156 km, s and qoms2t are altered - */ - if (perige < 156.0) - { - sfour = perige - 78.0; - if (perige < 98.0) - sfour = 20.0; - qzms24 = pow(((120.0 - sfour) / radiusearthkm), 4.0); - sfour = sfour / radiusearthkm + 1.0; - } - pinvsq = 1.0 / posq; - - tsi = 1.0 / (ao - sfour); - satrec.eta = ao * satrec.ecco * tsi; - etasq = satrec.eta * satrec.eta; - eeta = satrec.ecco * satrec.eta; - psisq = fabs(1.0 - etasq); - coef = qzms24 * pow(tsi, 4.0); - coef1 = coef / pow(psisq, 3.5); - cc2 = coef1 * satrec.no * (ao * (1.0 + 1.5 * etasq + eeta * - (4.0 + etasq)) + 0.375 * j2 * tsi / psisq * satrec.con41 * - (8.0 + 3.0 * etasq * (8.0 + etasq))); - satrec.cc1 = satrec.bstar * cc2; - cc3 = 0.0; - if (satrec.ecco > 1.0e-4) - cc3 = -2.0 * coef * tsi * j3oj2 * satrec.no * sinio / satrec.ecco; - satrec.x1mth2 = 1.0 - cosio2; - satrec.cc4 = 2.0* satrec.no * coef1 * ao * omeosq * - (satrec.eta * (2.0 + 0.5 * etasq) + satrec.ecco * - (0.5 + 2.0 * etasq) - j2 * tsi / (ao * psisq) * - (-3.0 * satrec.con41 * (1.0 - 2.0 * eeta + etasq * - (1.5 - 0.5 * eeta)) + 0.75 * satrec.x1mth2 * - (2.0 * etasq - eeta * (1.0 + etasq)) * cos(2.0 * satrec.argpo))); - satrec.cc5 = 2.0 * coef1 * ao * omeosq * (1.0 + 2.75 * - (etasq + eeta) + eeta * etasq); - cosio4 = cosio2 * cosio2; - temp1 = 1.5 * j2 * pinvsq * satrec.no; - temp2 = 0.5 * temp1 * j2 * pinvsq; - temp3 = -0.46875 * j4 * pinvsq * pinvsq * satrec.no; - satrec.mdot = satrec.no + 0.5 * temp1 * rteosq * satrec.con41 + 0.0625 * - temp2 * rteosq * (13.0 - 78.0 * cosio2 + 137.0 * cosio4); - satrec.argpdot = -0.5 * temp1 * con42 + 0.0625 * temp2 * - (7.0 - 114.0 * cosio2 + 395.0 * cosio4) + - temp3 * (3.0 - 36.0 * cosio2 + 49.0 * cosio4); - xhdot1 = -temp1 * cosio; - satrec.nodedot = xhdot1 + (0.5 * temp2 * (4.0 - 19.0 * cosio2) + - 2.0 * temp3 * (3.0 - 7.0 * cosio2)) * cosio; - xpidot = satrec.argpdot+ satrec.nodedot; - satrec.omgcof = satrec.bstar * cc3 * cos(satrec.argpo); - satrec.xmcof = 0.0; - if (satrec.ecco > 1.0e-4) - satrec.xmcof = -x2o3 * coef * satrec.bstar / eeta; - satrec.nodecf = 3.5 * omeosq * xhdot1 * satrec.cc1; - satrec.t2cof = 1.5 * satrec.cc1; - // sgp4fix for divide by zero with xinco = 180 deg - if (fabs(cosio+1.0) > 1.5e-12) - satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / (1.0 + cosio); - else - satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / temp4; - satrec.aycof = -0.5 * j3oj2 * sinio; - satrec.delmo = pow((1.0 + satrec.eta * cos(satrec.mo)), 3); - satrec.sinmao = sin(satrec.mo); - satrec.x7thm1 = 7.0 * cosio2 - 1.0; - - /* --------------- deep space initialization ------------- */ - if ((2*pi / satrec.no) >= 225.0) - { - satrec.method = 'd'; - satrec.isimp = 1; - tc = 0.0; - inclm = satrec.inclo; - - dscom - ( - epoch, satrec.ecco, satrec.argpo, tc, satrec.inclo, satrec.nodeo, - satrec.no, snodm, cnodm, sinim, cosim,sinomm, cosomm, - day, satrec.e3, satrec.ee2, em, emsq, gam, - satrec.peo, satrec.pgho, satrec.pho, satrec.pinco, - satrec.plo, rtemsq, satrec.se2, satrec.se3, - satrec.sgh2, satrec.sgh3, satrec.sgh4, - satrec.sh2, satrec.sh3, satrec.si2, satrec.si3, - satrec.sl2, satrec.sl3, satrec.sl4, s1, s2, s3, s4, s5, - s6, s7, ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3, - sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33, - satrec.xgh2, satrec.xgh3, satrec.xgh4, satrec.xh2, - satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2, - satrec.xl3, satrec.xl4, nm, z1, z2, z3, z11, - z12, z13, z21, z22, z23, z31, z32, z33, - satrec.zmol, satrec.zmos - ); - dpper - ( - satrec.e3, satrec.ee2, satrec.peo, satrec.pgho, - satrec.pho, satrec.pinco, satrec.plo, satrec.se2, - satrec.se3, satrec.sgh2, satrec.sgh3, satrec.sgh4, - satrec.sh2, satrec.sh3, satrec.si2, satrec.si3, - satrec.sl2, satrec.sl3, satrec.sl4, satrec.t, - satrec.xgh2,satrec.xgh3,satrec.xgh4, satrec.xh2, - satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2, - satrec.xl3, satrec.xl4, satrec.zmol, satrec.zmos, inclm, satrec.init, - satrec.ecco, satrec.inclo, satrec.nodeo, satrec.argpo, satrec.mo - ); - - argpm = 0.0; - nodem = 0.0; - mm = 0.0; - - dsinit - ( - whichconst, - cosim, emsq, satrec.argpo, s1, s2, s3, s4, s5, sinim, ss1, ss2, ss3, ss4, - ss5, sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33, satrec.t, tc, - satrec.gsto, satrec.mo, satrec.mdot, satrec.no, satrec.nodeo, - satrec.nodedot, xpidot, z1, z3, z11, z13, z21, z23, z31, z33, - satrec.ecco, eccsq, em, argpm, inclm, mm, nm, nodem, - satrec.irez, satrec.atime, - satrec.d2201, satrec.d2211, satrec.d3210, satrec.d3222 , - satrec.d4410, satrec.d4422, satrec.d5220, satrec.d5232, - satrec.d5421, satrec.d5433, satrec.dedt, satrec.didt, - satrec.dmdt, dndt, satrec.dnodt, satrec.domdt , - satrec.del1, satrec.del2, satrec.del3, satrec.xfact, - satrec.xlamo, satrec.xli, satrec.xni - ); - } - - /* ----------- set variables if not deep space ----------- */ - if (satrec.isimp != 1) - { - cc1sq = satrec.cc1 * satrec.cc1; - satrec.d2 = 4.0 * ao * tsi * cc1sq; - temp = satrec.d2 * tsi * satrec.cc1 / 3.0; - satrec.d3 = (17.0 * ao + sfour) * temp; - satrec.d4 = 0.5 * temp * ao * tsi * (221.0 * ao + 31.0 * sfour) * - satrec.cc1; - satrec.t3cof = satrec.d2 + 2.0 * cc1sq; - satrec.t4cof = 0.25 * (3.0 * satrec.d3 + satrec.cc1 * - (12.0 * satrec.d2 + 10.0 * cc1sq)); - satrec.t5cof = 0.2 * (3.0 * satrec.d4 + - 12.0 * satrec.cc1 * satrec.d3 + - 6.0 * satrec.d2 * satrec.d2 + - 15.0 * cc1sq * (2.0 * satrec.d2 + cc1sq)); - } - } // if omeosq = 0 ... - - /* finally propogate to zero epoch to initialise all others. */ - if(satrec.error == 0) - sgp4(whichconst, satrec, 0.0, r, v); - - satrec.init = 'n'; - -//#include "debug6.cpp" - return satrec.error; -} // end sgp4init - -/*----------------------------------------------------------------------------- -* -* procedure sgp4 -* -* this procedure is the sgp4 prediction model from space command. this is an -* updated and combined version of sgp4 and sdp4, which were originally -* published separately in spacetrack report #3. this version follows the -* methodology from the aiaa paper (2006) describing the history and -* development of the code. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* satrec - initialised structure from sgp4init() call. -* tsince - time eince epoch (minutes) -* -* outputs : -* r - position vector km -* v - velocity km/sec -* return code - non-zero on error. -* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er -* 2 - mean motion less than 0.0 -* 3 - pert elements, ecc < 0.0 or ecc > 1.0 -* 4 - semi-latus rectum < 0.0 -* 5 - epoch elements are sub-orbital -* 6 - satellite has decayed -* -* locals : -* am - -* axnl, aynl - -* betal - -* cosim , sinim , cosomm , sinomm , cnod , snod , cos2u , -* sin2u , coseo1 , sineo1 , cosi , sini , cosip , sinip , -* cosisq , cossu , sinsu , cosu , sinu -* delm - -* delomg - -* dndt - -* eccm - -* emsq - -* ecose - -* el2 - -* eo1 - -* eccp - -* esine - -* argpm - -* argpp - -* omgadf - -* pl - -* r - -* rtemsq - -* rdotl - -* rl - -* rvdot - -* rvdotl - -* su - -* t2 , t3 , t4 , tc -* tem5, temp , temp1 , temp2 , tempa , tempe , templ -* u , ux , uy , uz , vx , vy , vz -* inclm - inclination -* mm - mean anomaly -* nm - mean motion -* nodem - right asc of ascending node -* xinc - -* xincp - -* xl - -* xlm - -* mp - -* xmdf - -* xmx - -* xmy - -* nodedf - -* xnode - -* nodep - -* np - -* -* coupling : -* getgravconst- -* dpper -* dpspace -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -int sgp4 - ( - gravconsttype whichconst, elsetrec& satrec, double tsince, - double r[3], double v[3] - ) -{ - double am , axnl , aynl , betal , cosim , cnod , - cos2u, coseo1, cosi , cosip , cosisq, cossu , cosu, - delm , delomg, em , emsq , ecose , el2 , eo1 , - ep , esine , argpm, argpp , argpdf, pl, mrt = 0.0, - mvt , rdotl , rl , rvdot , rvdotl, sinim , - sin2u, sineo1, sini , sinip , sinsu , sinu , - snod , su , t2 , t3 , t4 , tem5 , temp, - temp1, temp2 , tempa, tempe , templ , u , ux , - uy , uz , vx , vy , vz , inclm , mm , - nm , nodem, xinc , xincp , xl , xlm , mp , - xmdf , xmx , xmy , nodedf, xnode , nodep, tc , dndt, - twopi, x2o3 , j2 , j3 , tumin, j4 , xke , j3oj2, radiusearthkm, - mu, vkmpersec; - int ktr; - - /* ------------------ set mathematical constants --------------- */ - // sgp4fix divisor for divide by zero check on inclination - const double temp4 = 1.0 + cos(pi-1.0e-9); - twopi = 2.0 * pi; - x2o3 = 2.0 / 3.0; - // sgp4fix identify constants and allow alternate values - getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); - vkmpersec = radiusearthkm * xke/60.0; - - /* --------------------- clear sgp4 error flag ----------------- */ - satrec.t = tsince; - satrec.error = 0; - - /* ------- update for secular gravity and atmospheric drag ----- */ - xmdf = satrec.mo + satrec.mdot * satrec.t; - argpdf = satrec.argpo + satrec.argpdot * satrec.t; - nodedf = satrec.nodeo + satrec.nodedot * satrec.t; - argpm = argpdf; - mm = xmdf; - t2 = satrec.t * satrec.t; - nodem = nodedf + satrec.nodecf * t2; - tempa = 1.0 - satrec.cc1 * satrec.t; - tempe = satrec.bstar * satrec.cc4 * satrec.t; - templ = satrec.t2cof * t2; - - if (satrec.isimp != 1) - { - delomg = satrec.omgcof * satrec.t; - delm = satrec.xmcof * - (pow((1.0 + satrec.eta * cos(xmdf)), 3) - - satrec.delmo); - temp = delomg + delm; - mm = xmdf + temp; - argpm = argpdf - temp; - t3 = t2 * satrec.t; - t4 = t3 * satrec.t; - tempa = tempa - satrec.d2 * t2 - satrec.d3 * t3 - - satrec.d4 * t4; - tempe = tempe + satrec.bstar * satrec.cc5 * (sin(mm) - - satrec.sinmao); - templ = templ + satrec.t3cof * t3 + t4 * (satrec.t4cof + - satrec.t * satrec.t5cof); - } - - nm = satrec.no; - em = satrec.ecco; - inclm = satrec.inclo; - if (satrec.method == 'd') - { - tc = satrec.t; - dspace - ( - satrec.irez, - satrec.d2201, satrec.d2211, satrec.d3210, - satrec.d3222, satrec.d4410, satrec.d4422, - satrec.d5220, satrec.d5232, satrec.d5421, - satrec.d5433, satrec.dedt, satrec.del1, - satrec.del2, satrec.del3, satrec.didt, - satrec.dmdt, satrec.dnodt, satrec.domdt, - satrec.argpo, satrec.argpdot, satrec.t, tc, - satrec.gsto, satrec.xfact, satrec.xlamo, - satrec.no, satrec.atime, - em, argpm, inclm, satrec.xli, mm, satrec.xni, - nodem, dndt, nm - ); - } // if method = d - - if (nm <= 0.0) - { -// printf("# error nm %f\n", nm); - satrec.error = 2; - } - am = pow((xke / nm),x2o3) * tempa * tempa; - nm = xke / pow(am, 1.5); - em = em - tempe; - - // fix tolerance for error recognition - if ((em >= 1.0) || (em < -0.001) || (am < 0.95)) - { -// printf("# error em %f\n", em); - satrec.error = 1; - } - if (em < 0.0) - em = 1.0e-6; - mm = mm + satrec.no * templ; - xlm = mm + argpm + nodem; - emsq = em * em; - temp = 1.0 - emsq; - - nodem = fmod(nodem, twopi); - argpm = fmod(argpm, twopi); - xlm = fmod(xlm, twopi); - mm = fmod(xlm - argpm - nodem, twopi); - - /* ----------------- compute extra mean quantities ------------- */ - sinim = sin(inclm); - cosim = cos(inclm); - - /* -------------------- add lunar-solar periodics -------------- */ - ep = em; - xincp = inclm; - argpp = argpm; - nodep = nodem; - mp = mm; - sinip = sinim; - cosip = cosim; - if (satrec.method == 'd') - { - dpper - ( - satrec.e3, satrec.ee2, satrec.peo, - satrec.pgho, satrec.pho, satrec.pinco, - satrec.plo, satrec.se2, satrec.se3, - satrec.sgh2, satrec.sgh3, satrec.sgh4, - satrec.sh2, satrec.sh3, satrec.si2, - satrec.si3, satrec.sl2, satrec.sl3, - satrec.sl4, satrec.t, satrec.xgh2, - satrec.xgh3, satrec.xgh4, satrec.xh2, - satrec.xh3, satrec.xi2, satrec.xi3, - satrec.xl2, satrec.xl3, satrec.xl4, - satrec.zmol, satrec.zmos, satrec.inclo, - 'n', ep, xincp, nodep, argpp, mp - ); - if (xincp < 0.0) - { - xincp = -xincp; - nodep = nodep + pi; - argpp = argpp - pi; - } - if ((ep < 0.0 ) || ( ep > 1.0)) - { - // printf("# error ep %f\n", ep); - satrec.error = 3; - } - } // if method = d - - /* -------------------- long period periodics ------------------ */ - if (satrec.method == 'd') - { - sinip = sin(xincp); - cosip = cos(xincp); - satrec.aycof = -0.5*j3oj2*sinip; - // sgp4fix for divide by zero for xincp = 180 deg - if (fabs(cosip+1.0) > 1.5e-12) - satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / (1.0 + cosip); - else - satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / temp4; - } - axnl = ep * cos(argpp); - temp = 1.0 / (am * (1.0 - ep * ep)); - aynl = ep* sin(argpp) + temp * satrec.aycof; - xl = mp + argpp + nodep + temp * satrec.xlcof * axnl; - - /* --------------------- solve kepler's equation --------------- */ - u = fmod(xl - nodep, twopi); - eo1 = u; - tem5 = 9999.9; - ktr = 1; - // sgp4fix for kepler iteration - // the following iteration needs better limits on corrections - while (( fabs(tem5) >= 1.0e-12) && (ktr <= 10) ) - { - sineo1 = sin(eo1); - coseo1 = cos(eo1); - tem5 = 1.0 - coseo1 * axnl - sineo1 * aynl; - tem5 = (u - aynl * coseo1 + axnl * sineo1 - eo1) / tem5; - if(fabs(tem5) >= 0.95) - tem5 = tem5 > 0.0 ? 0.95 : -0.95; - eo1 = eo1 + tem5; - ktr = ktr + 1; - } - - /* ------------- short period preliminary quantities ----------- */ - ecose = axnl*coseo1 + aynl*sineo1; - esine = axnl*sineo1 - aynl*coseo1; - el2 = axnl*axnl + aynl*aynl; - pl = am*(1.0-el2); - if (pl < 0.0) - { -// printf("# error pl %f\n", pl); - satrec.error = 4; - } - else - { - rl = am * (1.0 - ecose); - rdotl = sqrt(am) * esine/rl; - rvdotl = sqrt(pl) / rl; - betal = sqrt(1.0 - el2); - temp = esine / (1.0 + betal); - sinu = am / rl * (sineo1 - aynl - axnl * temp); - cosu = am / rl * (coseo1 - axnl + aynl * temp); - su = atan2(sinu, cosu); - sin2u = (cosu + cosu) * sinu; - cos2u = 1.0 - 2.0 * sinu * sinu; - temp = 1.0 / pl; - temp1 = 0.5 * j2 * temp; - temp2 = temp1 * temp; - - /* -------------- update for short period periodics ------------ */ - if (satrec.method == 'd') - { - cosisq = cosip * cosip; - satrec.con41 = 3.0*cosisq - 1.0; - satrec.x1mth2 = 1.0 - cosisq; - satrec.x7thm1 = 7.0*cosisq - 1.0; - } - mrt = rl * (1.0 - 1.5 * temp2 * betal * satrec.con41) + - 0.5 * temp1 * satrec.x1mth2 * cos2u; - su = su - 0.25 * temp2 * satrec.x7thm1 * sin2u; - xnode = nodep + 1.5 * temp2 * cosip * sin2u; - xinc = xincp + 1.5 * temp2 * cosip * sinip * cos2u; - mvt = rdotl - nm * temp1 * satrec.x1mth2 * sin2u / xke; - rvdot = rvdotl + nm * temp1 * (satrec.x1mth2 * cos2u + - 1.5 * satrec.con41) / xke; - - /* --------------------- orientation vectors ------------------- */ - sinsu = sin(su); - cossu = cos(su); - snod = sin(xnode); - cnod = cos(xnode); - sini = sin(xinc); - cosi = cos(xinc); - xmx = -snod * cosi; - xmy = cnod * cosi; - ux = xmx * sinsu + cnod * cossu; - uy = xmy * sinsu + snod * cossu; - uz = sini * sinsu; - vx = xmx * cossu - cnod * sinsu; - vy = xmy * cossu - snod * sinsu; - vz = sini * cossu; - - /* --------- position and velocity (in km and km/sec) ---------- */ - r[0] = (mrt * ux)* radiusearthkm; - r[1] = (mrt * uy)* radiusearthkm; - r[2] = (mrt * uz)* radiusearthkm; - v[0] = (mvt * ux + rvdot * vx) * vkmpersec; - v[1] = (mvt * uy + rvdot * vy) * vkmpersec; - v[2] = (mvt * uz + rvdot * vz) * vkmpersec; - } // if pl > 0 - - // sgp4fix for decaying satellites - if (mrt < 1.0) - { -// printf("# decay condition %11.6f \n",mrt); - satrec.error = 6; - } - - -//#include "debug7.cpp" - return satrec.error; -} // end sgp4 - - -/* ----------------------------------------------------------------------------- -* -* function gstime -* -* this function finds the greenwich sidereal time. -* -* author : david vallado 719-573-2600 1 mar 2001 -* -* inputs description range / units -* jdut1 - julian date in ut1 days from 4713 bc -* -* outputs : -* gstime - greenwich sidereal time 0 to 2pi rad -* -* locals : -* temp - temporary variable for doubles rad -* tut1 - julian centuries from the -* jan 1, 2000 12 h epoch (ut1) -* -* coupling : -* none -* -* references : -* vallado 2004, 191, eq 3-45 -* --------------------------------------------------------------------------- */ - -double gstime - ( - double jdut1 - ) - { - const double twopi = 2.0 * pi; - const double deg2rad = pi / 180.0; - double temp, tut1; - - tut1 = (jdut1 - 2451545.0) / 36525.0; - temp = -6.2e-6* tut1 * tut1 * tut1 + 0.093104 * tut1 * tut1 + - (876600.0*3600 + 8640184.812866) * tut1 + 67310.54841; // sec - temp = fmod(temp * deg2rad / 240.0, twopi); //360/86400 = 1/240, to deg, to rad - - // ------------------------ check quadrants --------------------- - if (temp < 0.0) - temp += twopi; - - return temp; - } // end gstime - -/* ----------------------------------------------------------------------------- -* -* function getgravconst -* -* this function gets constants for the propagator. note that mu is identified to -* facilitiate comparisons with newer models. the common useage is wgs72. -* -* author : david vallado 719-573-2600 21 jul 2006 -* -* inputs : -* whichconst - which set of constants to use wgs72old, wgs72, wgs84 -* -* outputs : -* tumin - minutes in one time unit -* mu - earth gravitational parameter -* radiusearthkm - radius of the earth in km -* xke - reciprocal of tumin -* j2, j3, j4 - un-normalized zonal harmonic values -* j3oj2 - j3 divided by j2 -* -* locals : -* -* coupling : -* none -* -* references : -* norad spacetrack report #3 -* vallado, crawford, hujsak, kelso 2006 - --------------------------------------------------------------------------- */ - -void getgravconst - ( - gravconsttype whichconst, - double& tumin, - double& mu, - double& radiusearthkm, - double& xke, - double& j2, - double& j3, - double& j4, - double& j3oj2 - ) - { - - switch (whichconst) - { - // -- wgs-72 low precision str#3 constants -- - case wgs72old: - mu = 398600.79964; // in km3 / s2 - radiusearthkm = 6378.135; // km - xke = 0.0743669161; - tumin = 1.0 / xke; - j2 = 0.001082616; - j3 = -0.00000253881; - j4 = -0.00000165597; - j3oj2 = j3 / j2; - break; - // ------------ wgs-72 constants ------------ - case wgs72: - mu = 398600.8; // in km3 / s2 - radiusearthkm = 6378.135; // km - xke = 60.0 / sqrt(radiusearthkm*radiusearthkm*radiusearthkm/mu); - tumin = 1.0 / xke; - j2 = 0.001082616; - j3 = -0.00000253881; - j4 = -0.00000165597; - j3oj2 = j3 / j2; - break; - case wgs84: - // ------------ wgs-84 constants ------------ - mu = 398600.5; // in km3 / s2 - radiusearthkm = 6378.137; // km - xke = 60.0 / sqrt(radiusearthkm*radiusearthkm*radiusearthkm/mu); - tumin = 1.0 / xke; - j2 = 0.00108262998905; - j3 = -0.00000253215306; - j4 = -0.00000161098761; - j3oj2 = j3 / j2; - break; - default: - fprintf(stderr,"unknown gravity option (%d)\n",whichconst); - break; - } - - } // end getgravconst - - - - - +/* ---------------------------------------------------------------- +* +* sgp4unit.cpp +* +* this file contains the sgp4 procedures for analytical propagation +* of a satellite. the code was originally released in the 1980 and 1986 +* spacetrack papers. a detailed discussion of the theory and history +* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, +* and kelso. +* +* companion code for +* fundamentals of astrodynamics and applications +* 2007 +* by david vallado +* +* (w) 719-573-2600, email dvallado@agi.com +* +* current : +* 16 nov 07 david vallado +* misc fixes for better compliance +* changes : +* 20 apr 07 david vallado +* misc fixes for constants +* 11 aug 06 david vallado +* chg lyddane choice back to strn3, constants, misc doc +* 15 dec 05 david vallado +* misc fixes +* 26 jul 05 david vallado +* fixes for paper +* note that each fix is preceded by a +* comment with "sgp4fix" and an explanation of +* what was changed +* 10 aug 04 david vallado +* 2nd printing baseline working +* 14 may 01 david vallado +* 2nd edition baseline +* 80 norad +* original baseline +* ---------------------------------------------------------------- */ + +#include "sgp4unit.h" + +const char help = 'n'; +FILE *dbgfile; + +#define pi 3.14159265358979323846 + + +/* ----------- local functions - only ever used internally by sgp4 ---------- */ +static void dpper + ( + double e3, double ee2, double peo, double pgho, double pho, + double pinco, double plo, double se2, double se3, double sgh2, + double sgh3, double sgh4, double sh2, double sh3, double si2, + double si3, double sl2, double sl3, double sl4, double t, + double xgh2, double xgh3, double xgh4, double xh2, double xh3, + double xi2, double xi3, double xl2, double xl3, double xl4, + double zmol, double zmos, double inclo, + char init, + double& ep, double& inclp, double& nodep, double& argpp, double& mp + ); + +static void dscom + ( + double epoch, double ep, double argpp, double tc, double inclp, + double nodep, double np, + double& snodm, double& cnodm, double& sinim, double& cosim, double& sinomm, + double& cosomm,double& day, double& e3, double& ee2, double& em, + double& emsq, double& gam, double& peo, double& pgho, double& pho, + double& pinco, double& plo, double& rtemsq, double& se2, double& se3, + double& sgh2, double& sgh3, double& sgh4, double& sh2, double& sh3, + double& si2, double& si3, double& sl2, double& sl3, double& sl4, + double& s1, double& s2, double& s3, double& s4, double& s5, + double& s6, double& s7, double& ss1, double& ss2, double& ss3, + double& ss4, double& ss5, double& ss6, double& ss7, double& sz1, + double& sz2, double& sz3, double& sz11, double& sz12, double& sz13, + double& sz21, double& sz22, double& sz23, double& sz31, double& sz32, + double& sz33, double& xgh2, double& xgh3, double& xgh4, double& xh2, + double& xh3, double& xi2, double& xi3, double& xl2, double& xl3, + double& xl4, double& nm, double& z1, double& z2, double& z3, + double& z11, double& z12, double& z13, double& z21, double& z22, + double& z23, double& z31, double& z32, double& z33, double& zmol, + double& zmos + ); + +static void dsinit + ( + gravconsttype whichconst, + double cosim, double emsq, double argpo, double s1, double s2, + double s3, double s4, double s5, double sinim, double ss1, + double ss2, double ss3, double ss4, double ss5, double sz1, + double sz3, double sz11, double sz13, double sz21, double sz23, + double sz31, double sz33, double t, double tc, double gsto, + double mo, double mdot, double no, double nodeo, double nodedot, + double xpidot, double z1, double z3, double z11, double z13, + double z21, double z23, double z31, double z33, double ecco, + double eccsq, double& em, double& argpm, double& inclm, double& mm, + double& nm, double& nodem, + int& irez, + double& atime, double& d2201, double& d2211, double& d3210, double& d3222, + double& d4410, double& d4422, double& d5220, double& d5232, double& d5421, + double& d5433, double& dedt, double& didt, double& dmdt, double& dndt, + double& dnodt, double& domdt, double& del1, double& del2, double& del3, + double& xfact, double& xlamo, double& xli, double& xni + ); + +static void dspace + ( + int irez, + double d2201, double d2211, double d3210, double d3222, double d4410, + double d4422, double d5220, double d5232, double d5421, double d5433, + double dedt, double del1, double del2, double del3, double didt, + double dmdt, double dnodt, double domdt, double argpo, double argpdot, + double t, double tc, double gsto, double xfact, double xlamo, + double no, + double& atime, double& em, double& argpm, double& inclm, double& xli, + double& mm, double& xni, double& nodem, double& dndt, double& nm + ); + +static void initl + ( + int satn, gravconsttype whichconst, + double ecco, double epoch, double inclo, double& no, + char& method, + double& ainv, double& ao, double& con41, double& con42, double& cosio, + double& cosio2,double& eccsq, double& omeosq, double& posq, + double& rp, double& rteosq,double& sinio , double& gsto + ); + +/* ----------------------------------------------------------------------------- +* +* procedure dpper +* +* this procedure provides deep space long period periodic contributions +* to the mean elements. by design, these periodics are zero at epoch. +* this used to be dscom which included initialization, but it's really a +* recurring function. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* e3 - +* ee2 - +* peo - +* pgho - +* pho - +* pinco - +* plo - +* se2 , se3 , sgh2, sgh3, sgh4, sh2, sh3, si2, si3, sl2, sl3, sl4 - +* t - +* xh2, xh3, xi2, xi3, xl2, xl3, xl4 - +* zmol - +* zmos - +* ep - eccentricity 0.0 - 1.0 +* inclo - inclination - needed for lyddane modification +* nodep - right ascension of ascending node +* argpp - argument of perigee +* mp - mean anomaly +* +* outputs : +* ep - eccentricity 0.0 - 1.0 +* inclp - inclination +* nodep - right ascension of ascending node +* argpp - argument of perigee +* mp - mean anomaly +* +* locals : +* alfdp - +* betdp - +* cosip , sinip , cosop , sinop , +* dalf - +* dbet - +* dls - +* f2, f3 - +* pe - +* pgh - +* ph - +* pinc - +* pl - +* sel , ses , sghl , sghs , shl , shs , sil , sinzf , sis , +* sll , sls +* xls - +* xnoh - +* zf - +* zm - +* +* coupling : +* none. +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dpper + ( + double e3, double ee2, double peo, double pgho, double pho, + double pinco, double plo, double se2, double se3, double sgh2, + double sgh3, double sgh4, double sh2, double sh3, double si2, + double si3, double sl2, double sl3, double sl4, double t, + double xgh2, double xgh3, double xgh4, double xh2, double xh3, + double xi2, double xi3, double xl2, double xl3, double xl4, + double zmol, double zmos, double inclo, + char init, + double& ep, double& inclp, double& nodep, double& argpp, double& mp + ) +{ + /* --------------------- local variables ------------------------ */ + const double twopi = 2.0 * pi; + double alfdp, betdp, cosip, cosop, dalf, dbet, dls, + f2, f3, pe, pgh, ph, pinc, pl , + sel, ses, sghl, sghs, shll, shs, sil, + sinip, sinop, sinzf, sis, sll, sls, xls, + xnoh, zf, zm, zel, zes, znl, zns; + + /* ---------------------- constants ----------------------------- */ + zns = 1.19459e-5; + zes = 0.01675; + znl = 1.5835218e-4; + zel = 0.05490; + + /* --------------- calculate time varying periodics ----------- */ + zm = zmos + zns * t; + // be sure that the initial call has time set to zero + if (init == 'y') + zm = zmos; + zf = zm + 2.0 * zes * sin(zm); + sinzf = sin(zf); + f2 = 0.5 * sinzf * sinzf - 0.25; + f3 = -0.5 * sinzf * cos(zf); + ses = se2* f2 + se3 * f3; + sis = si2 * f2 + si3 * f3; + sls = sl2 * f2 + sl3 * f3 + sl4 * sinzf; + sghs = sgh2 * f2 + sgh3 * f3 + sgh4 * sinzf; + shs = sh2 * f2 + sh3 * f3; + zm = zmol + znl * t; + if (init == 'y') + zm = zmol; + zf = zm + 2.0 * zel * sin(zm); + sinzf = sin(zf); + f2 = 0.5 * sinzf * sinzf - 0.25; + f3 = -0.5 * sinzf * cos(zf); + sel = ee2 * f2 + e3 * f3; + sil = xi2 * f2 + xi3 * f3; + sll = xl2 * f2 + xl3 * f3 + xl4 * sinzf; + sghl = xgh2 * f2 + xgh3 * f3 + xgh4 * sinzf; + shll = xh2 * f2 + xh3 * f3; + pe = ses + sel; + pinc = sis + sil; + pl = sls + sll; + pgh = sghs + sghl; + ph = shs + shll; + + if (init == 'n') + { + pe = pe - peo; + pinc = pinc - pinco; + pl = pl - plo; + pgh = pgh - pgho; + ph = ph - pho; + inclp = inclp + pinc; + ep = ep + pe; + sinip = sin(inclp); + cosip = cos(inclp); + + /* ----------------- apply periodics directly ------------ */ + // sgp4fix for lyddane choice + // strn3 used original inclination - this is technically feasible + // gsfc used perturbed inclination - also technically feasible + // probably best to readjust the 0.2 limit value and limit discontinuity + // 0.2 rad = 11.45916 deg + // use next line for original strn3 approach and original inclination + // if (inclo >= 0.2) + // use next line for gsfc version and perturbed inclination + if (inclp >= 0.2) + { + ph = ph / sinip; + pgh = pgh - cosip * ph; + argpp = argpp + pgh; + nodep = nodep + ph; + mp = mp + pl; + } + else + { + /* ---- apply periodics with lyddane modification ---- */ + sinop = sin(nodep); + cosop = cos(nodep); + alfdp = sinip * sinop; + betdp = sinip * cosop; + dalf = ph * cosop + pinc * cosip * sinop; + dbet = -ph * sinop + pinc * cosip * cosop; + alfdp = alfdp + dalf; + betdp = betdp + dbet; + nodep = fmod(nodep, twopi); + // sgp4fix for afspc written intrinsic functions + // nodep used without a trigonometric function ahead + if (nodep < 0.0) + nodep = nodep + twopi; + xls = mp + argpp + cosip * nodep; + dls = pl + pgh - pinc * nodep * sinip; + xls = xls + dls; + xnoh = nodep; + nodep = atan2(alfdp, betdp); + // sgp4fix for afspc written intrinsic functions + // nodep used without a trigonometric function ahead + if (nodep < 0.0) + nodep = nodep + twopi; + if (fabs(xnoh - nodep) > pi){ + if (nodep < xnoh) + nodep = nodep + twopi; + else + nodep = nodep - twopi; + } + mp = mp + pl; + argpp = xls - mp - cosip * nodep; + } + } // if init == 'n' + +//#include "debug1.cpp" +} // end dpper + +/*----------------------------------------------------------------------------- +* +* procedure dscom +* +* this procedure provides deep space common items used by both the secular +* and periodics subroutines. input is provided as shown. this routine +* used to be called dpper, but the functions inside weren't well organized. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* epoch - +* ep - eccentricity +* argpp - argument of perigee +* tc - +* inclp - inclination +* nodep - right ascension of ascending node +* np - mean motion +* +* outputs : +* sinim , cosim , sinomm , cosomm , snodm , cnodm +* day - +* e3 - +* ee2 - +* em - eccentricity +* emsq - eccentricity squared +* gam - +* peo - +* pgho - +* pho - +* pinco - +* plo - +* rtemsq - +* se2, se3 - +* sgh2, sgh3, sgh4 - +* sh2, sh3, si2, si3, sl2, sl3, sl4 - +* s1, s2, s3, s4, s5, s6, s7 - +* ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3 - +* sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33 - +* xgh2, xgh3, xgh4, xh2, xh3, xi2, xi3, xl2, xl3, xl4 - +* nm - mean motion +* z1, z2, z3, z11, z12, z13, z21, z22, z23, z31, z32, z33 - +* zmol - +* zmos - +* +* locals : +* a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 - +* betasq - +* cc - +* ctem, stem - +* x1, x2, x3, x4, x5, x6, x7, x8 - +* xnodce - +* xnoi - +* zcosg , zsing , zcosgl , zsingl , zcosh , zsinh , zcoshl , zsinhl , +* zcosi , zsini , zcosil , zsinil , +* zx - +* zy - +* +* coupling : +* none. +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dscom + ( + double epoch, double ep, double argpp, double tc, double inclp, + double nodep, double np, + double& snodm, double& cnodm, double& sinim, double& cosim, double& sinomm, + double& cosomm,double& day, double& e3, double& ee2, double& em, + double& emsq, double& gam, double& peo, double& pgho, double& pho, + double& pinco, double& plo, double& rtemsq, double& se2, double& se3, + double& sgh2, double& sgh3, double& sgh4, double& sh2, double& sh3, + double& si2, double& si3, double& sl2, double& sl3, double& sl4, + double& s1, double& s2, double& s3, double& s4, double& s5, + double& s6, double& s7, double& ss1, double& ss2, double& ss3, + double& ss4, double& ss5, double& ss6, double& ss7, double& sz1, + double& sz2, double& sz3, double& sz11, double& sz12, double& sz13, + double& sz21, double& sz22, double& sz23, double& sz31, double& sz32, + double& sz33, double& xgh2, double& xgh3, double& xgh4, double& xh2, + double& xh3, double& xi2, double& xi3, double& xl2, double& xl3, + double& xl4, double& nm, double& z1, double& z2, double& z3, + double& z11, double& z12, double& z13, double& z21, double& z22, + double& z23, double& z31, double& z32, double& z33, double& zmol, + double& zmos + ) +{ + /* -------------------------- constants ------------------------- */ + const double zes = 0.01675; + const double zel = 0.05490; + const double c1ss = 2.9864797e-6; + const double c1l = 4.7968065e-7; + const double zsinis = 0.39785416; + const double zcosis = 0.91744867; + const double zcosgs = 0.1945905; + const double zsings = -0.98088458; + const double twopi = 2.0 * pi; + + /* --------------------- local variables ------------------------ */ + int lsflg; + double a1 , a2 , a3 , a4 , a5 , a6 , a7 , + a8 , a9 , a10 , betasq, cc , ctem , stem , + x1 , x2 , x3 , x4 , x5 , x6 , x7 , + x8 , xnodce, xnoi , zcosg , zcosgl, zcosh , zcoshl, + zcosi , zcosil, zsing , zsingl, zsinh , zsinhl, zsini , + zsinil, zx , zy; + + nm = np; + em = ep; + snodm = sin(nodep); + cnodm = cos(nodep); + sinomm = sin(argpp); + cosomm = cos(argpp); + sinim = sin(inclp); + cosim = cos(inclp); + emsq = em * em; + betasq = 1.0 - emsq; + rtemsq = sqrt(betasq); + + /* ----------------- initialize lunar solar terms --------------- */ + peo = 0.0; + pinco = 0.0; + plo = 0.0; + pgho = 0.0; + pho = 0.0; + day = epoch + 18261.5 + tc / 1440.0; + xnodce = fmod(4.5236020 - 9.2422029e-4 * day, twopi); + stem = sin(xnodce); + ctem = cos(xnodce); + zcosil = 0.91375164 - 0.03568096 * ctem; + zsinil = sqrt(1.0 - zcosil * zcosil); + zsinhl = 0.089683511 * stem / zsinil; + zcoshl = sqrt(1.0 - zsinhl * zsinhl); + gam = 5.8351514 + 0.0019443680 * day; + zx = 0.39785416 * stem / zsinil; + zy = zcoshl * ctem + 0.91744867 * zsinhl * stem; + zx = atan2(zx, zy); + zx = gam + zx - xnodce; + zcosgl = cos(zx); + zsingl = sin(zx); + + /* ------------------------- do solar terms --------------------- */ + zcosg = zcosgs; + zsing = zsings; + zcosi = zcosis; + zsini = zsinis; + zcosh = cnodm; + zsinh = snodm; + cc = c1ss; + xnoi = 1.0 / nm; + + for (lsflg = 1; lsflg <= 2; lsflg++) + { + a1 = zcosg * zcosh + zsing * zcosi * zsinh; + a3 = -zsing * zcosh + zcosg * zcosi * zsinh; + a7 = -zcosg * zsinh + zsing * zcosi * zcosh; + a8 = zsing * zsini; + a9 = zsing * zsinh + zcosg * zcosi * zcosh; + a10 = zcosg * zsini; + a2 = cosim * a7 + sinim * a8; + a4 = cosim * a9 + sinim * a10; + a5 = -sinim * a7 + cosim * a8; + a6 = -sinim * a9 + cosim * a10; + + x1 = a1 * cosomm + a2 * sinomm; + x2 = a3 * cosomm + a4 * sinomm; + x3 = -a1 * sinomm + a2 * cosomm; + x4 = -a3 * sinomm + a4 * cosomm; + x5 = a5 * sinomm; + x6 = a6 * sinomm; + x7 = a5 * cosomm; + x8 = a6 * cosomm; + + z31 = 12.0 * x1 * x1 - 3.0 * x3 * x3; + z32 = 24.0 * x1 * x2 - 6.0 * x3 * x4; + z33 = 12.0 * x2 * x2 - 3.0 * x4 * x4; + z1 = 3.0 * (a1 * a1 + a2 * a2) + z31 * emsq; + z2 = 6.0 * (a1 * a3 + a2 * a4) + z32 * emsq; + z3 = 3.0 * (a3 * a3 + a4 * a4) + z33 * emsq; + z11 = -6.0 * a1 * a5 + emsq * (-24.0 * x1 * x7-6.0 * x3 * x5); + z12 = -6.0 * (a1 * a6 + a3 * a5) + emsq * + (-24.0 * (x2 * x7 + x1 * x8) - 6.0 * (x3 * x6 + x4 * x5)); + z13 = -6.0 * a3 * a6 + emsq * (-24.0 * x2 * x8 - 6.0 * x4 * x6); + z21 = 6.0 * a2 * a5 + emsq * (24.0 * x1 * x5 - 6.0 * x3 * x7); + z22 = 6.0 * (a4 * a5 + a2 * a6) + emsq * + (24.0 * (x2 * x5 + x1 * x6) - 6.0 * (x4 * x7 + x3 * x8)); + z23 = 6.0 * a4 * a6 + emsq * (24.0 * x2 * x6 - 6.0 * x4 * x8); + z1 = z1 + z1 + betasq * z31; + z2 = z2 + z2 + betasq * z32; + z3 = z3 + z3 + betasq * z33; + s3 = cc * xnoi; + s2 = -0.5 * s3 / rtemsq; + s4 = s3 * rtemsq; + s1 = -15.0 * em * s4; + s5 = x1 * x3 + x2 * x4; + s6 = x2 * x3 + x1 * x4; + s7 = x2 * x4 - x1 * x3; + + /* ----------------------- do lunar terms ------------------- */ + if (lsflg == 1) + { + ss1 = s1; + ss2 = s2; + ss3 = s3; + ss4 = s4; + ss5 = s5; + ss6 = s6; + ss7 = s7; + sz1 = z1; + sz2 = z2; + sz3 = z3; + sz11 = z11; + sz12 = z12; + sz13 = z13; + sz21 = z21; + sz22 = z22; + sz23 = z23; + sz31 = z31; + sz32 = z32; + sz33 = z33; + zcosg = zcosgl; + zsing = zsingl; + zcosi = zcosil; + zsini = zsinil; + zcosh = zcoshl * cnodm + zsinhl * snodm; + zsinh = snodm * zcoshl - cnodm * zsinhl; + cc = c1l; + } + } + + zmol = fmod(4.7199672 + 0.22997150 * day - gam, twopi); + zmos = fmod(6.2565837 + 0.017201977 * day, twopi); + + /* ------------------------ do solar terms ---------------------- */ + se2 = 2.0 * ss1 * ss6; + se3 = 2.0 * ss1 * ss7; + si2 = 2.0 * ss2 * sz12; + si3 = 2.0 * ss2 * (sz13 - sz11); + sl2 = -2.0 * ss3 * sz2; + sl3 = -2.0 * ss3 * (sz3 - sz1); + sl4 = -2.0 * ss3 * (-21.0 - 9.0 * emsq) * zes; + sgh2 = 2.0 * ss4 * sz32; + sgh3 = 2.0 * ss4 * (sz33 - sz31); + sgh4 = -18.0 * ss4 * zes; + sh2 = -2.0 * ss2 * sz22; + sh3 = -2.0 * ss2 * (sz23 - sz21); + + /* ------------------------ do lunar terms ---------------------- */ + ee2 = 2.0 * s1 * s6; + e3 = 2.0 * s1 * s7; + xi2 = 2.0 * s2 * z12; + xi3 = 2.0 * s2 * (z13 - z11); + xl2 = -2.0 * s3 * z2; + xl3 = -2.0 * s3 * (z3 - z1); + xl4 = -2.0 * s3 * (-21.0 - 9.0 * emsq) * zel; + xgh2 = 2.0 * s4 * z32; + xgh3 = 2.0 * s4 * (z33 - z31); + xgh4 = -18.0 * s4 * zel; + xh2 = -2.0 * s2 * z22; + xh3 = -2.0 * s2 * (z23 - z21); + +//#include "debug2.cpp" +} // end dscom + +/*----------------------------------------------------------------------------- +* +* procedure dsinit +* +* this procedure provides deep space contributions to mean motion dot due +* to geopotential resonance with half day and one day orbits. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* cosim, sinim- +* emsq - eccentricity squared +* argpo - argument of perigee +* s1, s2, s3, s4, s5 - +* ss1, ss2, ss3, ss4, ss5 - +* sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33 - +* t - time +* tc - +* gsto - greenwich sidereal time rad +* mo - mean anomaly +* mdot - mean anomaly dot (rate) +* no - mean motion +* nodeo - right ascension of ascending node +* nodedot - right ascension of ascending node dot (rate) +* xpidot - +* z1, z3, z11, z13, z21, z23, z31, z33 - +* eccm - eccentricity +* argpm - argument of perigee +* inclm - inclination +* mm - mean anomaly +* xn - mean motion +* nodem - right ascension of ascending node +* +* outputs : +* em - eccentricity +* argpm - argument of perigee +* inclm - inclination +* mm - mean anomaly +* nm - mean motion +* nodem - right ascension of ascending node +* irez - flag for resonance 0-none, 1-one day, 2-half day +* atime - +* d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 - +* dedt - +* didt - +* dmdt - +* dndt - +* dnodt - +* domdt - +* del1, del2, del3 - +* ses , sghl , sghs , sgs , shl , shs , sis , sls +* theta - +* xfact - +* xlamo - +* xli - +* xni +* +* locals : +* ainv2 - +* aonv - +* cosisq - +* eoc - +* f220, f221, f311, f321, f322, f330, f441, f442, f522, f523, f542, f543 - +* g200, g201, g211, g300, g310, g322, g410, g422, g520, g521, g532, g533 - +* sini2 - +* temp - +* temp1 - +* theta - +* xno2 - +* +* coupling : +* getgravconst +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dsinit + ( + gravconsttype whichconst, + double cosim, double emsq, double argpo, double s1, double s2, + double s3, double s4, double s5, double sinim, double ss1, + double ss2, double ss3, double ss4, double ss5, double sz1, + double sz3, double sz11, double sz13, double sz21, double sz23, + double sz31, double sz33, double t, double tc, double gsto, + double mo, double mdot, double no, double nodeo, double nodedot, + double xpidot, double z1, double z3, double z11, double z13, + double z21, double z23, double z31, double z33, double ecco, + double eccsq, double& em, double& argpm, double& inclm, double& mm, + double& nm, double& nodem, + int& irez, + double& atime, double& d2201, double& d2211, double& d3210, double& d3222, + double& d4410, double& d4422, double& d5220, double& d5232, double& d5421, + double& d5433, double& dedt, double& didt, double& dmdt, double& dndt, + double& dnodt, double& domdt, double& del1, double& del2, double& del3, + double& xfact, double& xlamo, double& xli, double& xni + ) +{ + /* --------------------- local variables ------------------------ */ + const double twopi = 2.0 * pi; + + double ainv2 , aonv=0.0, cosisq, eoc, f220 , f221 , f311 , + f321 , f322 , f330 , f441 , f442 , f522 , f523 , + f542 , f543 , g200 , g201 , g211 , g300 , g310 , + g322 , g410 , g422 , g520 , g521 , g532 , g533 , + ses , sgs , sghl , sghs , shs , shll , sis , + sini2 , sls , temp , temp1 , theta , xno2 , q22 , + q31 , q33 , root22, root44, root54, rptim , root32, + root52, x2o3 , xke , znl , emo , zns , emsqo, + tumin, mu, radiusearthkm, j2, j3, j4, j3oj2; + + q22 = 1.7891679e-6; + q31 = 2.1460748e-6; + q33 = 2.2123015e-7; + root22 = 1.7891679e-6; + root44 = 7.3636953e-9; + root54 = 2.1765803e-9; + rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec + root32 = 3.7393792e-7; + root52 = 1.1428639e-7; + x2o3 = 2.0 / 3.0; + znl = 1.5835218e-4; + zns = 1.19459e-5; + + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + + /* -------------------- deep space initialization ------------ */ + irez = 0; + if ((nm < 0.0052359877) && (nm > 0.0034906585)) + irez = 1; + if ((nm >= 8.26e-3) && (nm <= 9.24e-3) && (em >= 0.5)) + irez = 2; + + /* ------------------------ do solar terms ------------------- */ + ses = ss1 * zns * ss5; + sis = ss2 * zns * (sz11 + sz13); + sls = -zns * ss3 * (sz1 + sz3 - 14.0 - 6.0 * emsq); + sghs = ss4 * zns * (sz31 + sz33 - 6.0); + shs = -zns * ss2 * (sz21 + sz23); + // sgp4fix for 180 deg incl + if ((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2)) + shs = 0.0; + if (sinim != 0.0) + shs = shs / sinim; + sgs = sghs - cosim * shs; + + /* ------------------------- do lunar terms ------------------ */ + dedt = ses + s1 * znl * s5; + didt = sis + s2 * znl * (z11 + z13); + dmdt = sls - znl * s3 * (z1 + z3 - 14.0 - 6.0 * emsq); + sghl = s4 * znl * (z31 + z33 - 6.0); + shll = -znl * s2 * (z21 + z23); + // sgp4fix for 180 deg incl + if ((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2)) + shll = 0.0; + domdt = sgs + sghl; + dnodt = shs; + if (sinim != 0.0) + { + domdt = domdt - cosim / sinim * shll; + dnodt = dnodt + shll / sinim; + } + + /* ----------- calculate deep space resonance effects -------- */ + dndt = 0.0; + theta = fmod(gsto + tc * rptim, twopi); + em = em + dedt * t; + inclm = inclm + didt * t; + argpm = argpm + domdt * t; + nodem = nodem + dnodt * t; + mm = mm + dmdt * t; + // sgp4fix for negative inclinations + // the following if statement should be commented out + //if (inclm < 0.0) + // { + // inclm = -inclm; + // argpm = argpm - pi; + // nodem = nodem + pi; + // } + + /* -------------- initialize the resonance terms ------------- */ + if (irez != 0) + { + aonv = pow(nm / xke, x2o3); + + /* ---------- geopotential resonance for 12 hour orbits ------ */ + if (irez == 2) + { + cosisq = cosim * cosim; + emo = em; + em = ecco; + emsqo = emsq; + emsq = eccsq; + eoc = em * emsq; + g201 = -0.306 - (em - 0.64) * 0.440; + + if (em <= 0.65) + { + g211 = 3.616 - 13.2470 * em + 16.2900 * emsq; + g310 = -19.302 + 117.3900 * em - 228.4190 * emsq + 156.5910 * eoc; + g322 = -18.9068 + 109.7927 * em - 214.6334 * emsq + 146.5816 * eoc; + g410 = -41.122 + 242.6940 * em - 471.0940 * emsq + 313.9530 * eoc; + g422 = -146.407 + 841.8800 * em - 1629.014 * emsq + 1083.4350 * eoc; + g520 = -532.114 + 3017.977 * em - 5740.032 * emsq + 3708.2760 * eoc; + } + else + { + g211 = -72.099 + 331.819 * em - 508.738 * emsq + 266.724 * eoc; + g310 = -346.844 + 1582.851 * em - 2415.925 * emsq + 1246.113 * eoc; + g322 = -342.585 + 1554.908 * em - 2366.899 * emsq + 1215.972 * eoc; + g410 = -1052.797 + 4758.686 * em - 7193.992 * emsq + 3651.957 * eoc; + g422 = -3581.690 + 16178.110 * em - 24462.770 * emsq + 12422.520 * eoc; + if (em > 0.715) + g520 =-5149.66 + 29936.92 * em - 54087.36 * emsq + 31324.56 * eoc; + else + g520 = 1464.74 - 4664.75 * em + 3763.64 * emsq; + } + if (em < 0.7) + { + g533 = -919.22770 + 4988.6100 * em - 9064.7700 * emsq + 5542.21 * eoc; + g521 = -822.71072 + 4568.6173 * em - 8491.4146 * emsq + 5337.524 * eoc; + g532 = -853.66600 + 4690.2500 * em - 8624.7700 * emsq + 5341.4 * eoc; + } + else + { + g533 =-37995.780 + 161616.52 * em - 229838.20 * emsq + 109377.94 * eoc; + g521 =-51752.104 + 218913.95 * em - 309468.16 * emsq + 146349.42 * eoc; + g532 =-40023.880 + 170470.89 * em - 242699.48 * emsq + 115605.82 * eoc; + } + + sini2= sinim * sinim; + f220 = 0.75 * (1.0 + 2.0 * cosim+cosisq); + f221 = 1.5 * sini2; + f321 = 1.875 * sinim * (1.0 - 2.0 * cosim - 3.0 * cosisq); + f322 = -1.875 * sinim * (1.0 + 2.0 * cosim - 3.0 * cosisq); + f441 = 35.0 * sini2 * f220; + f442 = 39.3750 * sini2 * sini2; + f522 = 9.84375 * sinim * (sini2 * (1.0 - 2.0 * cosim- 5.0 * cosisq) + + 0.33333333 * (-2.0 + 4.0 * cosim + 6.0 * cosisq) ); + f523 = sinim * (4.92187512 * sini2 * (-2.0 - 4.0 * cosim + + 10.0 * cosisq) + 6.56250012 * (1.0+2.0 * cosim - 3.0 * cosisq)); + f542 = 29.53125 * sinim * (2.0 - 8.0 * cosim+cosisq * + (-12.0 + 8.0 * cosim + 10.0 * cosisq)); + f543 = 29.53125 * sinim * (-2.0 - 8.0 * cosim+cosisq * + (12.0 + 8.0 * cosim - 10.0 * cosisq)); + xno2 = nm * nm; + ainv2 = aonv * aonv; + temp1 = 3.0 * xno2 * ainv2; + temp = temp1 * root22; + d2201 = temp * f220 * g201; + d2211 = temp * f221 * g211; + temp1 = temp1 * aonv; + temp = temp1 * root32; + d3210 = temp * f321 * g310; + d3222 = temp * f322 * g322; + temp1 = temp1 * aonv; + temp = 2.0 * temp1 * root44; + d4410 = temp * f441 * g410; + d4422 = temp * f442 * g422; + temp1 = temp1 * aonv; + temp = temp1 * root52; + d5220 = temp * f522 * g520; + d5232 = temp * f523 * g532; + temp = 2.0 * temp1 * root54; + d5421 = temp * f542 * g521; + d5433 = temp * f543 * g533; + xlamo = fmod(mo + nodeo + nodeo-theta - theta, twopi); + xfact = mdot + dmdt + 2.0 * (nodedot + dnodt - rptim) - no; + em = emo; + emsq = emsqo; + } + + /* ---------------- synchronous resonance terms -------------- */ + if (irez == 1) + { + g200 = 1.0 + emsq * (-2.5 + 0.8125 * emsq); + g310 = 1.0 + 2.0 * emsq; + g300 = 1.0 + emsq * (-6.0 + 6.60937 * emsq); + f220 = 0.75 * (1.0 + cosim) * (1.0 + cosim); + f311 = 0.9375 * sinim * sinim * (1.0 + 3.0 * cosim) - 0.75 * (1.0 + cosim); + f330 = 1.0 + cosim; + f330 = 1.875 * f330 * f330 * f330; + del1 = 3.0 * nm * nm * aonv * aonv; + del2 = 2.0 * del1 * f220 * g200 * q22; + del3 = 3.0 * del1 * f330 * g300 * q33 * aonv; + del1 = del1 * f311 * g310 * q31 * aonv; + xlamo = fmod(mo + nodeo + argpo - theta, twopi); + xfact = mdot + xpidot - rptim + dmdt + domdt + dnodt - no; + } + + /* ------------ for sgp4, initialize the integrator ---------- */ + xli = xlamo; + xni = no; + atime = 0.0; + nm = no + dndt; + } + +//#include "debug3.cpp" +} // end dsinit + +/*----------------------------------------------------------------------------- +* +* procedure dspace +* +* this procedure provides deep space contributions to mean elements for +* perturbing third body. these effects have been averaged over one +* revolution of the sun and moon. for earth resonance effects, the +* effects have been averaged over no revolutions of the satellite. +* (mean motion) +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 - +* dedt - +* del1, del2, del3 - +* didt - +* dmdt - +* dnodt - +* domdt - +* irez - flag for resonance 0-none, 1-one day, 2-half day +* argpo - argument of perigee +* argpdot - argument of perigee dot (rate) +* t - time +* tc - +* gsto - gst +* xfact - +* xlamo - +* no - mean motion +* atime - +* em - eccentricity +* ft - +* argpm - argument of perigee +* inclm - inclination +* xli - +* mm - mean anomaly +* xni - mean motion +* nodem - right ascension of ascending node +* +* outputs : +* atime - +* em - eccentricity +* argpm - argument of perigee +* inclm - inclination +* xli - +* mm - mean anomaly +* xni - +* nodem - right ascension of ascending node +* dndt - +* nm - mean motion +* +* locals : +* delt - +* ft - +* theta - +* x2li - +* x2omi - +* xl - +* xldot - +* xnddt - +* xndt - +* xomi - +* +* coupling : +* none - +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dspace + ( + int irez, + double d2201, double d2211, double d3210, double d3222, double d4410, + double d4422, double d5220, double d5232, double d5421, double d5433, + double dedt, double del1, double del2, double del3, double didt, + double dmdt, double dnodt, double domdt, double argpo, double argpdot, + double t, double tc, double gsto, double xfact, double xlamo, + double no, + double& atime, double& em, double& argpm, double& inclm, double& xli, + double& mm, double& xni, double& nodem, double& dndt, double& nm + ) +{ + const double twopi = 2.0 * pi; + int iretn , iret; + double delt, ft, theta, x2li, x2omi, xl, xldot , xnddt, xndt, xomi, g22, g32, + g44, g52, g54, fasx2, fasx4, fasx6, rptim , step2, stepn , stepp; + + ft = 0.0; + fasx2 = 0.13130908; + fasx4 = 2.8843198; + fasx6 = 0.37448087; + g22 = 5.7686396; + g32 = 0.95240898; + g44 = 1.8014998; + g52 = 1.0508330; + g54 = 4.4108898; + rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec + stepp = 720.0; + stepn = -720.0; + step2 = 259200.0; + + /* ----------- calculate deep space resonance effects ----------- */ + dndt = 0.0; + theta = fmod(gsto + tc * rptim, twopi); + em = em + dedt * t; + + inclm = inclm + didt * t; + argpm = argpm + domdt * t; + nodem = nodem + dnodt * t; + mm = mm + dmdt * t; + + // sgp4fix for negative inclinations + // the following if statement should be commented out + // if (inclm < 0.0) + // { + // inclm = -inclm; + // argpm = argpm - pi; + // nodem = nodem + pi; + // } + + /* - update resonances : numerical (euler-maclaurin) integration - */ + /* ------------------------- epoch restart ---------------------- */ + // sgp4fix for propagator problems + // the following integration works for negative time steps and periods + // the specific changes are unknown because the original code was so convoluted + + ft = 0.0; + atime = 0.0; + if (irez != 0) + { + if ((atime == 0.0) || ((t >= 0.0) && (atime < 0.0)) || + ((t < 0.0) && (atime >= 0.0))) + { + if (t >= 0.0) + delt = stepp; + else + delt = stepn; + atime = 0.0; + xni = no; + xli = xlamo; + } + iretn = 381; // added for do loop + iret = 0; // added for loop + while (iretn == 381) + { + if ((fabs(t) < fabs(atime)) || (iret == 351)) + { + if (t >= 0.0) + delt = stepn; + else + delt = stepp; + iret = 351; + iretn = 381; + } + else + { + if (t > 0.0) // error if prev if has atime:=0.0 and t:=0.0 (ge) + delt = stepp; + else + delt = stepn; + if (fabs(t - atime) >= stepp) + { + iret = 0; + iretn = 381; + } + else + { + ft = t - atime; + iretn = 0; + } + } + + /* ------------------- dot terms calculated ------------- */ + /* ----------- near - synchronous resonance terms ------- */ + if (irez != 2) + { + xndt = del1 * sin(xli - fasx2) + del2 * sin(2.0 * (xli - fasx4)) + + del3 * sin(3.0 * (xli - fasx6)); + xldot = xni + xfact; + xnddt = del1 * cos(xli - fasx2) + + 2.0 * del2 * cos(2.0 * (xli - fasx4)) + + 3.0 * del3 * cos(3.0 * (xli - fasx6)); + xnddt = xnddt * xldot; + } + else + { + /* --------- near - half-day resonance terms -------- */ + xomi = argpo + argpdot * atime; + x2omi = xomi + xomi; + x2li = xli + xli; + xndt = d2201 * sin(x2omi + xli - g22) + d2211 * sin(xli - g22) + + d3210 * sin(xomi + xli - g32) + d3222 * sin(-xomi + xli - g32)+ + d4410 * sin(x2omi + x2li - g44)+ d4422 * sin(x2li - g44) + + d5220 * sin(xomi + xli - g52) + d5232 * sin(-xomi + xli - g52)+ + d5421 * sin(xomi + x2li - g54) + d5433 * sin(-xomi + x2li - g54); + xldot = xni + xfact; + xnddt = d2201 * cos(x2omi + xli - g22) + d2211 * cos(xli - g22) + + d3210 * cos(xomi + xli - g32) + d3222 * cos(-xomi + xli - g32) + + d5220 * cos(xomi + xli - g52) + d5232 * cos(-xomi + xli - g52) + + 2.0 * (d4410 * cos(x2omi + x2li - g44) + + d4422 * cos(x2li - g44) + d5421 * cos(xomi + x2li - g54) + + d5433 * cos(-xomi + x2li - g54)); + xnddt = xnddt * xldot; + } + + /* ----------------------- integrator ------------------- */ + if (iretn == 381) + { + xli = xli + xldot * delt + xndt * step2; + xni = xni + xndt * delt + xnddt * step2; + atime = atime + delt; + } + } // while iretn = 381 + + nm = xni + xndt * ft + xnddt * ft * ft * 0.5; + xl = xli + xldot * ft + xndt * ft * ft * 0.5; + if (irez != 1) + { + mm = xl - 2.0 * nodem + 2.0 * theta; + dndt = nm - no; + } + else + { + mm = xl - nodem - argpm + theta; + dndt = nm - no; + } + nm = no + dndt; + } + +//#include "debug4.cpp" +} // end dsspace + +/*----------------------------------------------------------------------------- +* +* procedure initl +* +* this procedure initializes the spg4 propagator. all the initialization is +* consolidated here instead of having multiple loops inside other routines. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* ecco - eccentricity 0.0 - 1.0 +* epoch - epoch time in days from jan 0, 1950. 0 hr +* inclo - inclination of satellite +* no - mean motion of satellite +* satn - satellite number +* +* outputs : +* ainv - 1.0 / a +* ao - semi major axis +* con41 - +* con42 - 1.0 - 5.0 cos(i) +* cosio - cosine of inclination +* cosio2 - cosio squared +* eccsq - eccentricity squared +* method - flag for deep space 'd', 'n' +* omeosq - 1.0 - ecco * ecco +* posq - semi-parameter squared +* rp - radius of perigee +* rteosq - square root of (1.0 - ecco*ecco) +* sinio - sine of inclination +* gsto - gst at time of observation rad +* no - mean motion of satellite +* +* locals : +* ak - +* d1 - +* del - +* adel - +* po - +* +* coupling : +* getgravconst +* gstime - find greenwich sidereal time from the julian date +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void initl + ( + int satn, gravconsttype whichconst, + double ecco, double epoch, double inclo, double& no, + char& method, + double& ainv, double& ao, double& con41, double& con42, double& cosio, + double& cosio2,double& eccsq, double& omeosq, double& posq, + double& rp, double& rteosq,double& sinio , double& gsto + ) +{ + /* --------------------- local variables ------------------------ */ + double ak, d1, del, adel, po, x2o3, j2, xke, + tumin, mu, radiusearthkm, j3, j4, j3oj2; + + // sgp4fix use old way of finding gst + int ids70; + double ts70, ds70, tfrac, c1, thgr70, fk5r, c1p2p; + const double twopi = 2.0 * pi; + + /* ----------------------- earth constants ---------------------- */ + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + x2o3 = 2.0 / 3.0; + + /* ------------- calculate auxillary epoch quantities ---------- */ + eccsq = ecco * ecco; + omeosq = 1.0 - eccsq; + rteosq = sqrt(omeosq); + cosio = cos(inclo); + cosio2 = cosio * cosio; + + /* ------------------ un-kozai the mean motion ----------------- */ + ak = pow(xke / no, x2o3); + d1 = 0.75 * j2 * (3.0 * cosio2 - 1.0) / (rteosq * omeosq); + del = d1 / (ak * ak); + adel = ak * (1.0 - del * del - del * + (1.0 / 3.0 + 134.0 * del * del / 81.0)); + del = d1/(adel * adel); + no = no / (1.0 + del); + + ao = pow(xke / no, x2o3); + sinio = sin(inclo); + po = ao * omeosq; + con42 = 1.0 - 5.0 * cosio2; + con41 = -con42-cosio2-cosio2; + ainv = 1.0 / ao; + posq = po * po; + rp = ao * (1.0 - ecco); + method = 'n'; + + // sgp4fix modern approach to finding sidereal timew + // gsto = gstime(epoch + 2433281.5); + + // sgp4fix use old way of finding gst + // count integer number of days from 0 jan 1970 + ts70 = epoch - 7305.0; + ids70 = floor(ts70 + 1.0e-8); + ds70 = ids70; + tfrac = ts70 - ds70; + // find greenwich location at epoch + c1 = 1.72027916940703639e-2; + thgr70= 1.7321343856509374; + fk5r = 5.07551419432269442e-15; + c1p2p = c1 + twopi; + gsto = fmod( thgr70 + c1*ds70 + c1p2p*tfrac + ts70*ts70*fk5r, twopi); + if ( gsto < 0.0 ) + gsto = gsto + twopi; + +//#include "debug5.cpp" +} // end initl + +/*----------------------------------------------------------------------------- +* +* procedure sgp4init +* +* this procedure initializes variables for sgp4. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* satn - satellite number +* bstar - sgp4 type drag coefficient kg/m2er +* ecco - eccentricity +* epoch - epoch time in days from jan 0, 1950. 0 hr +* argpo - argument of perigee (output if ds) +* inclo - inclination +* mo - mean anomaly (output if ds) +* no - mean motion +* nodeo - right ascension of ascending node +* +* outputs : +* satrec - common values for subsequent calls +* return code - non-zero on error. +* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er +* 2 - mean motion less than 0.0 +* 3 - pert elements, ecc < 0.0 or ecc > 1.0 +* 4 - semi-latus rectum < 0.0 +* 5 - epoch elements are sub-orbital +* 6 - satellite has decayed +* +* locals : +* cnodm , snodm , cosim , sinim , cosomm , sinomm +* cc1sq , cc2 , cc3 +* coef , coef1 +* cosio4 - +* day - +* dndt - +* em - eccentricity +* emsq - eccentricity squared +* eeta - +* etasq - +* gam - +* argpm - argument of perigee +* nodem - +* inclm - inclination +* mm - mean anomaly +* nm - mean motion +* perige - perigee +* pinvsq - +* psisq - +* qzms24 - +* rtemsq - +* s1, s2, s3, s4, s5, s6, s7 - +* sfour - +* ss1, ss2, ss3, ss4, ss5, ss6, ss7 - +* sz1, sz2, sz3 +* sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33 - +* tc - +* temp - +* temp1, temp2, temp3 - +* tsi - +* xpidot - +* xhdot1 - +* z1, z2, z3 - +* z11, z12, z13, z21, z22, z23, z31, z32, z33 - +* +* coupling : +* getgravconst- +* initl - +* dscom - +* dpper - +* dsinit - +* sgp4 - +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +int sgp4init + ( + gravconsttype whichconst, const int satn, const double epoch, + const double xbstar, const double xecco, const double xargpo, + const double xinclo, const double xmo, const double xno, + const double xnodeo, elsetrec& satrec + ) +{ + /* --------------------- local variables ------------------------ */ + double ao, ainv, con42, cosio, sinio, cosio2, eccsq, + omeosq, posq, rp, rteosq, + cnodm , snodm , cosim , sinim , cosomm, sinomm, cc1sq , + cc2 , cc3 , coef , coef1 , cosio4, day , dndt , + em , emsq , eeta , etasq , gam , argpm , nodem , + inclm , mm , nm , perige, pinvsq, psisq , qzms24, + rtemsq, s1 , s2 , s3 , s4 , s5 , s6 , + s7 , sfour , ss1 = 0 , ss2 = 0 , ss3 = 0 , ss4 = 0 , ss5 = 0 , + ss6 = 0 , ss7 = 0 , sz1 = 0 , sz2 = 0 , sz3 = 0 , sz11 = 0 , sz12 = 0 , + sz13 = 0 , sz21 = 0 , sz22 = 0 , sz23 = 0 , sz31 = 0 , sz32 = 0 , sz33 = 0 , + tc , temp , temp1 , temp2 , temp3 , tsi , xpidot, + xhdot1, z1 , z2 , z3 , z11 , z12 , z13 , + z21 , z22 , z23 , z31 , z32 , z33, + qzms2t, ss, j2, j3oj2, j4, x2o3, r[3], v[3], + tumin, mu, radiusearthkm, xke, j3; + + /* ------------------------ initialization --------------------- */ + // sgp4fix divisor for divide by zero check on inclination + const double temp4 = 1.0 + cos(pi-1.0e-9); + + /* ----------- set all near earth variables to zero ------------ */ + satrec.isimp = 0; satrec.method = 'n'; satrec.aycof = 0.0; + satrec.con41 = 0.0; satrec.cc1 = 0.0; satrec.cc4 = 0.0; + satrec.cc5 = 0.0; satrec.d2 = 0.0; satrec.d3 = 0.0; + satrec.d4 = 0.0; satrec.delmo = 0.0; satrec.eta = 0.0; + satrec.argpdot = 0.0; satrec.omgcof = 0.0; satrec.sinmao = 0.0; + satrec.t = 0.0; satrec.t2cof = 0.0; satrec.t3cof = 0.0; + satrec.t4cof = 0.0; satrec.t5cof = 0.0; satrec.x1mth2 = 0.0; + satrec.x7thm1 = 0.0; satrec.mdot = 0.0; satrec.nodedot = 0.0; + satrec.xlcof = 0.0; satrec.xmcof = 0.0; satrec.nodecf = 0.0; + + /* ----------- set all deep space variables to zero ------------ */ + satrec.irez = 0; satrec.d2201 = 0.0; satrec.d2211 = 0.0; + satrec.d3210 = 0.0; satrec.d3222 = 0.0; satrec.d4410 = 0.0; + satrec.d4422 = 0.0; satrec.d5220 = 0.0; satrec.d5232 = 0.0; + satrec.d5421 = 0.0; satrec.d5433 = 0.0; satrec.dedt = 0.0; + satrec.del1 = 0.0; satrec.del2 = 0.0; satrec.del3 = 0.0; + satrec.didt = 0.0; satrec.dmdt = 0.0; satrec.dnodt = 0.0; + satrec.domdt = 0.0; satrec.e3 = 0.0; satrec.ee2 = 0.0; + satrec.peo = 0.0; satrec.pgho = 0.0; satrec.pho = 0.0; + satrec.pinco = 0.0; satrec.plo = 0.0; satrec.se2 = 0.0; + satrec.se3 = 0.0; satrec.sgh2 = 0.0; satrec.sgh3 = 0.0; + satrec.sgh4 = 0.0; satrec.sh2 = 0.0; satrec.sh3 = 0.0; + satrec.si2 = 0.0; satrec.si3 = 0.0; satrec.sl2 = 0.0; + satrec.sl3 = 0.0; satrec.sl4 = 0.0; satrec.gsto = 0.0; + satrec.xfact = 0.0; satrec.xgh2 = 0.0; satrec.xgh3 = 0.0; + satrec.xgh4 = 0.0; satrec.xh2 = 0.0; satrec.xh3 = 0.0; + satrec.xi2 = 0.0; satrec.xi3 = 0.0; satrec.xl2 = 0.0; + satrec.xl3 = 0.0; satrec.xl4 = 0.0; satrec.xlamo = 0.0; + satrec.zmol = 0.0; satrec.zmos = 0.0; satrec.atime = 0.0; + satrec.xli = 0.0; satrec.xni = 0.0; + + // sgp4fix - note the following variables are also passed directly via satrec. + // it is possible to streamline the sgp4init call by deleting the "x" + // variables, but the user would need to set the satrec.* values first. we + // include the additional assignments in case twoline2rv is not used. + satrec.bstar = xbstar; + satrec.ecco = xecco; + satrec.argpo = xargpo; + satrec.inclo = xinclo; + satrec.mo = xmo; + satrec.no = xno; + satrec.nodeo = xnodeo; + + /* ------------------------ earth constants ----------------------- */ + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + ss = 78.0 / radiusearthkm + 1.0; + qzms2t = pow(((120.0 - 78.0) / radiusearthkm), 4); + x2o3 = 2.0 / 3.0; + + satrec.init = 'y'; + satrec.t = 0.0; + + initl + ( + satn, whichconst, satrec.ecco, epoch, satrec.inclo, satrec.no, satrec.method, + ainv, ao, satrec.con41, con42, cosio, cosio2, eccsq, omeosq, + posq, rp, rteosq, sinio, satrec.gsto + ); + satrec.error = 0; + + if (rp < 1.0) + { +// printf("# *** satn%d epoch elts sub-orbital ***\n", satn); + satrec.error = 5; + } + + if ((omeosq >= 0.0 ) || ( satrec.no >= 0.0)) + { + satrec.isimp = 0; + if (rp < (220.0 / radiusearthkm + 1.0)) + satrec.isimp = 1; + sfour = ss; + qzms24 = qzms2t; + perige = (rp - 1.0) * radiusearthkm; + + /* - for perigees below 156 km, s and qoms2t are altered - */ + if (perige < 156.0) + { + sfour = perige - 78.0; + if (perige < 98.0) + sfour = 20.0; + qzms24 = pow(((120.0 - sfour) / radiusearthkm), 4.0); + sfour = sfour / radiusearthkm + 1.0; + } + pinvsq = 1.0 / posq; + + tsi = 1.0 / (ao - sfour); + satrec.eta = ao * satrec.ecco * tsi; + etasq = satrec.eta * satrec.eta; + eeta = satrec.ecco * satrec.eta; + psisq = fabs(1.0 - etasq); + coef = qzms24 * pow(tsi, 4.0); + coef1 = coef / pow(psisq, 3.5); + cc2 = coef1 * satrec.no * (ao * (1.0 + 1.5 * etasq + eeta * + (4.0 + etasq)) + 0.375 * j2 * tsi / psisq * satrec.con41 * + (8.0 + 3.0 * etasq * (8.0 + etasq))); + satrec.cc1 = satrec.bstar * cc2; + cc3 = 0.0; + if (satrec.ecco > 1.0e-4) + cc3 = -2.0 * coef * tsi * j3oj2 * satrec.no * sinio / satrec.ecco; + satrec.x1mth2 = 1.0 - cosio2; + satrec.cc4 = 2.0* satrec.no * coef1 * ao * omeosq * + (satrec.eta * (2.0 + 0.5 * etasq) + satrec.ecco * + (0.5 + 2.0 * etasq) - j2 * tsi / (ao * psisq) * + (-3.0 * satrec.con41 * (1.0 - 2.0 * eeta + etasq * + (1.5 - 0.5 * eeta)) + 0.75 * satrec.x1mth2 * + (2.0 * etasq - eeta * (1.0 + etasq)) * cos(2.0 * satrec.argpo))); + satrec.cc5 = 2.0 * coef1 * ao * omeosq * (1.0 + 2.75 * + (etasq + eeta) + eeta * etasq); + cosio4 = cosio2 * cosio2; + temp1 = 1.5 * j2 * pinvsq * satrec.no; + temp2 = 0.5 * temp1 * j2 * pinvsq; + temp3 = -0.46875 * j4 * pinvsq * pinvsq * satrec.no; + satrec.mdot = satrec.no + 0.5 * temp1 * rteosq * satrec.con41 + 0.0625 * + temp2 * rteosq * (13.0 - 78.0 * cosio2 + 137.0 * cosio4); + satrec.argpdot = -0.5 * temp1 * con42 + 0.0625 * temp2 * + (7.0 - 114.0 * cosio2 + 395.0 * cosio4) + + temp3 * (3.0 - 36.0 * cosio2 + 49.0 * cosio4); + xhdot1 = -temp1 * cosio; + satrec.nodedot = xhdot1 + (0.5 * temp2 * (4.0 - 19.0 * cosio2) + + 2.0 * temp3 * (3.0 - 7.0 * cosio2)) * cosio; + xpidot = satrec.argpdot+ satrec.nodedot; + satrec.omgcof = satrec.bstar * cc3 * cos(satrec.argpo); + satrec.xmcof = 0.0; + if (satrec.ecco > 1.0e-4) + satrec.xmcof = -x2o3 * coef * satrec.bstar / eeta; + satrec.nodecf = 3.5 * omeosq * xhdot1 * satrec.cc1; + satrec.t2cof = 1.5 * satrec.cc1; + // sgp4fix for divide by zero with xinco = 180 deg + if (fabs(cosio+1.0) > 1.5e-12) + satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / (1.0 + cosio); + else + satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / temp4; + satrec.aycof = -0.5 * j3oj2 * sinio; + satrec.delmo = pow((1.0 + satrec.eta * cos(satrec.mo)), 3); + satrec.sinmao = sin(satrec.mo); + satrec.x7thm1 = 7.0 * cosio2 - 1.0; + + /* --------------- deep space initialization ------------- */ + if ((2*pi / satrec.no) >= 225.0) + { + satrec.method = 'd'; + satrec.isimp = 1; + tc = 0.0; + inclm = satrec.inclo; + + dscom + ( + epoch, satrec.ecco, satrec.argpo, tc, satrec.inclo, satrec.nodeo, + satrec.no, snodm, cnodm, sinim, cosim,sinomm, cosomm, + day, satrec.e3, satrec.ee2, em, emsq, gam, + satrec.peo, satrec.pgho, satrec.pho, satrec.pinco, + satrec.plo, rtemsq, satrec.se2, satrec.se3, + satrec.sgh2, satrec.sgh3, satrec.sgh4, + satrec.sh2, satrec.sh3, satrec.si2, satrec.si3, + satrec.sl2, satrec.sl3, satrec.sl4, s1, s2, s3, s4, s5, + s6, s7, ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3, + sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33, + satrec.xgh2, satrec.xgh3, satrec.xgh4, satrec.xh2, + satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2, + satrec.xl3, satrec.xl4, nm, z1, z2, z3, z11, + z12, z13, z21, z22, z23, z31, z32, z33, + satrec.zmol, satrec.zmos + ); + dpper + ( + satrec.e3, satrec.ee2, satrec.peo, satrec.pgho, + satrec.pho, satrec.pinco, satrec.plo, satrec.se2, + satrec.se3, satrec.sgh2, satrec.sgh3, satrec.sgh4, + satrec.sh2, satrec.sh3, satrec.si2, satrec.si3, + satrec.sl2, satrec.sl3, satrec.sl4, satrec.t, + satrec.xgh2,satrec.xgh3,satrec.xgh4, satrec.xh2, + satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2, + satrec.xl3, satrec.xl4, satrec.zmol, satrec.zmos, inclm, satrec.init, + satrec.ecco, satrec.inclo, satrec.nodeo, satrec.argpo, satrec.mo + ); + + argpm = 0.0; + nodem = 0.0; + mm = 0.0; + + dsinit + ( + whichconst, + cosim, emsq, satrec.argpo, s1, s2, s3, s4, s5, sinim, ss1, ss2, ss3, ss4, + ss5, sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33, satrec.t, tc, + satrec.gsto, satrec.mo, satrec.mdot, satrec.no, satrec.nodeo, + satrec.nodedot, xpidot, z1, z3, z11, z13, z21, z23, z31, z33, + satrec.ecco, eccsq, em, argpm, inclm, mm, nm, nodem, + satrec.irez, satrec.atime, + satrec.d2201, satrec.d2211, satrec.d3210, satrec.d3222 , + satrec.d4410, satrec.d4422, satrec.d5220, satrec.d5232, + satrec.d5421, satrec.d5433, satrec.dedt, satrec.didt, + satrec.dmdt, dndt, satrec.dnodt, satrec.domdt , + satrec.del1, satrec.del2, satrec.del3, satrec.xfact, + satrec.xlamo, satrec.xli, satrec.xni + ); + } + + /* ----------- set variables if not deep space ----------- */ + if (satrec.isimp != 1) + { + cc1sq = satrec.cc1 * satrec.cc1; + satrec.d2 = 4.0 * ao * tsi * cc1sq; + temp = satrec.d2 * tsi * satrec.cc1 / 3.0; + satrec.d3 = (17.0 * ao + sfour) * temp; + satrec.d4 = 0.5 * temp * ao * tsi * (221.0 * ao + 31.0 * sfour) * + satrec.cc1; + satrec.t3cof = satrec.d2 + 2.0 * cc1sq; + satrec.t4cof = 0.25 * (3.0 * satrec.d3 + satrec.cc1 * + (12.0 * satrec.d2 + 10.0 * cc1sq)); + satrec.t5cof = 0.2 * (3.0 * satrec.d4 + + 12.0 * satrec.cc1 * satrec.d3 + + 6.0 * satrec.d2 * satrec.d2 + + 15.0 * cc1sq * (2.0 * satrec.d2 + cc1sq)); + } + } // if omeosq = 0 ... + + /* finally propogate to zero epoch to initialise all others. */ + if(satrec.error == 0) + sgp4(whichconst, satrec, 0.0, r, v); + + satrec.init = 'n'; + +//#include "debug6.cpp" + return satrec.error; +} // end sgp4init + +/*----------------------------------------------------------------------------- +* +* procedure sgp4 +* +* this procedure is the sgp4 prediction model from space command. this is an +* updated and combined version of sgp4 and sdp4, which were originally +* published separately in spacetrack report #3. this version follows the +* methodology from the aiaa paper (2006) describing the history and +* development of the code. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* satrec - initialised structure from sgp4init() call. +* tsince - time eince epoch (minutes) +* +* outputs : +* r - position vector km +* v - velocity km/sec +* return code - non-zero on error. +* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er +* 2 - mean motion less than 0.0 +* 3 - pert elements, ecc < 0.0 or ecc > 1.0 +* 4 - semi-latus rectum < 0.0 +* 5 - epoch elements are sub-orbital +* 6 - satellite has decayed +* +* locals : +* am - +* axnl, aynl - +* betal - +* cosim , sinim , cosomm , sinomm , cnod , snod , cos2u , +* sin2u , coseo1 , sineo1 , cosi , sini , cosip , sinip , +* cosisq , cossu , sinsu , cosu , sinu +* delm - +* delomg - +* dndt - +* eccm - +* emsq - +* ecose - +* el2 - +* eo1 - +* eccp - +* esine - +* argpm - +* argpp - +* omgadf - +* pl - +* r - +* rtemsq - +* rdotl - +* rl - +* rvdot - +* rvdotl - +* su - +* t2 , t3 , t4 , tc +* tem5, temp , temp1 , temp2 , tempa , tempe , templ +* u , ux , uy , uz , vx , vy , vz +* inclm - inclination +* mm - mean anomaly +* nm - mean motion +* nodem - right asc of ascending node +* xinc - +* xincp - +* xl - +* xlm - +* mp - +* xmdf - +* xmx - +* xmy - +* nodedf - +* xnode - +* nodep - +* np - +* +* coupling : +* getgravconst- +* dpper +* dpspace +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +int sgp4 + ( + gravconsttype whichconst, elsetrec& satrec, double tsince, + double r[3], double v[3] + ) +{ + double am , axnl , aynl , betal , cosim , cnod , + cos2u, coseo1, cosi , cosip , cosisq, cossu , cosu, + delm , delomg, em , emsq , ecose , el2 , eo1 , + ep , esine , argpm, argpp , argpdf, pl, mrt = 0.0, + mvt , rdotl , rl , rvdot , rvdotl, sinim , + sin2u, sineo1, sini , sinip , sinsu , sinu , + snod , su , t2 , t3 , t4 , tem5 , temp, + temp1, temp2 , tempa, tempe , templ , u , ux , + uy , uz , vx , vy , vz , inclm , mm , + nm , nodem, xinc , xincp , xl , xlm , mp , + xmdf , xmx , xmy , nodedf, xnode , nodep, tc , dndt, + twopi, x2o3 , j2 , j3 , tumin, j4 , xke , j3oj2, radiusearthkm, + mu, vkmpersec; + int ktr; + + /* ------------------ set mathematical constants --------------- */ + // sgp4fix divisor for divide by zero check on inclination + const double temp4 = 1.0 + cos(pi-1.0e-9); + twopi = 2.0 * pi; + x2o3 = 2.0 / 3.0; + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + vkmpersec = radiusearthkm * xke/60.0; + + /* --------------------- clear sgp4 error flag ----------------- */ + satrec.t = tsince; + satrec.error = 0; + + /* ------- update for secular gravity and atmospheric drag ----- */ + xmdf = satrec.mo + satrec.mdot * satrec.t; + argpdf = satrec.argpo + satrec.argpdot * satrec.t; + nodedf = satrec.nodeo + satrec.nodedot * satrec.t; + argpm = argpdf; + mm = xmdf; + t2 = satrec.t * satrec.t; + nodem = nodedf + satrec.nodecf * t2; + tempa = 1.0 - satrec.cc1 * satrec.t; + tempe = satrec.bstar * satrec.cc4 * satrec.t; + templ = satrec.t2cof * t2; + + if (satrec.isimp != 1) + { + delomg = satrec.omgcof * satrec.t; + delm = satrec.xmcof * + (pow((1.0 + satrec.eta * cos(xmdf)), 3) - + satrec.delmo); + temp = delomg + delm; + mm = xmdf + temp; + argpm = argpdf - temp; + t3 = t2 * satrec.t; + t4 = t3 * satrec.t; + tempa = tempa - satrec.d2 * t2 - satrec.d3 * t3 - + satrec.d4 * t4; + tempe = tempe + satrec.bstar * satrec.cc5 * (sin(mm) - + satrec.sinmao); + templ = templ + satrec.t3cof * t3 + t4 * (satrec.t4cof + + satrec.t * satrec.t5cof); + } + + nm = satrec.no; + em = satrec.ecco; + inclm = satrec.inclo; + if (satrec.method == 'd') + { + tc = satrec.t; + dspace + ( + satrec.irez, + satrec.d2201, satrec.d2211, satrec.d3210, + satrec.d3222, satrec.d4410, satrec.d4422, + satrec.d5220, satrec.d5232, satrec.d5421, + satrec.d5433, satrec.dedt, satrec.del1, + satrec.del2, satrec.del3, satrec.didt, + satrec.dmdt, satrec.dnodt, satrec.domdt, + satrec.argpo, satrec.argpdot, satrec.t, tc, + satrec.gsto, satrec.xfact, satrec.xlamo, + satrec.no, satrec.atime, + em, argpm, inclm, satrec.xli, mm, satrec.xni, + nodem, dndt, nm + ); + } // if method = d + + if (nm <= 0.0) + { +// printf("# error nm %f\n", nm); + satrec.error = 2; + } + am = pow((xke / nm),x2o3) * tempa * tempa; + nm = xke / pow(am, 1.5); + em = em - tempe; + + // fix tolerance for error recognition + if ((em >= 1.0) || (em < -0.001) || (am < 0.95)) + { +// printf("# error em %f\n", em); + satrec.error = 1; + } + if (em < 0.0) + em = 1.0e-6; + mm = mm + satrec.no * templ; + xlm = mm + argpm + nodem; + emsq = em * em; + temp = 1.0 - emsq; + + nodem = fmod(nodem, twopi); + argpm = fmod(argpm, twopi); + xlm = fmod(xlm, twopi); + mm = fmod(xlm - argpm - nodem, twopi); + + /* ----------------- compute extra mean quantities ------------- */ + sinim = sin(inclm); + cosim = cos(inclm); + + /* -------------------- add lunar-solar periodics -------------- */ + ep = em; + xincp = inclm; + argpp = argpm; + nodep = nodem; + mp = mm; + sinip = sinim; + cosip = cosim; + if (satrec.method == 'd') + { + dpper + ( + satrec.e3, satrec.ee2, satrec.peo, + satrec.pgho, satrec.pho, satrec.pinco, + satrec.plo, satrec.se2, satrec.se3, + satrec.sgh2, satrec.sgh3, satrec.sgh4, + satrec.sh2, satrec.sh3, satrec.si2, + satrec.si3, satrec.sl2, satrec.sl3, + satrec.sl4, satrec.t, satrec.xgh2, + satrec.xgh3, satrec.xgh4, satrec.xh2, + satrec.xh3, satrec.xi2, satrec.xi3, + satrec.xl2, satrec.xl3, satrec.xl4, + satrec.zmol, satrec.zmos, satrec.inclo, + 'n', ep, xincp, nodep, argpp, mp + ); + if (xincp < 0.0) + { + xincp = -xincp; + nodep = nodep + pi; + argpp = argpp - pi; + } + if ((ep < 0.0 ) || ( ep > 1.0)) + { + // printf("# error ep %f\n", ep); + satrec.error = 3; + } + } // if method = d + + /* -------------------- long period periodics ------------------ */ + if (satrec.method == 'd') + { + sinip = sin(xincp); + cosip = cos(xincp); + satrec.aycof = -0.5*j3oj2*sinip; + // sgp4fix for divide by zero for xincp = 180 deg + if (fabs(cosip+1.0) > 1.5e-12) + satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / (1.0 + cosip); + else + satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / temp4; + } + axnl = ep * cos(argpp); + temp = 1.0 / (am * (1.0 - ep * ep)); + aynl = ep* sin(argpp) + temp * satrec.aycof; + xl = mp + argpp + nodep + temp * satrec.xlcof * axnl; + + /* --------------------- solve kepler's equation --------------- */ + u = fmod(xl - nodep, twopi); + eo1 = u; + tem5 = 9999.9; + ktr = 1; + // sgp4fix for kepler iteration + // the following iteration needs better limits on corrections + while (( fabs(tem5) >= 1.0e-12) && (ktr <= 10) ) + { + sineo1 = sin(eo1); + coseo1 = cos(eo1); + tem5 = 1.0 - coseo1 * axnl - sineo1 * aynl; + tem5 = (u - aynl * coseo1 + axnl * sineo1 - eo1) / tem5; + if(fabs(tem5) >= 0.95) + tem5 = tem5 > 0.0 ? 0.95 : -0.95; + eo1 = eo1 + tem5; + ktr = ktr + 1; + } + + /* ------------- short period preliminary quantities ----------- */ + ecose = axnl*coseo1 + aynl*sineo1; + esine = axnl*sineo1 - aynl*coseo1; + el2 = axnl*axnl + aynl*aynl; + pl = am*(1.0-el2); + if (pl < 0.0) + { +// printf("# error pl %f\n", pl); + satrec.error = 4; + } + else + { + rl = am * (1.0 - ecose); + rdotl = sqrt(am) * esine/rl; + rvdotl = sqrt(pl) / rl; + betal = sqrt(1.0 - el2); + temp = esine / (1.0 + betal); + sinu = am / rl * (sineo1 - aynl - axnl * temp); + cosu = am / rl * (coseo1 - axnl + aynl * temp); + su = atan2(sinu, cosu); + sin2u = (cosu + cosu) * sinu; + cos2u = 1.0 - 2.0 * sinu * sinu; + temp = 1.0 / pl; + temp1 = 0.5 * j2 * temp; + temp2 = temp1 * temp; + + /* -------------- update for short period periodics ------------ */ + if (satrec.method == 'd') + { + cosisq = cosip * cosip; + satrec.con41 = 3.0*cosisq - 1.0; + satrec.x1mth2 = 1.0 - cosisq; + satrec.x7thm1 = 7.0*cosisq - 1.0; + } + mrt = rl * (1.0 - 1.5 * temp2 * betal * satrec.con41) + + 0.5 * temp1 * satrec.x1mth2 * cos2u; + su = su - 0.25 * temp2 * satrec.x7thm1 * sin2u; + xnode = nodep + 1.5 * temp2 * cosip * sin2u; + xinc = xincp + 1.5 * temp2 * cosip * sinip * cos2u; + mvt = rdotl - nm * temp1 * satrec.x1mth2 * sin2u / xke; + rvdot = rvdotl + nm * temp1 * (satrec.x1mth2 * cos2u + + 1.5 * satrec.con41) / xke; + + /* --------------------- orientation vectors ------------------- */ + sinsu = sin(su); + cossu = cos(su); + snod = sin(xnode); + cnod = cos(xnode); + sini = sin(xinc); + cosi = cos(xinc); + xmx = -snod * cosi; + xmy = cnod * cosi; + ux = xmx * sinsu + cnod * cossu; + uy = xmy * sinsu + snod * cossu; + uz = sini * sinsu; + vx = xmx * cossu - cnod * sinsu; + vy = xmy * cossu - snod * sinsu; + vz = sini * cossu; + + /* --------- position and velocity (in km and km/sec) ---------- */ + r[0] = (mrt * ux)* radiusearthkm; + r[1] = (mrt * uy)* radiusearthkm; + r[2] = (mrt * uz)* radiusearthkm; + v[0] = (mvt * ux + rvdot * vx) * vkmpersec; + v[1] = (mvt * uy + rvdot * vy) * vkmpersec; + v[2] = (mvt * uz + rvdot * vz) * vkmpersec; + } // if pl > 0 + + // sgp4fix for decaying satellites + if (mrt < 1.0) + { +// printf("# decay condition %11.6f \n",mrt); + satrec.error = 6; + } + + +//#include "debug7.cpp" + return satrec.error; +} // end sgp4 + + +/* ----------------------------------------------------------------------------- +* +* function gstime +* +* this function finds the greenwich sidereal time. +* +* author : david vallado 719-573-2600 1 mar 2001 +* +* inputs description range / units +* jdut1 - julian date in ut1 days from 4713 bc +* +* outputs : +* gstime - greenwich sidereal time 0 to 2pi rad +* +* locals : +* temp - temporary variable for doubles rad +* tut1 - julian centuries from the +* jan 1, 2000 12 h epoch (ut1) +* +* coupling : +* none +* +* references : +* vallado 2004, 191, eq 3-45 +* --------------------------------------------------------------------------- */ + +double gstime + ( + double jdut1 + ) + { + const double twopi = 2.0 * pi; + const double deg2rad = pi / 180.0; + double temp, tut1; + + tut1 = (jdut1 - 2451545.0) / 36525.0; + temp = -6.2e-6* tut1 * tut1 * tut1 + 0.093104 * tut1 * tut1 + + (876600.0*3600 + 8640184.812866) * tut1 + 67310.54841; // sec + temp = fmod(temp * deg2rad / 240.0, twopi); //360/86400 = 1/240, to deg, to rad + + // ------------------------ check quadrants --------------------- + if (temp < 0.0) + temp += twopi; + + return temp; + } // end gstime + +/* ----------------------------------------------------------------------------- +* +* function getgravconst +* +* this function gets constants for the propagator. note that mu is identified to +* facilitiate comparisons with newer models. the common useage is wgs72. +* +* author : david vallado 719-573-2600 21 jul 2006 +* +* inputs : +* whichconst - which set of constants to use wgs72old, wgs72, wgs84 +* +* outputs : +* tumin - minutes in one time unit +* mu - earth gravitational parameter +* radiusearthkm - radius of the earth in km +* xke - reciprocal of tumin +* j2, j3, j4 - un-normalized zonal harmonic values +* j3oj2 - j3 divided by j2 +* +* locals : +* +* coupling : +* none +* +* references : +* norad spacetrack report #3 +* vallado, crawford, hujsak, kelso 2006 + --------------------------------------------------------------------------- */ + +void getgravconst + ( + gravconsttype whichconst, + double& tumin, + double& mu, + double& radiusearthkm, + double& xke, + double& j2, + double& j3, + double& j4, + double& j3oj2 + ) + { + + switch (whichconst) + { + // -- wgs-72 low precision str#3 constants -- + case wgs72old: + mu = 398600.79964; // in km3 / s2 + radiusearthkm = 6378.135; // km + xke = 0.0743669161; + tumin = 1.0 / xke; + j2 = 0.001082616; + j3 = -0.00000253881; + j4 = -0.00000165597; + j3oj2 = j3 / j2; + break; + // ------------ wgs-72 constants ------------ + case wgs72: + mu = 398600.8; // in km3 / s2 + radiusearthkm = 6378.135; // km + xke = 60.0 / sqrt(radiusearthkm*radiusearthkm*radiusearthkm/mu); + tumin = 1.0 / xke; + j2 = 0.001082616; + j3 = -0.00000253881; + j4 = -0.00000165597; + j3oj2 = j3 / j2; + break; + case wgs84: + // ------------ wgs-84 constants ------------ + mu = 398600.5; // in km3 / s2 + radiusearthkm = 6378.137; // km + xke = 60.0 / sqrt(radiusearthkm*radiusearthkm*radiusearthkm/mu); + tumin = 1.0 / xke; + j2 = 0.00108262998905; + j3 = -0.00000253215306; + j4 = -0.00000161098761; + j3oj2 = j3 / j2; + break; + default: + fprintf(stderr,"unknown gravity option (%d)\n",whichconst); + break; + } + + } // end getgravconst + + + + + diff --git a/contrib/sgp4/sgp4unit.h b/contrib/sgp4/sgp4unit.h index 48c113d7..f16acbd9 100644 --- a/contrib/sgp4/sgp4unit.h +++ b/contrib/sgp4/sgp4unit.h @@ -1,117 +1,117 @@ -#ifndef _sgp4unit_ -#define _sgp4unit_ -/* ---------------------------------------------------------------- -* -* sgp4unit.h -* -* this file contains the sgp4 procedures for analytical propagation -* of a satellite. the code was originally released in the 1980 and 1986 -* spacetrack papers. a detailed discussion of the theory and history -* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, -* and kelso. -* -* companion code for -* fundamentals of astrodynamics and applications -* 2007 -* by david vallado -* -* (w) 719-573-2600, email dvallado@agi.com -* -* current : -* 20 apr 07 david vallado -* misc fixes for constants -* changes : -* 11 aug 06 david vallado -* chg lyddane choice back to strn3, constants, misc doc -* 15 dec 05 david vallado -* misc fixes -* 26 jul 05 david vallado -* fixes for paper -* note that each fix is preceded by a -* comment with "sgp4fix" and an explanation of -* what was changed -* 10 aug 04 david vallado -* 2nd printing baseline working -* 14 may 01 david vallado -* 2nd edition baseline -* 80 norad -* original baseline -* ---------------------------------------------------------------- */ - -#include -#include - -// -------------------------- structure declarations ---------------------------- -typedef enum -{ - wgs72old, - wgs72, - wgs84 -} gravconsttype; - -typedef struct elsetrec -{ - long int satnum; - int epochyr, epochtynumrev; - int error; - char init, method; - - /* Near Earth */ - int isimp; - double aycof , con41 , cc1 , cc4 , cc5 , d2 , d3 , d4 , - delmo , eta , argpdot, omgcof , sinmao , t , t2cof, t3cof , - t4cof , t5cof , x1mth2 , x7thm1 , mdot , nodedot, xlcof , xmcof , - nodecf; - - /* Deep Space */ - int irez; - double d2201 , d2211 , d3210 , d3222 , d4410 , d4422 , d5220 , d5232 , - d5421 , d5433 , dedt , del1 , del2 , del3 , didt , dmdt , - dnodt , domdt , e3 , ee2 , peo , pgho , pho , pinco , - plo , se2 , se3 , sgh2 , sgh3 , sgh4 , sh2 , sh3 , - si2 , si3 , sl2 , sl3 , sl4 , gsto , xfact , xgh2 , - xgh3 , xgh4 , xh2 , xh3 , xi2 , xi3 , xl2 , xl3 , - xl4 , xlamo , zmol , zmos , atime , xli , xni; - - double a , altp , alta , epochdays, jdsatepoch , nddot , ndot , - bstar , rcse , inclo , nodeo , ecco , argpo , mo , - no; -} elsetrec; - -// --------------------------- function declarations ---------------------------- -int sgp4init - ( - gravconsttype whichconst, const int satn, const double epoch, - const double xbstar, const double xecco, const double xargpo, - const double xinclo, const double xmo, const double xno, - const double xnodeo, - elsetrec& satrec - ); - -int sgp4 - ( - gravconsttype whichconst, - elsetrec& satrec, double tsince, - double r[], double v[] - ); - -double gstime - ( - double - ); - -void getgravconst - ( - gravconsttype, - double&, - double&, - double&, - double&, - double&, - double&, - double&, - double& - ); - -#endif - +#ifndef _sgp4unit_ +#define _sgp4unit_ +/* ---------------------------------------------------------------- +* +* sgp4unit.h +* +* this file contains the sgp4 procedures for analytical propagation +* of a satellite. the code was originally released in the 1980 and 1986 +* spacetrack papers. a detailed discussion of the theory and history +* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, +* and kelso. +* +* companion code for +* fundamentals of astrodynamics and applications +* 2007 +* by david vallado +* +* (w) 719-573-2600, email dvallado@agi.com +* +* current : +* 20 apr 07 david vallado +* misc fixes for constants +* changes : +* 11 aug 06 david vallado +* chg lyddane choice back to strn3, constants, misc doc +* 15 dec 05 david vallado +* misc fixes +* 26 jul 05 david vallado +* fixes for paper +* note that each fix is preceded by a +* comment with "sgp4fix" and an explanation of +* what was changed +* 10 aug 04 david vallado +* 2nd printing baseline working +* 14 may 01 david vallado +* 2nd edition baseline +* 80 norad +* original baseline +* ---------------------------------------------------------------- */ + +#include +#include + +// -------------------------- structure declarations ---------------------------- +typedef enum +{ + wgs72old, + wgs72, + wgs84 +} gravconsttype; + +typedef struct elsetrec +{ + long int satnum; + int epochyr, epochtynumrev; + int error; + char init, method; + + /* Near Earth */ + int isimp; + double aycof , con41 , cc1 , cc4 , cc5 , d2 , d3 , d4 , + delmo , eta , argpdot, omgcof , sinmao , t , t2cof, t3cof , + t4cof , t5cof , x1mth2 , x7thm1 , mdot , nodedot, xlcof , xmcof , + nodecf; + + /* Deep Space */ + int irez; + double d2201 , d2211 , d3210 , d3222 , d4410 , d4422 , d5220 , d5232 , + d5421 , d5433 , dedt , del1 , del2 , del3 , didt , dmdt , + dnodt , domdt , e3 , ee2 , peo , pgho , pho , pinco , + plo , se2 , se3 , sgh2 , sgh3 , sgh4 , sh2 , sh3 , + si2 , si3 , sl2 , sl3 , sl4 , gsto , xfact , xgh2 , + xgh3 , xgh4 , xh2 , xh3 , xi2 , xi3 , xl2 , xl3 , + xl4 , xlamo , zmol , zmos , atime , xli , xni; + + double a , altp , alta , epochdays, jdsatepoch , nddot , ndot , + bstar , rcse , inclo , nodeo , ecco , argpo , mo , + no; +} elsetrec; + +// --------------------------- function declarations ---------------------------- +int sgp4init + ( + gravconsttype whichconst, const int satn, const double epoch, + const double xbstar, const double xecco, const double xargpo, + const double xinclo, const double xmo, const double xno, + const double xnodeo, + elsetrec& satrec + ); + +int sgp4 + ( + gravconsttype whichconst, + elsetrec& satrec, double tsince, + double r[], double v[] + ); + +double gstime + ( + double + ); + +void getgravconst + ( + gravconsttype, + double&, + double&, + double&, + double&, + double&, + double&, + double&, + double& + ); + +#endif + diff --git a/globalfunctions/timevalOperations.cpp b/globalfunctions/timevalOperations.cpp index ae49ef21..1228da04 100644 --- a/globalfunctions/timevalOperations.cpp +++ b/globalfunctions/timevalOperations.cpp @@ -1,99 +1,99 @@ -#include "timevalOperations.h" - -timeval& operator+=(timeval& lhs, const timeval& rhs) { - int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; - sum += rhs.tv_sec * 1000000. + rhs.tv_usec; - lhs.tv_sec = sum / 1000000; - lhs.tv_usec = sum - lhs.tv_sec * 1000000; - return lhs; -} - -timeval operator+(timeval lhs, const timeval& rhs) { - lhs += rhs; - return lhs; -} - -timeval& operator-=(timeval& lhs, const timeval& rhs) { - int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; - sum -= rhs.tv_sec * 1000000. + rhs.tv_usec; - lhs.tv_sec = sum / 1000000; - lhs.tv_usec = sum - lhs.tv_sec * 1000000; - return lhs; -} - -timeval operator-(timeval lhs, const timeval& rhs) { - lhs -= rhs; - return lhs; -} - -double operator/(const timeval& lhs, const timeval& rhs) { - double lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; - double rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; - return lhs64 / rhs64; -} - -timeval& operator/=(timeval& lhs, double scalar) { - int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec; - product /= scalar; - lhs.tv_sec = product / 1000000; - lhs.tv_usec = product - lhs.tv_sec * 1000000; - return lhs; -} - -timeval operator/(timeval lhs, double scalar) { - lhs /= scalar; - return lhs; -} - -timeval& operator*=(timeval& lhs, double scalar) { - int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec; - product *= scalar; - lhs.tv_sec = product / 1000000; - lhs.tv_usec = product - lhs.tv_sec * 1000000; - return lhs; -} - -timeval operator*(timeval lhs, double scalar) { - lhs *= scalar; - return lhs; -} - -timeval operator*(double scalar, timeval rhs) { - rhs *= scalar; - return rhs; -} - -bool operator==(const timeval& lhs, const timeval& rhs) { - int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; - int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; - return lhs64 == rhs64; -} -bool operator!=(const timeval& lhs, const timeval& rhs) { - return !operator==(lhs, rhs); -} -bool operator<(const timeval& lhs, const timeval& rhs) { - int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; - int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; - return lhs64 < rhs64; -} -bool operator>(const timeval& lhs, const timeval& rhs) { - return operator<(rhs, lhs); -} -bool operator<=(const timeval& lhs, const timeval& rhs) { - return !operator>(lhs, rhs); -} -bool operator>=(const timeval& lhs, const timeval& rhs) { - return !operator<(lhs, rhs); -} - -double timevalOperations::toDouble(const timeval timeval) { - double result = timeval.tv_sec * 1000000. + timeval.tv_usec; - return result / 1000000.; -} - -timeval timevalOperations::toTimeval(const double seconds) { - timeval tval; - tval.tv_sec = seconds; - tval.tv_usec = seconds *(double) 1e6 - (tval.tv_sec *1e6); - return tval; -} +#include "timevalOperations.h" + +timeval& operator+=(timeval& lhs, const timeval& rhs) { + int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; + sum += rhs.tv_sec * 1000000. + rhs.tv_usec; + lhs.tv_sec = sum / 1000000; + lhs.tv_usec = sum - lhs.tv_sec * 1000000; + return lhs; +} + +timeval operator+(timeval lhs, const timeval& rhs) { + lhs += rhs; + return lhs; +} + +timeval& operator-=(timeval& lhs, const timeval& rhs) { + int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; + sum -= rhs.tv_sec * 1000000. + rhs.tv_usec; + lhs.tv_sec = sum / 1000000; + lhs.tv_usec = sum - lhs.tv_sec * 1000000; + return lhs; +} + +timeval operator-(timeval lhs, const timeval& rhs) { + lhs -= rhs; + return lhs; +} + +double operator/(const timeval& lhs, const timeval& rhs) { + double lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; + double rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; + return lhs64 / rhs64; +} + +timeval& operator/=(timeval& lhs, double scalar) { + int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec; + product /= scalar; + lhs.tv_sec = product / 1000000; + lhs.tv_usec = product - lhs.tv_sec * 1000000; + return lhs; +} + +timeval operator/(timeval lhs, double scalar) { + lhs /= scalar; + return lhs; +} + +timeval& operator*=(timeval& lhs, double scalar) { + int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec; + product *= scalar; + lhs.tv_sec = product / 1000000; + lhs.tv_usec = product - lhs.tv_sec * 1000000; + return lhs; +} + +timeval operator*(timeval lhs, double scalar) { + lhs *= scalar; + return lhs; +} + +timeval operator*(double scalar, timeval rhs) { + rhs *= scalar; + return rhs; +} + +bool operator==(const timeval& lhs, const timeval& rhs) { + int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; + int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; + return lhs64 == rhs64; +} +bool operator!=(const timeval& lhs, const timeval& rhs) { + return !operator==(lhs, rhs); +} +bool operator<(const timeval& lhs, const timeval& rhs) { + int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; + int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; + return lhs64 < rhs64; +} +bool operator>(const timeval& lhs, const timeval& rhs) { + return operator<(rhs, lhs); +} +bool operator<=(const timeval& lhs, const timeval& rhs) { + return !operator>(lhs, rhs); +} +bool operator>=(const timeval& lhs, const timeval& rhs) { + return !operator<(lhs, rhs); +} + +double timevalOperations::toDouble(const timeval timeval) { + double result = timeval.tv_sec * 1000000. + timeval.tv_usec; + return result / 1000000.; +} + +timeval timevalOperations::toTimeval(const double seconds) { + timeval tval; + tval.tv_sec = seconds; + tval.tv_usec = seconds *(double) 1e6 - (tval.tv_sec *1e6); + return tval; +} diff --git a/osal/FreeRTOS/BinSemaphUsingTask.cpp b/osal/FreeRTOS/BinSemaphUsingTask.cpp index 8c831bbe..dd1e48ca 100644 --- a/osal/FreeRTOS/BinSemaphUsingTask.cpp +++ b/osal/FreeRTOS/BinSemaphUsingTask.cpp @@ -1,95 +1,95 @@ -#include "../../osal/FreeRTOS/BinSemaphUsingTask.h" -#include "../../osal/FreeRTOS/TaskManagement.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" - -BinarySemaphoreUsingTask::BinarySemaphoreUsingTask() { - handle = TaskManagement::getCurrentTaskHandle(); - if(handle == nullptr) { - sif::error << "Could not retrieve task handle. Please ensure the" - "constructor was called inside a task." << std::endl; - } - xTaskNotifyGive(handle); -} - -BinarySemaphoreUsingTask::~BinarySemaphoreUsingTask() { - // Clear notification value on destruction. - xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr); -} - -ReturnValue_t BinarySemaphoreUsingTask::acquire(TimeoutType timeoutType, - uint32_t timeoutMs) { - TickType_t timeout = 0; - if(timeoutType == TimeoutType::POLLING) { - timeout = 0; - } - else if(timeoutType == TimeoutType::WAITING){ - timeout = pdMS_TO_TICKS(timeoutMs); - } - else { - timeout = portMAX_DELAY; - } - return acquireWithTickTimeout(timeoutType, timeout); -} - -ReturnValue_t BinarySemaphoreUsingTask::acquireWithTickTimeout( - TimeoutType timeoutType, TickType_t timeoutTicks) { - BaseType_t returncode = ulTaskNotifyTake(pdTRUE, timeoutTicks); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - return SemaphoreIF::SEMAPHORE_TIMEOUT; - } -} - -ReturnValue_t BinarySemaphoreUsingTask::release() { - return release(this->handle); -} - -ReturnValue_t BinarySemaphoreUsingTask::release( - TaskHandle_t taskHandle) { - if(getSemaphoreCounter(taskHandle) == 1) { - return SemaphoreIF::SEMAPHORE_NOT_OWNED; - } - BaseType_t returncode = xTaskNotifyGive(taskHandle); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - // This should never happen. - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -TaskHandle_t BinarySemaphoreUsingTask::getTaskHandle() { - return handle; -} - -uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter() const { - return getSemaphoreCounter(this->handle); -} - -uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter( - TaskHandle_t taskHandle) { - uint32_t notificationValue; - xTaskNotifyAndQuery(taskHandle, 0, eNoAction, ¬ificationValue); - return notificationValue; -} - -// Be careful with the stack size here. This is called from an ISR! -ReturnValue_t BinarySemaphoreUsingTask::releaseFromISR( - TaskHandle_t taskHandle, BaseType_t * higherPriorityTaskWoken) { - if(getSemaphoreCounterFromISR(taskHandle, higherPriorityTaskWoken) == 1) { - return SemaphoreIF::SEMAPHORE_NOT_OWNED; - } - vTaskNotifyGiveFromISR(taskHandle, higherPriorityTaskWoken); - return HasReturnvaluesIF::RETURN_OK; -} - -uint8_t BinarySemaphoreUsingTask::getSemaphoreCounterFromISR( - TaskHandle_t taskHandle, BaseType_t* higherPriorityTaskWoken) { - uint32_t notificationValue = 0; - xTaskNotifyAndQueryFromISR(taskHandle, 0, eNoAction, ¬ificationValue, - higherPriorityTaskWoken); - return notificationValue; -} +#include "../../osal/FreeRTOS/BinSemaphUsingTask.h" +#include "../../osal/FreeRTOS/TaskManagement.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +BinarySemaphoreUsingTask::BinarySemaphoreUsingTask() { + handle = TaskManagement::getCurrentTaskHandle(); + if(handle == nullptr) { + sif::error << "Could not retrieve task handle. Please ensure the" + "constructor was called inside a task." << std::endl; + } + xTaskNotifyGive(handle); +} + +BinarySemaphoreUsingTask::~BinarySemaphoreUsingTask() { + // Clear notification value on destruction. + xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr); +} + +ReturnValue_t BinarySemaphoreUsingTask::acquire(TimeoutType timeoutType, + uint32_t timeoutMs) { + TickType_t timeout = 0; + if(timeoutType == TimeoutType::POLLING) { + timeout = 0; + } + else if(timeoutType == TimeoutType::WAITING){ + timeout = pdMS_TO_TICKS(timeoutMs); + } + else { + timeout = portMAX_DELAY; + } + return acquireWithTickTimeout(timeoutType, timeout); +} + +ReturnValue_t BinarySemaphoreUsingTask::acquireWithTickTimeout( + TimeoutType timeoutType, TickType_t timeoutTicks) { + BaseType_t returncode = ulTaskNotifyTake(pdTRUE, timeoutTicks); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SemaphoreIF::SEMAPHORE_TIMEOUT; + } +} + +ReturnValue_t BinarySemaphoreUsingTask::release() { + return release(this->handle); +} + +ReturnValue_t BinarySemaphoreUsingTask::release( + TaskHandle_t taskHandle) { + if(getSemaphoreCounter(taskHandle) == 1) { + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } + BaseType_t returncode = xTaskNotifyGive(taskHandle); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + // This should never happen. + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +TaskHandle_t BinarySemaphoreUsingTask::getTaskHandle() { + return handle; +} + +uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter() const { + return getSemaphoreCounter(this->handle); +} + +uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter( + TaskHandle_t taskHandle) { + uint32_t notificationValue; + xTaskNotifyAndQuery(taskHandle, 0, eNoAction, ¬ificationValue); + return notificationValue; +} + +// Be careful with the stack size here. This is called from an ISR! +ReturnValue_t BinarySemaphoreUsingTask::releaseFromISR( + TaskHandle_t taskHandle, BaseType_t * higherPriorityTaskWoken) { + if(getSemaphoreCounterFromISR(taskHandle, higherPriorityTaskWoken) == 1) { + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } + vTaskNotifyGiveFromISR(taskHandle, higherPriorityTaskWoken); + return HasReturnvaluesIF::RETURN_OK; +} + +uint8_t BinarySemaphoreUsingTask::getSemaphoreCounterFromISR( + TaskHandle_t taskHandle, BaseType_t* higherPriorityTaskWoken) { + uint32_t notificationValue = 0; + xTaskNotifyAndQueryFromISR(taskHandle, 0, eNoAction, ¬ificationValue, + higherPriorityTaskWoken); + return notificationValue; +} diff --git a/osal/FreeRTOS/BinSemaphUsingTask.h b/osal/FreeRTOS/BinSemaphUsingTask.h index 2d2cf159..f3c0b0ea 100644 --- a/osal/FreeRTOS/BinSemaphUsingTask.h +++ b/osal/FreeRTOS/BinSemaphUsingTask.h @@ -1,76 +1,76 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ -#define FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ - -#include "../../returnvalues/HasReturnvaluesIF.h" -#include "../../tasks/SemaphoreIF.h" - -#include -#include - -/** - * @brief Binary Semaphore implementation using the task notification value. - * The notification value should therefore not be used - * for other purposes. - * @details - * Additional information: https://www.freertos.org/RTOS-task-notifications.html - * and general semaphore documentation. - */ -class BinarySemaphoreUsingTask: public SemaphoreIF, - public HasReturnvaluesIF { -public: - static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; - - //! @brief Default ctor - BinarySemaphoreUsingTask(); - //! @brief Default dtor - virtual~ BinarySemaphoreUsingTask(); - - ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, - uint32_t timeoutMs = portMAX_DELAY) override; - ReturnValue_t release() override; - uint8_t getSemaphoreCounter() const override; - static uint8_t getSemaphoreCounter(TaskHandle_t taskHandle); - static uint8_t getSemaphoreCounterFromISR(TaskHandle_t taskHandle, - BaseType_t* higherPriorityTaskWoken); - - /** - * Same as acquire() with timeout in FreeRTOS ticks. - * @param timeoutTicks - * @return - @c RETURN_OK on success - * - @c RETURN_FAILED on failure - */ - ReturnValue_t acquireWithTickTimeout( - TimeoutType timeoutType = TimeoutType::BLOCKING, - TickType_t timeoutTicks = portMAX_DELAY); - - /** - * Get handle to the task related to the semaphore. - * @return - */ - TaskHandle_t getTaskHandle(); - - /** - * Wrapper function to give back semaphore from handle - * @param semaphore - * @return - @c RETURN_OK on success - * - @c RETURN_FAILED on failure - */ - static ReturnValue_t release(TaskHandle_t taskToNotify); - - /** - * Wrapper function to give back semaphore from handle when called from an ISR - * @param semaphore - * @param higherPriorityTaskWoken This will be set to pdPASS if a task with - * a higher priority was unblocked. A context switch should be requested - * from an ISR if this is the case (see TaskManagement functions) - * @return - @c RETURN_OK on success - * - @c RETURN_FAILED on failure - */ - static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify, - BaseType_t * higherPriorityTaskWoken); - -protected: - TaskHandle_t handle; -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ +#define FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ + +#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../tasks/SemaphoreIF.h" + +#include +#include + +/** + * @brief Binary Semaphore implementation using the task notification value. + * The notification value should therefore not be used + * for other purposes. + * @details + * Additional information: https://www.freertos.org/RTOS-task-notifications.html + * and general semaphore documentation. + */ +class BinarySemaphoreUsingTask: public SemaphoreIF, + public HasReturnvaluesIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; + + //! @brief Default ctor + BinarySemaphoreUsingTask(); + //! @brief Default dtor + virtual~ BinarySemaphoreUsingTask(); + + ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, + uint32_t timeoutMs = portMAX_DELAY) override; + ReturnValue_t release() override; + uint8_t getSemaphoreCounter() const override; + static uint8_t getSemaphoreCounter(TaskHandle_t taskHandle); + static uint8_t getSemaphoreCounterFromISR(TaskHandle_t taskHandle, + BaseType_t* higherPriorityTaskWoken); + + /** + * Same as acquire() with timeout in FreeRTOS ticks. + * @param timeoutTicks + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + ReturnValue_t acquireWithTickTimeout( + TimeoutType timeoutType = TimeoutType::BLOCKING, + TickType_t timeoutTicks = portMAX_DELAY); + + /** + * Get handle to the task related to the semaphore. + * @return + */ + TaskHandle_t getTaskHandle(); + + /** + * Wrapper function to give back semaphore from handle + * @param semaphore + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + static ReturnValue_t release(TaskHandle_t taskToNotify); + + /** + * Wrapper function to give back semaphore from handle when called from an ISR + * @param semaphore + * @param higherPriorityTaskWoken This will be set to pdPASS if a task with + * a higher priority was unblocked. A context switch should be requested + * from an ISR if this is the case (see TaskManagement functions) + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify, + BaseType_t * higherPriorityTaskWoken); + +protected: + TaskHandle_t handle; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ */ diff --git a/osal/FreeRTOS/BinarySemaphore.cpp b/osal/FreeRTOS/BinarySemaphore.cpp index f1c78473..8cc3c495 100644 --- a/osal/FreeRTOS/BinarySemaphore.cpp +++ b/osal/FreeRTOS/BinarySemaphore.cpp @@ -1,108 +1,108 @@ -#include "../../osal/FreeRTOS/BinarySemaphore.h" -#include "../../osal/FreeRTOS/TaskManagement.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" - -BinarySemaphore::BinarySemaphore() { - handle = xSemaphoreCreateBinary(); - if(handle == nullptr) { - sif::error << "Semaphore: Binary semaph creation failure" << std::endl; - } - // Initiated semaphore must be given before it can be taken. - xSemaphoreGive(handle); -} - -BinarySemaphore::~BinarySemaphore() { - vSemaphoreDelete(handle); -} - -BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { - handle = xSemaphoreCreateBinary(); - if(handle == nullptr) { - sif::error << "Binary semaphore creation failure" << std::endl; - } - xSemaphoreGive(handle); -} - -BinarySemaphore& BinarySemaphore::operator =( - BinarySemaphore&& s) { - if(&s != this) { - handle = xSemaphoreCreateBinary(); - if(handle == nullptr) { - sif::error << "Binary semaphore creation failure" << std::endl; - } - xSemaphoreGive(handle); - } - return *this; -} - -ReturnValue_t BinarySemaphore::acquire(TimeoutType timeoutType, - uint32_t timeoutMs) { - TickType_t timeout = 0; - if(timeoutType == TimeoutType::POLLING) { - timeout = 0; - } - else if(timeoutType == TimeoutType::WAITING){ - timeout = pdMS_TO_TICKS(timeoutMs); - } - else { - timeout = portMAX_DELAY; - } - return acquireWithTickTimeout(timeoutType, timeout); -} - -ReturnValue_t BinarySemaphore::acquireWithTickTimeout(TimeoutType timeoutType, - TickType_t timeoutTicks) { - if(handle == nullptr) { - return SemaphoreIF::SEMAPHORE_INVALID; - } - - BaseType_t returncode = xSemaphoreTake(handle, timeoutTicks); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - return SemaphoreIF::SEMAPHORE_TIMEOUT; - } -} - -ReturnValue_t BinarySemaphore::release() { - return release(handle); -} - -ReturnValue_t BinarySemaphore::release(SemaphoreHandle_t semaphore) { - if (semaphore == nullptr) { - return SemaphoreIF::SEMAPHORE_INVALID; - } - BaseType_t returncode = xSemaphoreGive(semaphore); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - return SemaphoreIF::SEMAPHORE_NOT_OWNED; - } -} - -uint8_t BinarySemaphore::getSemaphoreCounter() const { - return uxSemaphoreGetCount(handle); -} - -SemaphoreHandle_t BinarySemaphore::getSemaphore() { - return handle; -} - - -// Be careful with the stack size here. This is called from an ISR! -ReturnValue_t BinarySemaphore::releaseFromISR( - SemaphoreHandle_t semaphore, BaseType_t * higherPriorityTaskWoken) { - if (semaphore == nullptr) { - return SemaphoreIF::SEMAPHORE_INVALID; - } - BaseType_t returncode = xSemaphoreGiveFromISR(semaphore, - higherPriorityTaskWoken); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - return SemaphoreIF::SEMAPHORE_NOT_OWNED; - } -} +#include "../../osal/FreeRTOS/BinarySemaphore.h" +#include "../../osal/FreeRTOS/TaskManagement.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +BinarySemaphore::BinarySemaphore() { + handle = xSemaphoreCreateBinary(); + if(handle == nullptr) { + sif::error << "Semaphore: Binary semaph creation failure" << std::endl; + } + // Initiated semaphore must be given before it can be taken. + xSemaphoreGive(handle); +} + +BinarySemaphore::~BinarySemaphore() { + vSemaphoreDelete(handle); +} + +BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { + handle = xSemaphoreCreateBinary(); + if(handle == nullptr) { + sif::error << "Binary semaphore creation failure" << std::endl; + } + xSemaphoreGive(handle); +} + +BinarySemaphore& BinarySemaphore::operator =( + BinarySemaphore&& s) { + if(&s != this) { + handle = xSemaphoreCreateBinary(); + if(handle == nullptr) { + sif::error << "Binary semaphore creation failure" << std::endl; + } + xSemaphoreGive(handle); + } + return *this; +} + +ReturnValue_t BinarySemaphore::acquire(TimeoutType timeoutType, + uint32_t timeoutMs) { + TickType_t timeout = 0; + if(timeoutType == TimeoutType::POLLING) { + timeout = 0; + } + else if(timeoutType == TimeoutType::WAITING){ + timeout = pdMS_TO_TICKS(timeoutMs); + } + else { + timeout = portMAX_DELAY; + } + return acquireWithTickTimeout(timeoutType, timeout); +} + +ReturnValue_t BinarySemaphore::acquireWithTickTimeout(TimeoutType timeoutType, + TickType_t timeoutTicks) { + if(handle == nullptr) { + return SemaphoreIF::SEMAPHORE_INVALID; + } + + BaseType_t returncode = xSemaphoreTake(handle, timeoutTicks); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SemaphoreIF::SEMAPHORE_TIMEOUT; + } +} + +ReturnValue_t BinarySemaphore::release() { + return release(handle); +} + +ReturnValue_t BinarySemaphore::release(SemaphoreHandle_t semaphore) { + if (semaphore == nullptr) { + return SemaphoreIF::SEMAPHORE_INVALID; + } + BaseType_t returncode = xSemaphoreGive(semaphore); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } +} + +uint8_t BinarySemaphore::getSemaphoreCounter() const { + return uxSemaphoreGetCount(handle); +} + +SemaphoreHandle_t BinarySemaphore::getSemaphore() { + return handle; +} + + +// Be careful with the stack size here. This is called from an ISR! +ReturnValue_t BinarySemaphore::releaseFromISR( + SemaphoreHandle_t semaphore, BaseType_t * higherPriorityTaskWoken) { + if (semaphore == nullptr) { + return SemaphoreIF::SEMAPHORE_INVALID; + } + BaseType_t returncode = xSemaphoreGiveFromISR(semaphore, + higherPriorityTaskWoken); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } +} diff --git a/osal/FreeRTOS/BinarySemaphore.h b/osal/FreeRTOS/BinarySemaphore.h index 5a32088a..c6cedc53 100644 --- a/osal/FreeRTOS/BinarySemaphore.h +++ b/osal/FreeRTOS/BinarySemaphore.h @@ -1,107 +1,107 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ -#define FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ - -#include "../../returnvalues/HasReturnvaluesIF.h" -#include "../../tasks/SemaphoreIF.h" - -#include -#include - -/** - * @brief OS Tool to achieve synchronization of between tasks or between - * task and ISR. The default semaphore implementation creates a - * binary semaphore, which can only be taken once. - * @details - * Documentation: https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html - * - * Please note that if the semaphore implementation is only related to - * the synchronization of one task, the new task notifications can be used, - * also see the BinSemaphUsingTask and CountingSemaphUsingTask classes. - * These use the task notification value instead of a queue and are - * faster and more efficient. - * - * @author R. Mueller - * @ingroup osal - */ -class BinarySemaphore: public SemaphoreIF, - public HasReturnvaluesIF { -public: - static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; - - //! @brief Default ctor - BinarySemaphore(); - //! @brief Copy ctor, deleted explicitely. - BinarySemaphore(const BinarySemaphore&) = delete; - //! @brief Copy assignment, deleted explicitely. - BinarySemaphore& operator=(const BinarySemaphore&) = delete; - //! @brief Move ctor - BinarySemaphore (BinarySemaphore &&); - //! @brief Move assignment - BinarySemaphore & operator=(BinarySemaphore &&); - //! @brief Destructor - virtual ~BinarySemaphore(); - - uint8_t getSemaphoreCounter() const override; - - /** - * Take the binary semaphore. - * If the semaphore has already been taken, the task will be blocked - * for a maximum of #timeoutMs or until the semaphore is given back, - * for example by an ISR or another task. - * @param timeoutMs - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout - */ - ReturnValue_t acquire(TimeoutType timeoutType = - TimeoutType::BLOCKING, uint32_t timeoutMs = portMAX_DELAY) override; - - /** - * Same as lockBinarySemaphore() with timeout in FreeRTOS ticks. - * @param timeoutTicks - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout - */ - ReturnValue_t acquireWithTickTimeout(TimeoutType timeoutType = - TimeoutType::BLOCKING, TickType_t timeoutTicks = portMAX_DELAY); - - /** - * Release the binary semaphore. - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is - * already available. - */ - ReturnValue_t release() override; - - /** - * Get Handle to the semaphore. - * @return - */ - SemaphoreHandle_t getSemaphore(); - - /** - * Wrapper function to give back semaphore from handle - * @param semaphore - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is - * already available. - */ - static ReturnValue_t release(SemaphoreHandle_t semaphore); - - /** - * Wrapper function to give back semaphore from handle when called from an ISR - * @param semaphore - * @param higherPriorityTaskWoken This will be set to pdPASS if a task with - * a higher priority was unblocked. A context switch from an ISR should - * then be requested (see TaskManagement functions) - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is - * already available. - */ - static ReturnValue_t releaseFromISR(SemaphoreHandle_t semaphore, - BaseType_t * higherPriorityTaskWoken); - -protected: - SemaphoreHandle_t handle; -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ +#define FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ + +#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../tasks/SemaphoreIF.h" + +#include +#include + +/** + * @brief OS Tool to achieve synchronization of between tasks or between + * task and ISR. The default semaphore implementation creates a + * binary semaphore, which can only be taken once. + * @details + * Documentation: https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html + * + * Please note that if the semaphore implementation is only related to + * the synchronization of one task, the new task notifications can be used, + * also see the BinSemaphUsingTask and CountingSemaphUsingTask classes. + * These use the task notification value instead of a queue and are + * faster and more efficient. + * + * @author R. Mueller + * @ingroup osal + */ +class BinarySemaphore: public SemaphoreIF, + public HasReturnvaluesIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; + + //! @brief Default ctor + BinarySemaphore(); + //! @brief Copy ctor, deleted explicitely. + BinarySemaphore(const BinarySemaphore&) = delete; + //! @brief Copy assignment, deleted explicitely. + BinarySemaphore& operator=(const BinarySemaphore&) = delete; + //! @brief Move ctor + BinarySemaphore (BinarySemaphore &&); + //! @brief Move assignment + BinarySemaphore & operator=(BinarySemaphore &&); + //! @brief Destructor + virtual ~BinarySemaphore(); + + uint8_t getSemaphoreCounter() const override; + + /** + * Take the binary semaphore. + * If the semaphore has already been taken, the task will be blocked + * for a maximum of #timeoutMs or until the semaphore is given back, + * for example by an ISR or another task. + * @param timeoutMs + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout + */ + ReturnValue_t acquire(TimeoutType timeoutType = + TimeoutType::BLOCKING, uint32_t timeoutMs = portMAX_DELAY) override; + + /** + * Same as lockBinarySemaphore() with timeout in FreeRTOS ticks. + * @param timeoutTicks + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout + */ + ReturnValue_t acquireWithTickTimeout(TimeoutType timeoutType = + TimeoutType::BLOCKING, TickType_t timeoutTicks = portMAX_DELAY); + + /** + * Release the binary semaphore. + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is + * already available. + */ + ReturnValue_t release() override; + + /** + * Get Handle to the semaphore. + * @return + */ + SemaphoreHandle_t getSemaphore(); + + /** + * Wrapper function to give back semaphore from handle + * @param semaphore + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is + * already available. + */ + static ReturnValue_t release(SemaphoreHandle_t semaphore); + + /** + * Wrapper function to give back semaphore from handle when called from an ISR + * @param semaphore + * @param higherPriorityTaskWoken This will be set to pdPASS if a task with + * a higher priority was unblocked. A context switch from an ISR should + * then be requested (see TaskManagement functions) + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is + * already available. + */ + static ReturnValue_t releaseFromISR(SemaphoreHandle_t semaphore, + BaseType_t * higherPriorityTaskWoken); + +protected: + SemaphoreHandle_t handle; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */ diff --git a/osal/FreeRTOS/CountingSemaphUsingTask.cpp b/osal/FreeRTOS/CountingSemaphUsingTask.cpp index e66671ac..a47341bc 100644 --- a/osal/FreeRTOS/CountingSemaphUsingTask.cpp +++ b/osal/FreeRTOS/CountingSemaphUsingTask.cpp @@ -1,114 +1,114 @@ -#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h" -#include "../../osal/FreeRTOS/TaskManagement.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" - -CountingSemaphoreUsingTask::CountingSemaphoreUsingTask(const uint8_t maxCount, - uint8_t initCount): maxCount(maxCount) { - if(initCount > maxCount) { - sif::error << "CountingSemaphoreUsingTask: Max count bigger than " - "intial cout. Setting initial count to max count." << std::endl; - initCount = maxCount; - } - - handle = TaskManagement::getCurrentTaskHandle(); - if(handle == nullptr) { - sif::error << "CountingSemaphoreUsingTask: Could not retrieve task " - "handle. Please ensure the constructor was called inside a " - "task." << std::endl; - } - - uint32_t oldNotificationValue; - xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, - &oldNotificationValue); - if(oldNotificationValue != 0) { - sif::warning << "CountinSemaphoreUsingTask: Semaphore initiated but " - "current notification value is not 0. Please ensure the " - "notification value is not used for other purposes!" << std::endl; - } - for(int i = 0; i < initCount; i++) { - xTaskNotifyGive(handle); - } -} - -CountingSemaphoreUsingTask::~CountingSemaphoreUsingTask() { - // Clear notification value on destruction. - // If this is not desired, don't call the destructor - // (or implement a boolean which disables the reset) - xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr); -} - -ReturnValue_t CountingSemaphoreUsingTask::acquire(TimeoutType timeoutType, - uint32_t timeoutMs) { - TickType_t timeout = 0; - if(timeoutType == TimeoutType::POLLING) { - timeout = 0; - } - else if(timeoutType == TimeoutType::WAITING){ - timeout = pdMS_TO_TICKS(timeoutMs); - } - else { - timeout = portMAX_DELAY; - } - return acquireWithTickTimeout(timeoutType, timeout); - -} - -ReturnValue_t CountingSemaphoreUsingTask::acquireWithTickTimeout( - TimeoutType timeoutType, TickType_t timeoutTicks) { - // Decrement notfication value without resetting it. - BaseType_t oldCount = ulTaskNotifyTake(pdFALSE, timeoutTicks); - if (getSemaphoreCounter() == oldCount - 1) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - return SemaphoreIF::SEMAPHORE_TIMEOUT; - } -} - -ReturnValue_t CountingSemaphoreUsingTask::release() { - if(getSemaphoreCounter() == maxCount) { - return SemaphoreIF::SEMAPHORE_NOT_OWNED; - } - return release(handle); -} - -ReturnValue_t CountingSemaphoreUsingTask::release( - TaskHandle_t taskToNotify) { - BaseType_t returncode = xTaskNotifyGive(taskToNotify); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - // This should never happen. - return HasReturnvaluesIF::RETURN_FAILED; - } -} - - -uint8_t CountingSemaphoreUsingTask::getSemaphoreCounter() const { - uint32_t notificationValue = 0; - xTaskNotifyAndQuery(handle, 0, eNoAction, ¬ificationValue); - return notificationValue; -} - -TaskHandle_t CountingSemaphoreUsingTask::getTaskHandle() { - return handle; -} - -ReturnValue_t CountingSemaphoreUsingTask::releaseFromISR( - TaskHandle_t taskToNotify, BaseType_t* higherPriorityTaskWoken) { - vTaskNotifyGiveFromISR(taskToNotify, higherPriorityTaskWoken); - return HasReturnvaluesIF::RETURN_OK; -} - -uint8_t CountingSemaphoreUsingTask::getSemaphoreCounterFromISR( - TaskHandle_t task, BaseType_t* higherPriorityTaskWoken) { - uint32_t notificationValue; - xTaskNotifyAndQueryFromISR(task, 0, eNoAction, ¬ificationValue, - higherPriorityTaskWoken); - return notificationValue; -} - -uint8_t CountingSemaphoreUsingTask::getMaxCount() const { - return maxCount; -} +#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h" +#include "../../osal/FreeRTOS/TaskManagement.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +CountingSemaphoreUsingTask::CountingSemaphoreUsingTask(const uint8_t maxCount, + uint8_t initCount): maxCount(maxCount) { + if(initCount > maxCount) { + sif::error << "CountingSemaphoreUsingTask: Max count bigger than " + "intial cout. Setting initial count to max count." << std::endl; + initCount = maxCount; + } + + handle = TaskManagement::getCurrentTaskHandle(); + if(handle == nullptr) { + sif::error << "CountingSemaphoreUsingTask: Could not retrieve task " + "handle. Please ensure the constructor was called inside a " + "task." << std::endl; + } + + uint32_t oldNotificationValue; + xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, + &oldNotificationValue); + if(oldNotificationValue != 0) { + sif::warning << "CountinSemaphoreUsingTask: Semaphore initiated but " + "current notification value is not 0. Please ensure the " + "notification value is not used for other purposes!" << std::endl; + } + for(int i = 0; i < initCount; i++) { + xTaskNotifyGive(handle); + } +} + +CountingSemaphoreUsingTask::~CountingSemaphoreUsingTask() { + // Clear notification value on destruction. + // If this is not desired, don't call the destructor + // (or implement a boolean which disables the reset) + xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr); +} + +ReturnValue_t CountingSemaphoreUsingTask::acquire(TimeoutType timeoutType, + uint32_t timeoutMs) { + TickType_t timeout = 0; + if(timeoutType == TimeoutType::POLLING) { + timeout = 0; + } + else if(timeoutType == TimeoutType::WAITING){ + timeout = pdMS_TO_TICKS(timeoutMs); + } + else { + timeout = portMAX_DELAY; + } + return acquireWithTickTimeout(timeoutType, timeout); + +} + +ReturnValue_t CountingSemaphoreUsingTask::acquireWithTickTimeout( + TimeoutType timeoutType, TickType_t timeoutTicks) { + // Decrement notfication value without resetting it. + BaseType_t oldCount = ulTaskNotifyTake(pdFALSE, timeoutTicks); + if (getSemaphoreCounter() == oldCount - 1) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SemaphoreIF::SEMAPHORE_TIMEOUT; + } +} + +ReturnValue_t CountingSemaphoreUsingTask::release() { + if(getSemaphoreCounter() == maxCount) { + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } + return release(handle); +} + +ReturnValue_t CountingSemaphoreUsingTask::release( + TaskHandle_t taskToNotify) { + BaseType_t returncode = xTaskNotifyGive(taskToNotify); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + // This should never happen. + return HasReturnvaluesIF::RETURN_FAILED; + } +} + + +uint8_t CountingSemaphoreUsingTask::getSemaphoreCounter() const { + uint32_t notificationValue = 0; + xTaskNotifyAndQuery(handle, 0, eNoAction, ¬ificationValue); + return notificationValue; +} + +TaskHandle_t CountingSemaphoreUsingTask::getTaskHandle() { + return handle; +} + +ReturnValue_t CountingSemaphoreUsingTask::releaseFromISR( + TaskHandle_t taskToNotify, BaseType_t* higherPriorityTaskWoken) { + vTaskNotifyGiveFromISR(taskToNotify, higherPriorityTaskWoken); + return HasReturnvaluesIF::RETURN_OK; +} + +uint8_t CountingSemaphoreUsingTask::getSemaphoreCounterFromISR( + TaskHandle_t task, BaseType_t* higherPriorityTaskWoken) { + uint32_t notificationValue; + xTaskNotifyAndQueryFromISR(task, 0, eNoAction, ¬ificationValue, + higherPriorityTaskWoken); + return notificationValue; +} + +uint8_t CountingSemaphoreUsingTask::getMaxCount() const { + return maxCount; +} diff --git a/osal/FreeRTOS/CountingSemaphUsingTask.h b/osal/FreeRTOS/CountingSemaphUsingTask.h index e3733382..8977258c 100644 --- a/osal/FreeRTOS/CountingSemaphUsingTask.h +++ b/osal/FreeRTOS/CountingSemaphUsingTask.h @@ -1,102 +1,102 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ -#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ - -#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h" -#include "../../tasks/SemaphoreIF.h" - -extern "C" { -#include -#include -} - -/** - * @brief Couting Semaphore implementation which uses the notification value - * of the task. The notification value should therefore not be used - * for other purposes. - * @details - * Additional information: https://www.freertos.org/RTOS-task-notifications.html - * and general semaphore documentation. - */ -class CountingSemaphoreUsingTask: public SemaphoreIF { -public: - CountingSemaphoreUsingTask(const uint8_t maxCount, uint8_t initCount); - virtual ~CountingSemaphoreUsingTask(); - - /** - * Acquire the counting semaphore. - * If no semaphores are available, the task will be blocked - * for a maximum of #timeoutMs or until one is given back, - * for example by an ISR or another task. - * @param timeoutMs - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout - */ - ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, - uint32_t timeoutMs = portMAX_DELAY) override; - - /** - * Release a semaphore, increasing the number of available counting - * semaphores up to the #maxCount value. - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are - * already available. - */ - ReturnValue_t release() override; - - uint8_t getSemaphoreCounter() const override; - /** - * Get the semaphore counter from an ISR. - * @param task - * @param higherPriorityTaskWoken This will be set to pdPASS if a task with - * a higher priority was unblocked. A context switch should be requested - * from an ISR if this is the case (see TaskManagement functions) - * @return - */ - static uint8_t getSemaphoreCounterFromISR(TaskHandle_t task, - BaseType_t* higherPriorityTaskWoken); - - /** - * Acquire with a timeout value in ticks - * @param timeoutTicks - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout - */ - ReturnValue_t acquireWithTickTimeout( - TimeoutType timeoutType = TimeoutType::BLOCKING, - TickType_t timeoutTicks = portMAX_DELAY); - - /** - * Get handle to the task related to the semaphore. - * @return - */ - TaskHandle_t getTaskHandle(); - - /** - * Release semaphore of task by supplying task handle - * @param taskToNotify - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are - * already available. - */ - static ReturnValue_t release(TaskHandle_t taskToNotify); - /** - * Release seamphore of a task from an ISR. - * @param taskToNotify - * @param higherPriorityTaskWoken This will be set to pdPASS if a task with - * a higher priority was unblocked. A context switch should be requested - * from an ISR if this is the case (see TaskManagement functions) - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are - * already available. - */ - static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify, - BaseType_t* higherPriorityTaskWoken); - - uint8_t getMaxCount() const; - -private: - TaskHandle_t handle; - const uint8_t maxCount; -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ +#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ + +#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h" +#include "../../tasks/SemaphoreIF.h" + +extern "C" { +#include +#include +} + +/** + * @brief Couting Semaphore implementation which uses the notification value + * of the task. The notification value should therefore not be used + * for other purposes. + * @details + * Additional information: https://www.freertos.org/RTOS-task-notifications.html + * and general semaphore documentation. + */ +class CountingSemaphoreUsingTask: public SemaphoreIF { +public: + CountingSemaphoreUsingTask(const uint8_t maxCount, uint8_t initCount); + virtual ~CountingSemaphoreUsingTask(); + + /** + * Acquire the counting semaphore. + * If no semaphores are available, the task will be blocked + * for a maximum of #timeoutMs or until one is given back, + * for example by an ISR or another task. + * @param timeoutMs + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout + */ + ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, + uint32_t timeoutMs = portMAX_DELAY) override; + + /** + * Release a semaphore, increasing the number of available counting + * semaphores up to the #maxCount value. + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are + * already available. + */ + ReturnValue_t release() override; + + uint8_t getSemaphoreCounter() const override; + /** + * Get the semaphore counter from an ISR. + * @param task + * @param higherPriorityTaskWoken This will be set to pdPASS if a task with + * a higher priority was unblocked. A context switch should be requested + * from an ISR if this is the case (see TaskManagement functions) + * @return + */ + static uint8_t getSemaphoreCounterFromISR(TaskHandle_t task, + BaseType_t* higherPriorityTaskWoken); + + /** + * Acquire with a timeout value in ticks + * @param timeoutTicks + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout + */ + ReturnValue_t acquireWithTickTimeout( + TimeoutType timeoutType = TimeoutType::BLOCKING, + TickType_t timeoutTicks = portMAX_DELAY); + + /** + * Get handle to the task related to the semaphore. + * @return + */ + TaskHandle_t getTaskHandle(); + + /** + * Release semaphore of task by supplying task handle + * @param taskToNotify + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are + * already available. + */ + static ReturnValue_t release(TaskHandle_t taskToNotify); + /** + * Release seamphore of a task from an ISR. + * @param taskToNotify + * @param higherPriorityTaskWoken This will be set to pdPASS if a task with + * a higher priority was unblocked. A context switch should be requested + * from an ISR if this is the case (see TaskManagement functions) + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are + * already available. + */ + static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify, + BaseType_t* higherPriorityTaskWoken); + + uint8_t getMaxCount() const; + +private: + TaskHandle_t handle; + const uint8_t maxCount; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ */ diff --git a/osal/FreeRTOS/CountingSemaphore.cpp b/osal/FreeRTOS/CountingSemaphore.cpp index 0b218e54..d1310a6a 100644 --- a/osal/FreeRTOS/CountingSemaphore.cpp +++ b/osal/FreeRTOS/CountingSemaphore.cpp @@ -1,43 +1,43 @@ -#include "../../osal/FreeRTOS/CountingSemaphore.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" -#include "../../osal/FreeRTOS/TaskManagement.h" - -#include - -// Make sure #define configUSE_COUNTING_SEMAPHORES 1 is set in -// free FreeRTOSConfig.h file. -CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount): - maxCount(maxCount), initCount(initCount) { - if(initCount > maxCount) { - sif::error << "CountingSemaphoreUsingTask: Max count bigger than " - "intial cout. Setting initial count to max count." << std::endl; - initCount = maxCount; - } - - handle = xSemaphoreCreateCounting(maxCount, initCount); - if(handle == nullptr) { - sif::error << "CountingSemaphore: Creation failure" << std::endl; - } -} - -CountingSemaphore::CountingSemaphore(CountingSemaphore&& other): - maxCount(other.maxCount), initCount(other.initCount) { - handle = xSemaphoreCreateCounting(other.maxCount, other.initCount); - if(handle == nullptr) { - sif::error << "CountingSemaphore: Creation failure" << std::endl; - } -} - -CountingSemaphore& CountingSemaphore::operator =( - CountingSemaphore&& other) { - handle = xSemaphoreCreateCounting(other.maxCount, other.initCount); - if(handle == nullptr) { - sif::error << "CountingSemaphore: Creation failure" << std::endl; - } - return * this; -} - - -uint8_t CountingSemaphore::getMaxCount() const { - return maxCount; -} +#include "../../osal/FreeRTOS/CountingSemaphore.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../osal/FreeRTOS/TaskManagement.h" + +#include + +// Make sure #define configUSE_COUNTING_SEMAPHORES 1 is set in +// free FreeRTOSConfig.h file. +CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount): + maxCount(maxCount), initCount(initCount) { + if(initCount > maxCount) { + sif::error << "CountingSemaphoreUsingTask: Max count bigger than " + "intial cout. Setting initial count to max count." << std::endl; + initCount = maxCount; + } + + handle = xSemaphoreCreateCounting(maxCount, initCount); + if(handle == nullptr) { + sif::error << "CountingSemaphore: Creation failure" << std::endl; + } +} + +CountingSemaphore::CountingSemaphore(CountingSemaphore&& other): + maxCount(other.maxCount), initCount(other.initCount) { + handle = xSemaphoreCreateCounting(other.maxCount, other.initCount); + if(handle == nullptr) { + sif::error << "CountingSemaphore: Creation failure" << std::endl; + } +} + +CountingSemaphore& CountingSemaphore::operator =( + CountingSemaphore&& other) { + handle = xSemaphoreCreateCounting(other.maxCount, other.initCount); + if(handle == nullptr) { + sif::error << "CountingSemaphore: Creation failure" << std::endl; + } + return * this; +} + + +uint8_t CountingSemaphore::getMaxCount() const { + return maxCount; +} diff --git a/osal/FreeRTOS/CountingSemaphore.h b/osal/FreeRTOS/CountingSemaphore.h index 9432ed81..ae2f62ae 100644 --- a/osal/FreeRTOS/CountingSemaphore.h +++ b/osal/FreeRTOS/CountingSemaphore.h @@ -1,34 +1,34 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ -#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ -#include "../../osal/FreeRTOS/BinarySemaphore.h" - -/** - * @brief Counting semaphores, which can be acquire more than once. - * @details - * See: https://www.freertos.org/CreateCounting.html - * API of counting semaphores is almost identical to binary semaphores, - * so we just inherit from binary semaphore and provide the respective - * constructors. - */ -class CountingSemaphore: public BinarySemaphore { -public: - CountingSemaphore(const uint8_t maxCount, uint8_t initCount); - //! @brief Copy ctor, disabled - CountingSemaphore(const CountingSemaphore&) = delete; - //! @brief Copy assignment, disabled - CountingSemaphore& operator=(const CountingSemaphore&) = delete; - //! @brief Move ctor - CountingSemaphore (CountingSemaphore &&); - //! @brief Move assignment - CountingSemaphore & operator=(CountingSemaphore &&); - - /* Same API as binary semaphore otherwise. acquire() can be called - * until there are not semaphores left and release() can be called - * until maxCount is reached. */ - uint8_t getMaxCount() const; -private: - const uint8_t maxCount; - uint8_t initCount = 0; -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ +#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ +#include "../../osal/FreeRTOS/BinarySemaphore.h" + +/** + * @brief Counting semaphores, which can be acquire more than once. + * @details + * See: https://www.freertos.org/CreateCounting.html + * API of counting semaphores is almost identical to binary semaphores, + * so we just inherit from binary semaphore and provide the respective + * constructors. + */ +class CountingSemaphore: public BinarySemaphore { +public: + CountingSemaphore(const uint8_t maxCount, uint8_t initCount); + //! @brief Copy ctor, disabled + CountingSemaphore(const CountingSemaphore&) = delete; + //! @brief Copy assignment, disabled + CountingSemaphore& operator=(const CountingSemaphore&) = delete; + //! @brief Move ctor + CountingSemaphore (CountingSemaphore &&); + //! @brief Move assignment + CountingSemaphore & operator=(CountingSemaphore &&); + + /* Same API as binary semaphore otherwise. acquire() can be called + * until there are not semaphores left and release() can be called + * until maxCount is reached. */ + uint8_t getMaxCount() const; +private: + const uint8_t maxCount; + uint8_t initCount = 0; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */ diff --git a/osal/FreeRTOS/SemaphoreFactory.cpp b/osal/FreeRTOS/SemaphoreFactory.cpp index 8575cf4a..beb0d096 100644 --- a/osal/FreeRTOS/SemaphoreFactory.cpp +++ b/osal/FreeRTOS/SemaphoreFactory.cpp @@ -1,59 +1,59 @@ -#include "../../osal/FreeRTOS/BinarySemaphore.h" -#include "../../osal/FreeRTOS/BinSemaphUsingTask.h" -#include "../../osal/FreeRTOS/CountingSemaphore.h" -#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h" -#include "../../tasks/SemaphoreFactory.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" - -SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; - -static const uint32_t USE_REGULAR_SEMAPHORES = 0; -static const uint32_t USE_TASK_NOTIFICATIONS = 1; - -SemaphoreFactory::SemaphoreFactory() { -} - -SemaphoreFactory::~SemaphoreFactory() { - delete factoryInstance; -} - -SemaphoreFactory* SemaphoreFactory::instance() { - if (factoryInstance == nullptr){ - factoryInstance = new SemaphoreFactory(); - } - return SemaphoreFactory::factoryInstance; -} - -SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t argument) { - if(argument == USE_REGULAR_SEMAPHORES) { - return new BinarySemaphore(); - } - else if(argument == USE_TASK_NOTIFICATIONS) { - return new BinarySemaphoreUsingTask(); - } - else { - sif::warning << "SemaphoreFactory: Invalid argument, return regular" - "binary semaphore" << std::endl; - return new BinarySemaphore(); - } -} - -SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t maxCount, - uint8_t initCount, uint32_t argument) { - if(argument == USE_REGULAR_SEMAPHORES) { - return new CountingSemaphore(maxCount, initCount); - } - else if(argument == USE_TASK_NOTIFICATIONS) { - return new CountingSemaphoreUsingTask(maxCount, initCount); - } - else { - sif::warning << "SemaphoreFactory: Invalid argument, return regular" - "binary semaphore" << std::endl; - return new CountingSemaphore(maxCount, initCount); - } - -} - -void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { - delete semaphore; -} +#include "../../osal/FreeRTOS/BinarySemaphore.h" +#include "../../osal/FreeRTOS/BinSemaphUsingTask.h" +#include "../../osal/FreeRTOS/CountingSemaphore.h" +#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h" +#include "../../tasks/SemaphoreFactory.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; + +static const uint32_t USE_REGULAR_SEMAPHORES = 0; +static const uint32_t USE_TASK_NOTIFICATIONS = 1; + +SemaphoreFactory::SemaphoreFactory() { +} + +SemaphoreFactory::~SemaphoreFactory() { + delete factoryInstance; +} + +SemaphoreFactory* SemaphoreFactory::instance() { + if (factoryInstance == nullptr){ + factoryInstance = new SemaphoreFactory(); + } + return SemaphoreFactory::factoryInstance; +} + +SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t argument) { + if(argument == USE_REGULAR_SEMAPHORES) { + return new BinarySemaphore(); + } + else if(argument == USE_TASK_NOTIFICATIONS) { + return new BinarySemaphoreUsingTask(); + } + else { + sif::warning << "SemaphoreFactory: Invalid argument, return regular" + "binary semaphore" << std::endl; + return new BinarySemaphore(); + } +} + +SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t maxCount, + uint8_t initCount, uint32_t argument) { + if(argument == USE_REGULAR_SEMAPHORES) { + return new CountingSemaphore(maxCount, initCount); + } + else if(argument == USE_TASK_NOTIFICATIONS) { + return new CountingSemaphoreUsingTask(maxCount, initCount); + } + else { + sif::warning << "SemaphoreFactory: Invalid argument, return regular" + "binary semaphore" << std::endl; + return new CountingSemaphore(maxCount, initCount); + } + +} + +void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { + delete semaphore; +} diff --git a/osal/FreeRTOS/TaskManagement.cpp b/osal/FreeRTOS/TaskManagement.cpp index 16682d36..b77f12a9 100644 --- a/osal/FreeRTOS/TaskManagement.cpp +++ b/osal/FreeRTOS/TaskManagement.cpp @@ -1,24 +1,24 @@ -#include "../../osal/FreeRTOS/TaskManagement.h" - -void TaskManagement::vRequestContextSwitchFromTask() { - vTaskDelay(0); -} - -void TaskManagement::requestContextSwitch( - CallContext callContext = CallContext::TASK) { - if(callContext == CallContext::ISR) { - // This function depends on the partmacro.h definition for the specific device - vRequestContextSwitchFromISR(); - } else { - vRequestContextSwitchFromTask(); - } -} - -TaskHandle_t TaskManagement::getCurrentTaskHandle() { - return xTaskGetCurrentTaskHandle(); -} - -size_t TaskManagement::getTaskStackHighWatermark( - TaskHandle_t task) { - return uxTaskGetStackHighWaterMark(task) * sizeof(StackType_t); -} +#include "../../osal/FreeRTOS/TaskManagement.h" + +void TaskManagement::vRequestContextSwitchFromTask() { + vTaskDelay(0); +} + +void TaskManagement::requestContextSwitch( + CallContext callContext = CallContext::TASK) { + if(callContext == CallContext::ISR) { + // This function depends on the partmacro.h definition for the specific device + vRequestContextSwitchFromISR(); + } else { + vRequestContextSwitchFromTask(); + } +} + +TaskHandle_t TaskManagement::getCurrentTaskHandle() { + return xTaskGetCurrentTaskHandle(); +} + +size_t TaskManagement::getTaskStackHighWatermark( + TaskHandle_t task) { + return uxTaskGetStackHighWaterMark(task) * sizeof(StackType_t); +} diff --git a/osal/FreeRTOS/TaskManagement.h b/osal/FreeRTOS/TaskManagement.h index 43003d76..4b7fe3eb 100644 --- a/osal/FreeRTOS/TaskManagement.h +++ b/osal/FreeRTOS/TaskManagement.h @@ -1,64 +1,64 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ -#define FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ - -#include "../../returnvalues/HasReturnvaluesIF.h" - -extern "C" { -#include -#include -} -#include - -/** - * Architecture dependant portmacro.h function call. - * Should be implemented in bsp. - */ -extern void vRequestContextSwitchFromISR(); - -/*! - * Used by functions to tell if they are being called from - * within an ISR or from a regular task. This is required because FreeRTOS - * has different functions for handling semaphores and messages from within - * an ISR and task. - */ -enum class CallContext { - TASK = 0x00,//!< task_context - ISR = 0xFF //!< isr_context -}; - - -class TaskManagement { -public: - /** - * @brief In this function, a function dependant on the portmacro.h header - * function calls to request a context switch can be specified. - * This can be used if sending to the queue from an ISR caused a task - * to unblock and a context switch is required. - */ - static void requestContextSwitch(CallContext callContext); - - /** - * If task preemption in FreeRTOS is disabled, a context switch - * can be requested manually by calling this function. - */ - static void vRequestContextSwitchFromTask(void); - - /** - * @return The current task handle - */ - static TaskHandle_t getCurrentTaskHandle(); - - /** - * Get returns the minimum amount of remaining stack space in words - * that was a available to the task since the task started executing. - * Please note that the actual value in bytes depends - * on the stack depth type. - * E.g. on a 32 bit machine, a value of 200 means 800 bytes. - * @return Smallest value of stack remaining since the task was started in - * words. - */ - static size_t getTaskStackHighWatermark( - TaskHandle_t task = nullptr); -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ +#define FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ + +#include "../../returnvalues/HasReturnvaluesIF.h" + +extern "C" { +#include +#include +} +#include + +/** + * Architecture dependant portmacro.h function call. + * Should be implemented in bsp. + */ +extern void vRequestContextSwitchFromISR(); + +/*! + * Used by functions to tell if they are being called from + * within an ISR or from a regular task. This is required because FreeRTOS + * has different functions for handling semaphores and messages from within + * an ISR and task. + */ +enum class CallContext { + TASK = 0x00,//!< task_context + ISR = 0xFF //!< isr_context +}; + + +class TaskManagement { +public: + /** + * @brief In this function, a function dependant on the portmacro.h header + * function calls to request a context switch can be specified. + * This can be used if sending to the queue from an ISR caused a task + * to unblock and a context switch is required. + */ + static void requestContextSwitch(CallContext callContext); + + /** + * If task preemption in FreeRTOS is disabled, a context switch + * can be requested manually by calling this function. + */ + static void vRequestContextSwitchFromTask(void); + + /** + * @return The current task handle + */ + static TaskHandle_t getCurrentTaskHandle(); + + /** + * Get returns the minimum amount of remaining stack space in words + * that was a available to the task since the task started executing. + * Please note that the actual value in bytes depends + * on the stack depth type. + * E.g. on a 32 bit machine, a value of 200 means 800 bytes. + * @return Smallest value of stack remaining since the task was started in + * words. + */ + static size_t getTaskStackHighWatermark( + TaskHandle_t task = nullptr); +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */ diff --git a/osal/linux/BinarySemaphore.cpp b/osal/linux/BinarySemaphore.cpp index 5216ff37..8c0eeae7 100644 --- a/osal/linux/BinarySemaphore.cpp +++ b/osal/linux/BinarySemaphore.cpp @@ -1,149 +1,149 @@ -#include "../../osal/linux/BinarySemaphore.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" - -extern "C" { -#include -#include -} - -BinarySemaphore::BinarySemaphore() { - // Using unnamed semaphores for now - initSemaphore(); -} - -BinarySemaphore::~BinarySemaphore() { - sem_destroy(&handle); -} - -BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { - initSemaphore(); -} - -BinarySemaphore& BinarySemaphore::operator =( - BinarySemaphore&& s) { - initSemaphore(); - return * this; -} - -ReturnValue_t BinarySemaphore::acquire(TimeoutType timeoutType, - uint32_t timeoutMs) { - int result = 0; - if(timeoutType == TimeoutType::POLLING) { - result = sem_trywait(&handle); - } - else if(timeoutType == TimeoutType::BLOCKING) { - result = sem_wait(&handle); - } - else if(timeoutType == TimeoutType::WAITING){ - timespec timeOut; - clock_gettime(CLOCK_REALTIME, &timeOut); - uint64_t nseconds = timeOut.tv_sec * 1000000000 + timeOut.tv_nsec; - nseconds += timeoutMs * 1000000; - timeOut.tv_sec = nseconds / 1000000000; - timeOut.tv_nsec = nseconds - timeOut.tv_sec * 1000000000; - result = sem_timedwait(&handle, &timeOut); - if(result != 0 and errno == EINVAL) { - sif::debug << "BinarySemaphore::acquire: Invalid time value possible" - << std::endl; - } - } - if(result == 0) { - return HasReturnvaluesIF::RETURN_OK; - } - - switch(errno) { - case(EAGAIN): - // Operation could not be performed without blocking (for sem_trywait) - case(ETIMEDOUT): - // Semaphore is 0 - return SemaphoreIF::SEMAPHORE_TIMEOUT; - case(EINVAL): - // Semaphore invalid - return SemaphoreIF::SEMAPHORE_INVALID; - case(EINTR): - // Call was interrupted by signal handler - sif::debug << "BinarySemaphore::acquire: Signal handler interrupted." - "Code " << strerror(errno) << std::endl; - /* No break */ - default: - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -ReturnValue_t BinarySemaphore::release() { - return BinarySemaphore::release(&this->handle); -} - -ReturnValue_t BinarySemaphore::release(sem_t *handle) { - ReturnValue_t countResult = checkCount(handle, 1); - if(countResult != HasReturnvaluesIF::RETURN_OK) { - return countResult; - } - - int result = sem_post(handle); - if(result == 0) { - return HasReturnvaluesIF::RETURN_OK; - } - - switch(errno) { - case(EINVAL): - // Semaphore invalid - return SemaphoreIF::SEMAPHORE_INVALID; - case(EOVERFLOW): - // SEM_MAX_VALUE overflow. This should never happen - default: - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -uint8_t BinarySemaphore::getSemaphoreCounter() const { - // And another ugly cast :-D - return getSemaphoreCounter(const_cast(&this->handle)); -} - -uint8_t BinarySemaphore::getSemaphoreCounter(sem_t *handle) { - int value = 0; - int result = sem_getvalue(handle, &value); - if (result == 0) { - return value; - } - else if(result != 0 and errno == EINVAL) { - // Could be called from interrupt, use lightweight printf - printf("BinarySemaphore::getSemaphoreCounter: Invalid semaphore\n"); - return 0; - } - else { - // This should never happen. - return 0; - } -} - -void BinarySemaphore::initSemaphore(uint8_t initCount) { - auto result = sem_init(&handle, true, initCount); - if(result == -1) { - switch(errno) { - case(EINVAL): - // Value exceeds SEM_VALUE_MAX - case(ENOSYS): - // System does not support process-shared semaphores - sif::error << "BinarySemaphore: Init failed with" << strerror(errno) - << std::endl; - } - } -} - -ReturnValue_t BinarySemaphore::checkCount(sem_t* handle, uint8_t maxCount) { - int value = getSemaphoreCounter(handle); - if(value >= maxCount) { - if(maxCount == 1 and value > 1) { - // Binary Semaphore special case. - // This is a config error use lightweight printf is this is called - // from an interrupt - printf("BinarySemaphore::release: Value of binary semaphore greater" - " than 1!\n"); - return HasReturnvaluesIF::RETURN_FAILED; - } - return SemaphoreIF::SEMAPHORE_NOT_OWNED; - } - return HasReturnvaluesIF::RETURN_OK; -} +#include "../../osal/linux/BinarySemaphore.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +extern "C" { +#include +#include +} + +BinarySemaphore::BinarySemaphore() { + // Using unnamed semaphores for now + initSemaphore(); +} + +BinarySemaphore::~BinarySemaphore() { + sem_destroy(&handle); +} + +BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { + initSemaphore(); +} + +BinarySemaphore& BinarySemaphore::operator =( + BinarySemaphore&& s) { + initSemaphore(); + return * this; +} + +ReturnValue_t BinarySemaphore::acquire(TimeoutType timeoutType, + uint32_t timeoutMs) { + int result = 0; + if(timeoutType == TimeoutType::POLLING) { + result = sem_trywait(&handle); + } + else if(timeoutType == TimeoutType::BLOCKING) { + result = sem_wait(&handle); + } + else if(timeoutType == TimeoutType::WAITING){ + timespec timeOut; + clock_gettime(CLOCK_REALTIME, &timeOut); + uint64_t nseconds = timeOut.tv_sec * 1000000000 + timeOut.tv_nsec; + nseconds += timeoutMs * 1000000; + timeOut.tv_sec = nseconds / 1000000000; + timeOut.tv_nsec = nseconds - timeOut.tv_sec * 1000000000; + result = sem_timedwait(&handle, &timeOut); + if(result != 0 and errno == EINVAL) { + sif::debug << "BinarySemaphore::acquire: Invalid time value possible" + << std::endl; + } + } + if(result == 0) { + return HasReturnvaluesIF::RETURN_OK; + } + + switch(errno) { + case(EAGAIN): + // Operation could not be performed without blocking (for sem_trywait) + case(ETIMEDOUT): + // Semaphore is 0 + return SemaphoreIF::SEMAPHORE_TIMEOUT; + case(EINVAL): + // Semaphore invalid + return SemaphoreIF::SEMAPHORE_INVALID; + case(EINTR): + // Call was interrupted by signal handler + sif::debug << "BinarySemaphore::acquire: Signal handler interrupted." + "Code " << strerror(errno) << std::endl; + /* No break */ + default: + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +ReturnValue_t BinarySemaphore::release() { + return BinarySemaphore::release(&this->handle); +} + +ReturnValue_t BinarySemaphore::release(sem_t *handle) { + ReturnValue_t countResult = checkCount(handle, 1); + if(countResult != HasReturnvaluesIF::RETURN_OK) { + return countResult; + } + + int result = sem_post(handle); + if(result == 0) { + return HasReturnvaluesIF::RETURN_OK; + } + + switch(errno) { + case(EINVAL): + // Semaphore invalid + return SemaphoreIF::SEMAPHORE_INVALID; + case(EOVERFLOW): + // SEM_MAX_VALUE overflow. This should never happen + default: + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +uint8_t BinarySemaphore::getSemaphoreCounter() const { + // And another ugly cast :-D + return getSemaphoreCounter(const_cast(&this->handle)); +} + +uint8_t BinarySemaphore::getSemaphoreCounter(sem_t *handle) { + int value = 0; + int result = sem_getvalue(handle, &value); + if (result == 0) { + return value; + } + else if(result != 0 and errno == EINVAL) { + // Could be called from interrupt, use lightweight printf + printf("BinarySemaphore::getSemaphoreCounter: Invalid semaphore\n"); + return 0; + } + else { + // This should never happen. + return 0; + } +} + +void BinarySemaphore::initSemaphore(uint8_t initCount) { + auto result = sem_init(&handle, true, initCount); + if(result == -1) { + switch(errno) { + case(EINVAL): + // Value exceeds SEM_VALUE_MAX + case(ENOSYS): + // System does not support process-shared semaphores + sif::error << "BinarySemaphore: Init failed with" << strerror(errno) + << std::endl; + } + } +} + +ReturnValue_t BinarySemaphore::checkCount(sem_t* handle, uint8_t maxCount) { + int value = getSemaphoreCounter(handle); + if(value >= maxCount) { + if(maxCount == 1 and value > 1) { + // Binary Semaphore special case. + // This is a config error use lightweight printf is this is called + // from an interrupt + printf("BinarySemaphore::release: Value of binary semaphore greater" + " than 1!\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/osal/linux/BinarySemaphore.h b/osal/linux/BinarySemaphore.h index 4181de85..e9bb8bb6 100644 --- a/osal/linux/BinarySemaphore.h +++ b/osal/linux/BinarySemaphore.h @@ -1,81 +1,81 @@ -#ifndef FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_ -#define FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_ - -#include "../../returnvalues/HasReturnvaluesIF.h" -#include "../../tasks/SemaphoreIF.h" - -extern "C" { -#include -} - -/** - * @brief OS Tool to achieve synchronization of between tasks or between - * task and ISR. The default semaphore implementation creates a - * binary semaphore, which can only be taken once. - * @details - * See: http://www.man7.org/linux/man-pages/man7/sem_overview.7.html - * @author R. Mueller - * @ingroup osal - */ -class BinarySemaphore: public SemaphoreIF, - public HasReturnvaluesIF { -public: - static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; - - //! @brief Default ctor - BinarySemaphore(); - //! @brief Copy ctor, deleted explicitely. - BinarySemaphore(const BinarySemaphore&) = delete; - //! @brief Copy assignment, deleted explicitely. - BinarySemaphore& operator=(const BinarySemaphore&) = delete; - //! @brief Move ctor - BinarySemaphore (BinarySemaphore &&); - //! @brief Move assignment - BinarySemaphore & operator=(BinarySemaphore &&); - //! @brief Destructor - virtual ~BinarySemaphore(); - - void initSemaphore(uint8_t initCount = 1); - - uint8_t getSemaphoreCounter() const override; - static uint8_t getSemaphoreCounter(sem_t* handle); - - /** - * Take the binary semaphore. - * If the semaphore has already been taken, the task will be blocked - * for a maximum of #timeoutMs or until the semaphore is given back, - * for example by an ISR or another task. - * @param timeoutMs - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout - */ - ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, - uint32_t timeoutMs = 0) override; - - /** - * Release the binary semaphore. - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is - * already available. - */ - virtual ReturnValue_t release() override; - /** - * This static function can be used to release a semaphore by providing - * its handle. - * @param handle - * @return - */ - static ReturnValue_t release(sem_t* handle); - - /** Checks the validity of the semaphore count against a specified - * known maxCount - * @param handle - * @param maxCount - * @return - */ - static ReturnValue_t checkCount(sem_t* handle, uint8_t maxCount); -protected: - sem_t handle; -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */ +#ifndef FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_ +#define FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_ + +#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../tasks/SemaphoreIF.h" + +extern "C" { +#include +} + +/** + * @brief OS Tool to achieve synchronization of between tasks or between + * task and ISR. The default semaphore implementation creates a + * binary semaphore, which can only be taken once. + * @details + * See: http://www.man7.org/linux/man-pages/man7/sem_overview.7.html + * @author R. Mueller + * @ingroup osal + */ +class BinarySemaphore: public SemaphoreIF, + public HasReturnvaluesIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; + + //! @brief Default ctor + BinarySemaphore(); + //! @brief Copy ctor, deleted explicitely. + BinarySemaphore(const BinarySemaphore&) = delete; + //! @brief Copy assignment, deleted explicitely. + BinarySemaphore& operator=(const BinarySemaphore&) = delete; + //! @brief Move ctor + BinarySemaphore (BinarySemaphore &&); + //! @brief Move assignment + BinarySemaphore & operator=(BinarySemaphore &&); + //! @brief Destructor + virtual ~BinarySemaphore(); + + void initSemaphore(uint8_t initCount = 1); + + uint8_t getSemaphoreCounter() const override; + static uint8_t getSemaphoreCounter(sem_t* handle); + + /** + * Take the binary semaphore. + * If the semaphore has already been taken, the task will be blocked + * for a maximum of #timeoutMs or until the semaphore is given back, + * for example by an ISR or another task. + * @param timeoutMs + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout + */ + ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, + uint32_t timeoutMs = 0) override; + + /** + * Release the binary semaphore. + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is + * already available. + */ + virtual ReturnValue_t release() override; + /** + * This static function can be used to release a semaphore by providing + * its handle. + * @param handle + * @return + */ + static ReturnValue_t release(sem_t* handle); + + /** Checks the validity of the semaphore count against a specified + * known maxCount + * @param handle + * @param maxCount + * @return + */ + static ReturnValue_t checkCount(sem_t* handle, uint8_t maxCount); +protected: + sem_t handle; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */ diff --git a/osal/linux/CountingSemaphore.cpp b/osal/linux/CountingSemaphore.cpp index ef32539b..18339399 100644 --- a/osal/linux/CountingSemaphore.cpp +++ b/osal/linux/CountingSemaphore.cpp @@ -1,54 +1,54 @@ -#include "../../osal/linux/CountingSemaphore.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" - -CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount): - maxCount(maxCount), initCount(initCount) { - if(initCount > maxCount) { - sif::error << "CountingSemaphoreUsingTask: Max count bigger than " - "intial cout. Setting initial count to max count." << std::endl; - initCount = maxCount; - } - - initSemaphore(initCount); -} - -CountingSemaphore::CountingSemaphore(CountingSemaphore&& other): - maxCount(other.maxCount), initCount(other.initCount) { - initSemaphore(initCount); -} - -CountingSemaphore& CountingSemaphore::operator =( - CountingSemaphore&& other) { - initSemaphore(other.initCount); - return * this; -} - -ReturnValue_t CountingSemaphore::release() { - ReturnValue_t result = checkCount(&handle, maxCount); - if(result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - return CountingSemaphore::release(&this->handle); -} - -ReturnValue_t CountingSemaphore::release(sem_t* handle) { - int result = sem_post(handle); - if(result == 0) { - return HasReturnvaluesIF::RETURN_OK; - } - - switch(errno) { - case(EINVAL): - // Semaphore invalid - return SemaphoreIF::SEMAPHORE_INVALID; - case(EOVERFLOW): - // SEM_MAX_VALUE overflow. This should never happen - default: - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -uint8_t CountingSemaphore::getMaxCount() const { - return maxCount; -} - +#include "../../osal/linux/CountingSemaphore.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount): + maxCount(maxCount), initCount(initCount) { + if(initCount > maxCount) { + sif::error << "CountingSemaphoreUsingTask: Max count bigger than " + "intial cout. Setting initial count to max count." << std::endl; + initCount = maxCount; + } + + initSemaphore(initCount); +} + +CountingSemaphore::CountingSemaphore(CountingSemaphore&& other): + maxCount(other.maxCount), initCount(other.initCount) { + initSemaphore(initCount); +} + +CountingSemaphore& CountingSemaphore::operator =( + CountingSemaphore&& other) { + initSemaphore(other.initCount); + return * this; +} + +ReturnValue_t CountingSemaphore::release() { + ReturnValue_t result = checkCount(&handle, maxCount); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return CountingSemaphore::release(&this->handle); +} + +ReturnValue_t CountingSemaphore::release(sem_t* handle) { + int result = sem_post(handle); + if(result == 0) { + return HasReturnvaluesIF::RETURN_OK; + } + + switch(errno) { + case(EINVAL): + // Semaphore invalid + return SemaphoreIF::SEMAPHORE_INVALID; + case(EOVERFLOW): + // SEM_MAX_VALUE overflow. This should never happen + default: + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +uint8_t CountingSemaphore::getMaxCount() const { + return maxCount; +} + diff --git a/osal/linux/CountingSemaphore.h b/osal/linux/CountingSemaphore.h index afe21a61..e0fbb992 100644 --- a/osal/linux/CountingSemaphore.h +++ b/osal/linux/CountingSemaphore.h @@ -1,37 +1,37 @@ -#ifndef FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_ -#define FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_ -#include "../../osal/linux/BinarySemaphore.h" - -/** - * @brief Counting semaphores, which can be acquired more than once. - * @details - * See: https://www.freertos.org/CreateCounting.html - * API of counting semaphores is almost identical to binary semaphores, - * so we just inherit from binary semaphore and provide the respective - * constructors. - */ -class CountingSemaphore: public BinarySemaphore { -public: - CountingSemaphore(const uint8_t maxCount, uint8_t initCount); - //! @brief Copy ctor, disabled - CountingSemaphore(const CountingSemaphore&) = delete; - //! @brief Copy assignment, disabled - CountingSemaphore& operator=(const CountingSemaphore&) = delete; - //! @brief Move ctor - CountingSemaphore (CountingSemaphore &&); - //! @brief Move assignment - CountingSemaphore & operator=(CountingSemaphore &&); - - ReturnValue_t release() override; - static ReturnValue_t release(sem_t* sem); - /* Same API as binary semaphore otherwise. acquire() can be called - * until there are not semaphores left and release() can be called - * until maxCount is reached. */ - - uint8_t getMaxCount() const; -private: - const uint8_t maxCount; - uint8_t initCount = 0; -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */ +#ifndef FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_ +#define FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_ +#include "../../osal/linux/BinarySemaphore.h" + +/** + * @brief Counting semaphores, which can be acquired more than once. + * @details + * See: https://www.freertos.org/CreateCounting.html + * API of counting semaphores is almost identical to binary semaphores, + * so we just inherit from binary semaphore and provide the respective + * constructors. + */ +class CountingSemaphore: public BinarySemaphore { +public: + CountingSemaphore(const uint8_t maxCount, uint8_t initCount); + //! @brief Copy ctor, disabled + CountingSemaphore(const CountingSemaphore&) = delete; + //! @brief Copy assignment, disabled + CountingSemaphore& operator=(const CountingSemaphore&) = delete; + //! @brief Move ctor + CountingSemaphore (CountingSemaphore &&); + //! @brief Move assignment + CountingSemaphore & operator=(CountingSemaphore &&); + + ReturnValue_t release() override; + static ReturnValue_t release(sem_t* sem); + /* Same API as binary semaphore otherwise. acquire() can be called + * until there are not semaphores left and release() can be called + * until maxCount is reached. */ + + uint8_t getMaxCount() const; +private: + const uint8_t maxCount; + uint8_t initCount = 0; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */ diff --git a/osal/linux/SemaphoreFactory.cpp b/osal/linux/SemaphoreFactory.cpp index bcb5d16f..e4710933 100644 --- a/osal/linux/SemaphoreFactory.cpp +++ b/osal/linux/SemaphoreFactory.cpp @@ -1,33 +1,33 @@ -#include "../../tasks/SemaphoreFactory.h" -#include "BinarySemaphore.h" -#include "CountingSemaphore.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" - -SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; - -SemaphoreFactory::SemaphoreFactory() { -} - -SemaphoreFactory::~SemaphoreFactory() { - delete factoryInstance; -} - -SemaphoreFactory* SemaphoreFactory::instance() { - if (factoryInstance == nullptr){ - factoryInstance = new SemaphoreFactory(); - } - return SemaphoreFactory::factoryInstance; -} - -SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t arguments) { - return new BinarySemaphore(); -} - -SemaphoreIF* SemaphoreFactory::createCountingSemaphore(const uint8_t maxCount, - uint8_t initCount, uint32_t arguments) { - return new CountingSemaphore(maxCount, initCount); -} - -void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { - delete semaphore; -} +#include "../../tasks/SemaphoreFactory.h" +#include "BinarySemaphore.h" +#include "CountingSemaphore.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; + +SemaphoreFactory::SemaphoreFactory() { +} + +SemaphoreFactory::~SemaphoreFactory() { + delete factoryInstance; +} + +SemaphoreFactory* SemaphoreFactory::instance() { + if (factoryInstance == nullptr){ + factoryInstance = new SemaphoreFactory(); + } + return SemaphoreFactory::factoryInstance; +} + +SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t arguments) { + return new BinarySemaphore(); +} + +SemaphoreIF* SemaphoreFactory::createCountingSemaphore(const uint8_t maxCount, + uint8_t initCount, uint32_t arguments) { + return new CountingSemaphore(maxCount, initCount); +} + +void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { + delete semaphore; +} diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index 812cd34b..1c11afd4 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -1,129 +1,129 @@ -#include "../serialize/SerialBufferAdapter.h" -#include "../serviceinterface/ServiceInterfaceStream.h" -#include - -template -SerialBufferAdapter::SerialBufferAdapter(const uint8_t* buffer, - count_t bufferLength, bool serializeLength) : - serializeLength(serializeLength), - constBuffer(buffer), buffer(nullptr), - bufferLength(bufferLength) {} - -template -SerialBufferAdapter::SerialBufferAdapter(uint8_t* buffer, - count_t bufferLength, bool serializeLength) : - serializeLength(serializeLength), constBuffer(buffer), buffer(buffer), - bufferLength(bufferLength) {} - - -template -SerialBufferAdapter::~SerialBufferAdapter() { -} - -template -ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, - size_t* size, size_t maxSize, Endianness streamEndianness) const { - if (serializeLength) { - ReturnValue_t result = SerializeAdapter::serialize(&bufferLength, - buffer, size, maxSize, streamEndianness); - if(result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - } - - if (*size + bufferLength > maxSize) { - return BUFFER_TOO_SHORT; - } - - if (this->constBuffer != nullptr) { - std::memcpy(*buffer, this->constBuffer, bufferLength); - } - else if (this->buffer != nullptr) { - // This will propably be never reached, constBuffer should always be - // set if non-const buffer is set. - std::memcpy(*buffer, this->buffer, bufferLength); - } - else { - return HasReturnvaluesIF::RETURN_FAILED; - } - *size += bufferLength; - (*buffer) += bufferLength; - return HasReturnvaluesIF::RETURN_OK; - -} - -template -size_t SerialBufferAdapter::getSerializedSize() const { - if (serializeLength) { - return bufferLength + SerializeAdapter::getSerializedSize(&bufferLength); - } else { - return bufferLength; - } -} - -template -ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, - size_t* size, Endianness streamEndianness) { - if (this->buffer == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - - if(serializeLength){ - count_t lengthField = 0; - ReturnValue_t result = SerializeAdapter::deSerialize(&lengthField, - buffer, size, streamEndianness); - if(result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - if(lengthField > bufferLength) { - return TOO_MANY_ELEMENTS; - } - bufferLength = lengthField; - } - - if (bufferLength <= *size) { - *size -= bufferLength; - std::memcpy(this->buffer, *buffer, bufferLength); - (*buffer) += bufferLength; - return HasReturnvaluesIF::RETURN_OK; - } - else { - return STREAM_TOO_SHORT; - } -} - -template -uint8_t * SerialBufferAdapter::getBuffer() { - if(buffer == nullptr) { - sif::error << "Wrong access function for stored type !" - " Use getConstBuffer()." << std::endl; - return nullptr; - } - return buffer; -} - -template -const uint8_t * SerialBufferAdapter::getConstBuffer() { - if(constBuffer == nullptr) { - sif::error << "SerialBufferAdapter::getConstBuffer:" - " Buffers are unitialized!" << std::endl; - return nullptr; - } - return constBuffer; -} - -template -void SerialBufferAdapter::setBuffer(uint8_t* buffer, - count_t bufferLength) { - this->buffer = buffer; - this->constBuffer = buffer; - this->bufferLength = bufferLength; -} - - -//forward Template declaration for linker -template class SerialBufferAdapter; -template class SerialBufferAdapter; -template class SerialBufferAdapter; -template class SerialBufferAdapter; - +#include "../serialize/SerialBufferAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include + +template +SerialBufferAdapter::SerialBufferAdapter(const uint8_t* buffer, + count_t bufferLength, bool serializeLength) : + serializeLength(serializeLength), + constBuffer(buffer), buffer(nullptr), + bufferLength(bufferLength) {} + +template +SerialBufferAdapter::SerialBufferAdapter(uint8_t* buffer, + count_t bufferLength, bool serializeLength) : + serializeLength(serializeLength), constBuffer(buffer), buffer(buffer), + bufferLength(bufferLength) {} + + +template +SerialBufferAdapter::~SerialBufferAdapter() { +} + +template +ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, + size_t* size, size_t maxSize, Endianness streamEndianness) const { + if (serializeLength) { + ReturnValue_t result = SerializeAdapter::serialize(&bufferLength, + buffer, size, maxSize, streamEndianness); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + + if (*size + bufferLength > maxSize) { + return BUFFER_TOO_SHORT; + } + + if (this->constBuffer != nullptr) { + std::memcpy(*buffer, this->constBuffer, bufferLength); + } + else if (this->buffer != nullptr) { + // This will propably be never reached, constBuffer should always be + // set if non-const buffer is set. + std::memcpy(*buffer, this->buffer, bufferLength); + } + else { + return HasReturnvaluesIF::RETURN_FAILED; + } + *size += bufferLength; + (*buffer) += bufferLength; + return HasReturnvaluesIF::RETURN_OK; + +} + +template +size_t SerialBufferAdapter::getSerializedSize() const { + if (serializeLength) { + return bufferLength + SerializeAdapter::getSerializedSize(&bufferLength); + } else { + return bufferLength; + } +} + +template +ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, + size_t* size, Endianness streamEndianness) { + if (this->buffer == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + + if(serializeLength){ + count_t lengthField = 0; + ReturnValue_t result = SerializeAdapter::deSerialize(&lengthField, + buffer, size, streamEndianness); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + if(lengthField > bufferLength) { + return TOO_MANY_ELEMENTS; + } + bufferLength = lengthField; + } + + if (bufferLength <= *size) { + *size -= bufferLength; + std::memcpy(this->buffer, *buffer, bufferLength); + (*buffer) += bufferLength; + return HasReturnvaluesIF::RETURN_OK; + } + else { + return STREAM_TOO_SHORT; + } +} + +template +uint8_t * SerialBufferAdapter::getBuffer() { + if(buffer == nullptr) { + sif::error << "Wrong access function for stored type !" + " Use getConstBuffer()." << std::endl; + return nullptr; + } + return buffer; +} + +template +const uint8_t * SerialBufferAdapter::getConstBuffer() { + if(constBuffer == nullptr) { + sif::error << "SerialBufferAdapter::getConstBuffer:" + " Buffers are unitialized!" << std::endl; + return nullptr; + } + return constBuffer; +} + +template +void SerialBufferAdapter::setBuffer(uint8_t* buffer, + count_t bufferLength) { + this->buffer = buffer; + this->constBuffer = buffer; + this->bufferLength = bufferLength; +} + + +//forward Template declaration for linker +template class SerialBufferAdapter; +template class SerialBufferAdapter; +template class SerialBufferAdapter; +template class SerialBufferAdapter; + diff --git a/serialize/SerialBufferAdapter.h b/serialize/SerialBufferAdapter.h index c3dfcd8f..9a89e18b 100644 --- a/serialize/SerialBufferAdapter.h +++ b/serialize/SerialBufferAdapter.h @@ -1,78 +1,78 @@ -#ifndef SERIALBUFFERADAPTER_H_ -#define SERIALBUFFERADAPTER_H_ - -#include "../serialize/SerializeIF.h" -#include "../serialize/SerializeAdapter.h" - -/** - * 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>. - * Right now, the SerialBufferAdapter must always - * be initialized with the buffer and size ! - * - * \ingroup serialize - */ -template -class SerialBufferAdapter: public SerializeIF { -public: - - /** - * Constructor for constant uint8_t buffer. Length field can be serialized optionally. - * Type of length can be supplied as template type. - * @param buffer - * @param bufferLength - * @param serializeLength - */ - SerialBufferAdapter(const uint8_t* buffer, count_t bufferLength, - bool serializeLength = false); - - /** - * Constructor for non-constant uint8_t buffer. - * Length field can be serialized optionally. - * Type of length can be supplied as template type. - * @param buffer - * @param bufferLength - * @param serializeLength Length field will be serialized with size count_t - */ - SerialBufferAdapter(uint8_t* buffer, count_t bufferLength, - bool serializeLength = false); - - virtual ~SerialBufferAdapter(); - - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, - size_t maxSize, Endianness streamEndianness) const override; - - virtual size_t getSerializedSize() const override; - - /** - * @brief This function deserializes a buffer into the member buffer. - * @details - * If a length field is present, it is ignored, as the size should have - * been set in the constructor. If the size is not known beforehand, - * consider using SerialFixedArrayListAdapter instead. - * @param buffer [out] Resulting buffer - * @param size remaining size to deserialize, should be larger than buffer - * + size field size - * @param bigEndian - * @return - */ - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) override; - - uint8_t * getBuffer(); - const uint8_t * getConstBuffer(); - void setBuffer(uint8_t* buffer, count_t bufferLength); -private: - bool serializeLength = false; - const uint8_t *constBuffer = nullptr; - uint8_t *buffer = nullptr; - count_t bufferLength = 0; -}; - -#endif /* SERIALBUFFERADAPTER_H_ */ +#ifndef SERIALBUFFERADAPTER_H_ +#define SERIALBUFFERADAPTER_H_ + +#include "../serialize/SerializeIF.h" +#include "../serialize/SerializeAdapter.h" + +/** + * 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>. + * Right now, the SerialBufferAdapter must always + * be initialized with the buffer and size ! + * + * \ingroup serialize + */ +template +class SerialBufferAdapter: public SerializeIF { +public: + + /** + * Constructor for constant uint8_t buffer. Length field can be serialized optionally. + * Type of length can be supplied as template type. + * @param buffer + * @param bufferLength + * @param serializeLength + */ + SerialBufferAdapter(const uint8_t* buffer, count_t bufferLength, + bool serializeLength = false); + + /** + * Constructor for non-constant uint8_t buffer. + * Length field can be serialized optionally. + * Type of length can be supplied as template type. + * @param buffer + * @param bufferLength + * @param serializeLength Length field will be serialized with size count_t + */ + SerialBufferAdapter(uint8_t* buffer, count_t bufferLength, + bool serializeLength = false); + + virtual ~SerialBufferAdapter(); + + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const override; + + virtual size_t getSerializedSize() const override; + + /** + * @brief This function deserializes a buffer into the member buffer. + * @details + * If a length field is present, it is ignored, as the size should have + * been set in the constructor. If the size is not known beforehand, + * consider using SerialFixedArrayListAdapter instead. + * @param buffer [out] Resulting buffer + * @param size remaining size to deserialize, should be larger than buffer + * + size field size + * @param bigEndian + * @return + */ + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; + + uint8_t * getBuffer(); + const uint8_t * getConstBuffer(); + void setBuffer(uint8_t* buffer, count_t bufferLength); +private: + bool serializeLength = false; + const uint8_t *constBuffer = nullptr; + uint8_t *buffer = nullptr; + count_t bufferLength = 0; +}; + +#endif /* SERIALBUFFERADAPTER_H_ */ diff --git a/tasks/SemaphoreFactory.h b/tasks/SemaphoreFactory.h index 2c41a135..01c09d1b 100644 --- a/tasks/SemaphoreFactory.h +++ b/tasks/SemaphoreFactory.h @@ -1,50 +1,50 @@ -#ifndef FSFW_TASKS_SEMAPHOREFACTORY_H_ -#define FSFW_TASKS_SEMAPHOREFACTORY_H_ - -#include "../tasks/SemaphoreIF.h" - -/** - * Creates Semaphore. - * This class is a "singleton" interface, i.e. it provides an - * interface, but also is the base class for a singleton. - */ -class SemaphoreFactory { -public: - virtual ~SemaphoreFactory(); - /** - * Returns the single instance of SemaphoreFactory. - * The implementation of #instance is found in its subclasses. - * Thus, we choose link-time variability of the instance. - */ - static SemaphoreFactory* instance(); - - /** - * Create a binary semaphore. - * Creator function for a binary semaphore which may only be acquired once - * @param argument Can be used to pass implementation specific information. - * @return Pointer to newly created semaphore class instance. - */ - SemaphoreIF* createBinarySemaphore(uint32_t arguments = 0); - /** - * Create a counting semaphore. - * Creator functons for a counting semaphore which may be acquired multiple - * times. - * @param count Semaphore can be taken count times. - * @param initCount Initial count value. - * @param argument Can be used to pass implementation specific information. - * @return - */ - SemaphoreIF* createCountingSemaphore(const uint8_t maxCount, - uint8_t initCount, uint32_t arguments = 0); - - void deleteSemaphore(SemaphoreIF* semaphore); - -private: - /** - * External instantiation is not allowed. - */ - SemaphoreFactory(); - static SemaphoreFactory* factoryInstance; -}; - -#endif /* FSFW_TASKS_SEMAPHOREFACTORY_H_ */ +#ifndef FSFW_TASKS_SEMAPHOREFACTORY_H_ +#define FSFW_TASKS_SEMAPHOREFACTORY_H_ + +#include "../tasks/SemaphoreIF.h" + +/** + * Creates Semaphore. + * This class is a "singleton" interface, i.e. it provides an + * interface, but also is the base class for a singleton. + */ +class SemaphoreFactory { +public: + virtual ~SemaphoreFactory(); + /** + * Returns the single instance of SemaphoreFactory. + * The implementation of #instance is found in its subclasses. + * Thus, we choose link-time variability of the instance. + */ + static SemaphoreFactory* instance(); + + /** + * Create a binary semaphore. + * Creator function for a binary semaphore which may only be acquired once + * @param argument Can be used to pass implementation specific information. + * @return Pointer to newly created semaphore class instance. + */ + SemaphoreIF* createBinarySemaphore(uint32_t arguments = 0); + /** + * Create a counting semaphore. + * Creator functons for a counting semaphore which may be acquired multiple + * times. + * @param count Semaphore can be taken count times. + * @param initCount Initial count value. + * @param argument Can be used to pass implementation specific information. + * @return + */ + SemaphoreIF* createCountingSemaphore(const uint8_t maxCount, + uint8_t initCount, uint32_t arguments = 0); + + void deleteSemaphore(SemaphoreIF* semaphore); + +private: + /** + * External instantiation is not allowed. + */ + SemaphoreFactory(); + static SemaphoreFactory* factoryInstance; +}; + +#endif /* FSFW_TASKS_SEMAPHOREFACTORY_H_ */ diff --git a/tasks/SemaphoreIF.h b/tasks/SemaphoreIF.h index 30d4ed88..dd327e23 100644 --- a/tasks/SemaphoreIF.h +++ b/tasks/SemaphoreIF.h @@ -1,68 +1,68 @@ -#ifndef FRAMEWORK_TASKS_SEMAPHOREIF_H_ -#define FRAMEWORK_TASKS_SEMAPHOREIF_H_ -#include "../returnvalues/FwClassIds.h" -#include "../returnvalues/HasReturnvaluesIF.h" -#include - -/** - * @brief Generic interface for semaphores, which can be used to achieve - * task synchronization. This is a generic interface which can be - * used for both binary semaphores and counting semaphores. - * @details - * A semaphore is a synchronization primitive. - * See: https://en.wikipedia.org/wiki/Semaphore_(programming) - * A semaphore can be used to achieve task synchonization and track the - * availability of resources by using either the binary or the counting - * semaphore types. - * - * If mutual exlcusion of a resource is desired, a mutex should be used, - * which is a special form of a semaphore and has an own interface. - */ -class SemaphoreIF { -public: - /** - * Different types of timeout for the mutex lock. - */ - enum TimeoutType { - POLLING, //!< If mutex is not available, return immediately - WAITING, //!< Wait a specified time for the mutex to become available - BLOCKING //!< Block indefinitely until the mutex becomes available. - }; - - virtual~ SemaphoreIF() {}; - - static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; - //! Semaphore timeout - static constexpr ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(1); - //! The current semaphore can not be given, because it is not owned - static constexpr ReturnValue_t SEMAPHORE_NOT_OWNED = MAKE_RETURN_CODE(2); - static constexpr ReturnValue_t SEMAPHORE_INVALID = MAKE_RETURN_CODE(3); - - /** - * Generic call to acquire a semaphore. - * If there are no more semaphores to be taken (for a counting semaphore, - * a semaphore may be taken more than once), the taks will block - * for a maximum of timeoutMs while trying to acquire the semaphore. - * This can be used to achieve task synchrnization. - * @param timeoutMs - * @return - c RETURN_OK for successfull acquisition - */ - virtual ReturnValue_t acquire(TimeoutType timeoutType = - TimeoutType::BLOCKING, uint32_t timeoutMs = 0) = 0; - - /** - * Corrensponding call to release a semaphore. - * @return -@c RETURN_OK for successfull release - */ - virtual ReturnValue_t release() = 0; - - /** - * If the semaphore is a counting semaphore then the semaphores current - * count value is returned. If the semaphore is a binary semaphore then 1 - * is returned if the semaphore is available, and 0 is returned if the - * semaphore is not available. - */ - virtual uint8_t getSemaphoreCounter() const = 0; -}; - -#endif /* FRAMEWORK_TASKS_SEMAPHOREIF_H_ */ +#ifndef FRAMEWORK_TASKS_SEMAPHOREIF_H_ +#define FRAMEWORK_TASKS_SEMAPHOREIF_H_ +#include "../returnvalues/FwClassIds.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include + +/** + * @brief Generic interface for semaphores, which can be used to achieve + * task synchronization. This is a generic interface which can be + * used for both binary semaphores and counting semaphores. + * @details + * A semaphore is a synchronization primitive. + * See: https://en.wikipedia.org/wiki/Semaphore_(programming) + * A semaphore can be used to achieve task synchonization and track the + * availability of resources by using either the binary or the counting + * semaphore types. + * + * If mutual exlcusion of a resource is desired, a mutex should be used, + * which is a special form of a semaphore and has an own interface. + */ +class SemaphoreIF { +public: + /** + * Different types of timeout for the mutex lock. + */ + enum TimeoutType { + POLLING, //!< If mutex is not available, return immediately + WAITING, //!< Wait a specified time for the mutex to become available + BLOCKING //!< Block indefinitely until the mutex becomes available. + }; + + virtual~ SemaphoreIF() {}; + + static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; + //! Semaphore timeout + static constexpr ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(1); + //! The current semaphore can not be given, because it is not owned + static constexpr ReturnValue_t SEMAPHORE_NOT_OWNED = MAKE_RETURN_CODE(2); + static constexpr ReturnValue_t SEMAPHORE_INVALID = MAKE_RETURN_CODE(3); + + /** + * Generic call to acquire a semaphore. + * If there are no more semaphores to be taken (for a counting semaphore, + * a semaphore may be taken more than once), the taks will block + * for a maximum of timeoutMs while trying to acquire the semaphore. + * This can be used to achieve task synchrnization. + * @param timeoutMs + * @return - c RETURN_OK for successfull acquisition + */ + virtual ReturnValue_t acquire(TimeoutType timeoutType = + TimeoutType::BLOCKING, uint32_t timeoutMs = 0) = 0; + + /** + * Corrensponding call to release a semaphore. + * @return -@c RETURN_OK for successfull release + */ + virtual ReturnValue_t release() = 0; + + /** + * If the semaphore is a counting semaphore then the semaphores current + * count value is returned. If the semaphore is a binary semaphore then 1 + * is returned if the semaphore is available, and 0 is returned if the + * semaphore is not available. + */ + virtual uint8_t getSemaphoreCounter() const = 0; +}; + +#endif /* FRAMEWORK_TASKS_SEMAPHOREIF_H_ */ From 85f21b05165efeabb626fcb5f7d8c7d3bc8a18ea Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 18 Sep 2020 13:32:53 +0200 Subject: [PATCH 346/653] object manager convergence --- objectmanager/ObjectManager.h | 23 +++++-------- objectmanager/ObjectManagerIF.h | 8 ++--- objectmanager/SystemObject.cpp | 2 +- objectmanager/SystemObject.h | 30 ++++++++--------- objectmanager/SystemObjectIF.h | 56 +++++++++++++++----------------- objectmanager/frameworkObjects.h | 14 ++++++-- 6 files changed, 65 insertions(+), 68 deletions(-) diff --git a/objectmanager/ObjectManager.h b/objectmanager/ObjectManager.h index 0d2b3c4a..69a74f73 100644 --- a/objectmanager/ObjectManager.h +++ b/objectmanager/ObjectManager.h @@ -1,12 +1,5 @@ -/** - * @file ObjectManager.h - * @brief This file contains the implementation of the ObjectManager class - * @date 18.09.2012 - * @author Bastian Baetz - */ - -#ifndef OBJECTMANAGER_H_ -#define OBJECTMANAGER_H_ +#ifndef FSFW_OBJECTMANAGER_OBJECTMANAGER_H_ +#define FSFW_OBJECTMANAGER_OBJECTMANAGER_H_ #include "ObjectManagerIF.h" #include "SystemObjectIF.h" @@ -22,14 +15,15 @@ * most of the system initialization. * As the system is static after initialization, no new objects are * created or inserted into the list after startup. - * \ingroup system_objects + * @ingroup system_objects + * @author Bastian Baetz */ class ObjectManager : public ObjectManagerIF { private: //comparison? /** - * \brief This is the map of all initialized objects in the manager. - * \details Objects in the List must inherit the SystemObjectIF. + * @brief This is the map of all initialized objects in the manager. + * @details Objects in the List must inherit the SystemObjectIF. */ std::map objectList; protected: @@ -54,7 +48,8 @@ public: /** * @brief In the class's destructor, all objects in the list are deleted. */ - //SHOULDDO: If, for some reason, deleting an ObjectManager instance is required, check if this works. + // SHOULDDO: If, for some reason, deleting an ObjectManager instance is + // required, check if this works. virtual ~ObjectManager( void ); ReturnValue_t insert( object_id_t id, SystemObjectIF* object ); ReturnValue_t remove( object_id_t id ); @@ -64,4 +59,4 @@ public: -#endif /* OBJECTMANAGER_H_ */ +#endif /* FSFW_OBJECTMANAGER_OBJECTMANAGER_H_ */ diff --git a/objectmanager/ObjectManagerIF.h b/objectmanager/ObjectManagerIF.h index e0162af9..1f462509 100644 --- a/objectmanager/ObjectManagerIF.h +++ b/objectmanager/ObjectManagerIF.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_OBJECTMANAGER_OBJECTMANAGERIF_H_ -#define FRAMEWORK_OBJECTMANAGER_OBJECTMANAGERIF_H_ +#ifndef FSFW_OBJECTMANAGER_OBJECTMANAGERIF_H_ +#define FSFW_OBJECTMANAGER_OBJECTMANAGERIF_H_ #include "frameworkObjects.h" #include "SystemObjectIF.h" @@ -21,8 +21,7 @@ public: static constexpr uint8_t INTERFACE_ID = CLASS_ID::OBJECT_MANAGER_IF; static constexpr ReturnValue_t INSERTION_FAILED = MAKE_RETURN_CODE( 1 ); static constexpr ReturnValue_t NOT_FOUND = MAKE_RETURN_CODE( 2 ); - - static constexpr ReturnValue_t CHILD_INIT_FAILED = MAKE_RETURN_CODE( 3 ); //!< Can be used if the initialization of a SystemObject failed. + static constexpr ReturnValue_t CHILD_INIT_FAILED = MAKE_RETURN_CODE( 3 ); static constexpr ReturnValue_t INTERNAL_ERR_REPORTER_UNINIT = MAKE_RETURN_CODE( 4 ); protected: @@ -80,6 +79,7 @@ public: /** * @brief This is the forward declaration of the global objectManager instance. */ +// maybe but this in the glob namespace to explicitely mark it global? extern ObjectManagerIF *objectManager; /*Documentation can be found in the class method declaration above.*/ diff --git a/objectmanager/SystemObject.cpp b/objectmanager/SystemObject.cpp index 53aac599..64330fbc 100644 --- a/objectmanager/SystemObject.cpp +++ b/objectmanager/SystemObject.cpp @@ -1,6 +1,6 @@ -#include "../events/EventManagerIF.h" #include "ObjectManager.h" #include "SystemObject.h" +#include "../events/EventManagerIF.h" SystemObject::SystemObject(object_id_t setObjectId, bool doRegister) : objectId(setObjectId), registered(doRegister) { diff --git a/objectmanager/SystemObject.h b/objectmanager/SystemObject.h index 8e9f20d5..9188693e 100644 --- a/objectmanager/SystemObject.h +++ b/objectmanager/SystemObject.h @@ -1,16 +1,9 @@ -/** - * @file SystemObject.h - * @brief This file contains the definition of the SystemObject class. - * @date 07.11.2012 - * @author Ulrich Mohr - */ - -#ifndef SYSTEMOBJECT_H_ -#define SYSTEMOBJECT_H_ +#ifndef FSFW_OBJECTMANAGER_SYSTEMOBJECT_H_ +#define FSFW_OBJECTMANAGER_SYSTEMOBJECT_H_ +#include "SystemObjectIF.h" #include "../events/Event.h" #include "../events/EventReportingProxyIF.h" -#include "SystemObjectIF.h" #include "../timemanager/Clock.h" /** @@ -20,7 +13,7 @@ * class that is announced to ObjectManager. It automatically includes * itself (and therefore the inheriting class) in the object manager's * list. - * \ingroup system_objects + * @ingroup system_objects */ class SystemObject: public SystemObjectIF { private: @@ -37,25 +30,28 @@ public: * @param parameter1 * @param parameter2 */ - virtual void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0); + virtual void triggerEvent(Event event, uint32_t parameter1 = 0, + uint32_t parameter2 = 0); /** * @brief The class's constructor. * @details In the constructor, the object id is set and the class is * inserted in the object manager. * @param setObjectId The id the object shall have. - * @param doRegister Determines if the object is registered in the global object manager. + * @param doRegister Determines if the object is registered in + * the global object manager. */ SystemObject(object_id_t setObjectId, bool doRegister = true); /** * @brief On destruction, the object removes itself from the list. */ virtual ~SystemObject(); - object_id_t getObjectId() const; - virtual ReturnValue_t initialize(); + object_id_t getObjectId() const override; + virtual ReturnValue_t initialize() override; virtual ReturnValue_t checkObjectConnections(); - virtual void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const; + virtual void forwardEvent(Event event, uint32_t parameter1 = 0, + uint32_t parameter2 = 0) const; }; -#endif /* SYSTEMOBJECT_H_ */ +#endif /* FSFW_OBJECTMANAGER_SYSTEMOBJECT_H_ */ diff --git a/objectmanager/SystemObjectIF.h b/objectmanager/SystemObjectIF.h index c5a92196..315fde9b 100644 --- a/objectmanager/SystemObjectIF.h +++ b/objectmanager/SystemObjectIF.h @@ -1,26 +1,19 @@ -/** - * @file SystemObjectIF.h - * @brief This file contains the definition of the SystemObjectIF interface. - * @date 18.09.2012 - * @author Bastian Baetz - */ - -#ifndef SYSTEMOBJECTIF_H_ -#define SYSTEMOBJECTIF_H_ +#ifndef FSFW_OBJECTMANAGER_SYSTEMOBJECTIF_H_ +#define FSFW_OBJECTMANAGER_SYSTEMOBJECTIF_H_ #include "../events/EventReportingProxyIF.h" #include "../returnvalues/HasReturnvaluesIF.h" -#include +#include /** - * \defgroup system_objects Software System Object Management - * The classes to create System Objects and classes to manage these are contained in this group. - * System Objects are software elements that can be controlled externally. They all have a unique - * object identifier. + * @defgroup system_objects Software System Object Management + * The classes to create System Objects and classes to manage these are + * contained in this group. System Objects are software elements that can be + * controlled externally. They all have a unique object identifier. */ /** * This is the typedef for object identifiers. - * \ingroup system_objects + * @ingroup system_objects */ typedef uint32_t object_id_t; @@ -29,7 +22,8 @@ typedef uint32_t object_id_t; * list. * It does not provide any method definitions, still it is required to * perform a type check with dynamic_cast. - * \ingroup system_objects + * @author Bastian Baetz + * @ingroup system_objects */ class SystemObjectIF : public EventReportingProxyIF { public: @@ -41,24 +35,28 @@ public: /** * The empty virtual destructor as required for C++ interfaces. */ - virtual ~SystemObjectIF() { - } + virtual ~SystemObjectIF() {} /** - * Initializes all inter-object dependencies. - * This is necessary to avoid circular dependencies of not-fully - * initialized objects on start up. - * @return - \c RETURN_OK in case the initialization was successful - * - \c RETURN_FAILED otherwise + * @brief Initializes the object. + * There are initialization steps which can also be done in the constructor. + * However, there is no clean way to get a returnvalue from a constructor. + * Furthermore some components require other system object to be created + * which might not have been built yet. + * Therefore, a two-step initialization resolves this problem and prevents + * circular dependencies of not-fully initialized objects on start up. + * @return - @c RETURN_OK in case the initialization was successful + * - @c RETURN_FAILED otherwise */ virtual ReturnValue_t initialize() = 0; /** - * Checks, if all object-object interconnections are satisfying for operation. - * Some objects need certain other objects (or a certain number), to be registered as children. - * These checks can be done in this method. - * @return - \c RETURN_OK in case the check was successful - * - \c any other code otherwise + * @brief Checks if all object-object interconnections are satisfying + * for operation. + * Some objects need certain other objects (or a certain number), to be + * registered as children. These checks can be done in this method. + * @return - @c RETURN_OK in case the check was successful + * - @c any other code otherwise */ virtual ReturnValue_t checkObjectConnections() = 0; }; -#endif /* SYSTEMOBJECTIF_H_ */ +#endif /* #ifndef FSFW_OBJECTMANAGER_SYSTEMOBJECTIF_H_ */ diff --git a/objectmanager/frameworkObjects.h b/objectmanager/frameworkObjects.h index c3deafc4..4a30e70a 100644 --- a/objectmanager/frameworkObjects.h +++ b/objectmanager/frameworkObjects.h @@ -1,8 +1,15 @@ -#ifndef FRAMEWORK_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ -#define FRAMEWORK_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ +#ifndef FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ +#define FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ namespace objects { enum framework_objects { + // Default verification reporter. + PUS_SERVICE_1 = 0x53000001, + PUS_SERVICE_2 = 0x53000002, + PUS_SERVICE_5 = 0x53000005, + PUS_SERVICE_8 = 0x53000008, + PUS_SERVICE_200 = 0x53000200, + //Generic IDs for IPC, modes, health, events HEALTH_TABLE = 0x53010000, // MODE_STORE = 0x53010100, @@ -12,10 +19,11 @@ enum framework_objects { //IDs for PUS Packet Communication TC_STORE = 0x534f0100, TM_STORE = 0x534f0200, + NO_OBJECT = 0xFFFFFFFF }; } -#endif /* FRAMEWORK_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ */ +#endif /* FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ */ From 6062192bf0a5865fe3c1edb23aa2bc1e1b19d122 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 18 Sep 2020 13:37:06 +0200 Subject: [PATCH 347/653] dded back retval expalanation --- objectmanager/ObjectManagerIF.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/objectmanager/ObjectManagerIF.h b/objectmanager/ObjectManagerIF.h index 1f462509..8bae800b 100644 --- a/objectmanager/ObjectManagerIF.h +++ b/objectmanager/ObjectManagerIF.h @@ -21,7 +21,7 @@ public: static constexpr uint8_t INTERFACE_ID = CLASS_ID::OBJECT_MANAGER_IF; static constexpr ReturnValue_t INSERTION_FAILED = MAKE_RETURN_CODE( 1 ); static constexpr ReturnValue_t NOT_FOUND = MAKE_RETURN_CODE( 2 ); - static constexpr ReturnValue_t CHILD_INIT_FAILED = MAKE_RETURN_CODE( 3 ); + static constexpr ReturnValue_t CHILD_INIT_FAILED = MAKE_RETURN_CODE( 3 ); //!< Can be used if the initialization of a SystemObject failed. static constexpr ReturnValue_t INTERNAL_ERR_REPORTER_UNINIT = MAKE_RETURN_CODE( 4 ); protected: From 8ea0a38658b1322a6bee67b7c656544d1f4d3467 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 18 Sep 2020 13:37:38 +0200 Subject: [PATCH 348/653] shoulddo fix --- objectmanager/ObjectManagerIF.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/objectmanager/ObjectManagerIF.h b/objectmanager/ObjectManagerIF.h index 8bae800b..4bd1d915 100644 --- a/objectmanager/ObjectManagerIF.h +++ b/objectmanager/ObjectManagerIF.h @@ -79,7 +79,7 @@ public: /** * @brief This is the forward declaration of the global objectManager instance. */ -// maybe but this in the glob namespace to explicitely mark it global? +// SHOULDDO: maybe put this in the glob namespace to explicitely mark it global? extern ObjectManagerIF *objectManager; /*Documentation can be found in the class method declaration above.*/ From 721793a0582174e2edfa1e624bcf67377c8ce981 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 18 Sep 2020 13:38:53 +0200 Subject: [PATCH 349/653] added author tag back --- objectmanager/SystemObject.h | 1 + 1 file changed, 1 insertion(+) diff --git a/objectmanager/SystemObject.h b/objectmanager/SystemObject.h index 9188693e..d9c4236d 100644 --- a/objectmanager/SystemObject.h +++ b/objectmanager/SystemObject.h @@ -13,6 +13,7 @@ * class that is announced to ObjectManager. It automatically includes * itself (and therefore the inheriting class) in the object manager's * list. + * @author Ulrich Mohr * @ingroup system_objects */ class SystemObject: public SystemObjectIF { From 7851a71a8eb96931fbdc5f24ef40b5326665a892 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 14:00:18 +0200 Subject: [PATCH 350/653] commanding service base hotfix --- tmtcservices/CommandingServiceBase.cpp | 2 +- tmtcservices/CommandingServiceBase.h | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index 4cead0e9..0ebc3944 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -384,7 +384,7 @@ void CommandingServiceBase::acceptPacket(uint8_t reportId, } -void CommandingServiceBase::checkAndExecuteFifo(CommandMapIter iter) { +void CommandingServiceBase::checkAndExecuteFifo(CommandMapIter& iter) { store_address_t address; if (iter->second.fifo.retrieve(&address) != RETURN_OK) { commandMap.erase(&iter); diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index 23b08acf..252b6943 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -39,7 +39,11 @@ class CommandingServiceBase: public SystemObject, public HasReturnvaluesIF { friend void (Factory::setStaticFrameworkObjectIds)(); public: + // We could make this configurable via preprocessor and the FSFWConfig file. + static constexpr uint8_t COMMAND_INFO_FIFO_DEPTH = 3; + static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_SERVICE_BASE; + static const ReturnValue_t EXECUTION_COMPLETE = MAKE_RETURN_CODE(1); static const ReturnValue_t NO_STEP_MESSAGE = MAKE_RETURN_CODE(2); static const ReturnValue_t OBJECT_BUSY = MAKE_RETURN_CODE(3); @@ -223,7 +227,7 @@ protected: uint32_t state; Command_t command; object_id_t objectId; - FIFO fifo; + FIFO fifo; virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, Endianness streamEndianness) const override{ @@ -235,7 +239,7 @@ protected: }; virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, - Endianness streamEndianness) override{ + Endianness streamEndianness) override { return HasReturnvaluesIF::RETURN_FAILED; }; }; @@ -312,7 +316,7 @@ protected: ReturnValue_t sendTmPacket(uint8_t subservice, SerializeIF* content, SerializeIF* header = nullptr); - void checkAndExecuteFifo(CommandMapIter iter); + void checkAndExecuteFifo(CommandMapIter& iter); private: /** From 4587fbb76d1bc356227229dcb1ad44d389d4a5c0 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 14:52:24 +0200 Subject: [PATCH 351/653] srv9 func removed --- pus/Service9TimeManagement.h | 1 - 1 file changed, 1 deletion(-) diff --git a/pus/Service9TimeManagement.h b/pus/Service9TimeManagement.h index 9eed12ca..4802cdec 100644 --- a/pus/Service9TimeManagement.h +++ b/pus/Service9TimeManagement.h @@ -34,7 +34,6 @@ private: SET_TIME = 128 //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format }; - void setIsisClock(Clock::TimeOfDay_t& timeOfDay); }; From b2777faf66885ee6dc440cf1633e7e34c39c4e1a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 15:29:28 +0200 Subject: [PATCH 352/653] queueue factory update --- osal/linux/QueueFactory.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osal/linux/QueueFactory.cpp b/osal/linux/QueueFactory.cpp index afeca547..44def48a 100644 --- a/osal/linux/QueueFactory.cpp +++ b/osal/linux/QueueFactory.cpp @@ -1,15 +1,21 @@ #include "../../ipc/QueueFactory.h" +#include "MessageQueue.h" + +#include "../../ipc/messageQueueDefinitions.h" +#include "../../ipc/MessageQueueSenderIF.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + #include #include -#include "MessageQueue.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" + + #include QueueFactory* QueueFactory::factoryInstance = nullptr; ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, bool ignoreFault) { return MessageQueue::sendMessageFromMessageQueue(sendTo,message, sentFrom,ignoreFault); From 7dc3a7ecbd79440c69cf28cec16950bdc8f44419 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 15:31:15 +0200 Subject: [PATCH 353/653] fix so it compiles --- osal/linux/QueueFactory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osal/linux/QueueFactory.cpp b/osal/linux/QueueFactory.cpp index 44def48a..0860950c 100644 --- a/osal/linux/QueueFactory.cpp +++ b/osal/linux/QueueFactory.cpp @@ -15,7 +15,7 @@ QueueFactory* QueueFactory::factoryInstance = nullptr; ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault) { return MessageQueue::sendMessageFromMessageQueue(sendTo,message, sentFrom,ignoreFault); From 74b9aef36b2dd920565ed119172cade85bcfd421 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 15:33:28 +0200 Subject: [PATCH 354/653] freeRTOS update --- osal/FreeRTOS/QueueFactory.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osal/FreeRTOS/QueueFactory.cpp b/osal/FreeRTOS/QueueFactory.cpp index 0de6ad4f..153d9b51 100644 --- a/osal/FreeRTOS/QueueFactory.cpp +++ b/osal/FreeRTOS/QueueFactory.cpp @@ -4,18 +4,18 @@ #include "MessageQueue.h" -QueueFactory* QueueFactory::factoryInstance = NULL; +QueueFactory* QueueFactory::factoryInstance = nullptr; ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault) { - return MessageQueue::sendMessageFromMessageQueue(sendTo, message, - sentFrom, ignoreFault); + return MessageQueue::sendMessageFromMessageQueue(sendTo,message, + sentFrom,ignoreFault); } QueueFactory* QueueFactory::instance() { - if (factoryInstance == NULL) { + if (factoryInstance == nullptr) { factoryInstance = new QueueFactory; } return factoryInstance; @@ -27,9 +27,9 @@ QueueFactory::QueueFactory() { QueueFactory::~QueueFactory() { } -MessageQueueIF* QueueFactory::createMessageQueue(uint32_t message_depth, +MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) { - return new MessageQueue(message_depth, maxMessageSize); + return new MessageQueue(messageDepth, maxMessageSize); } void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { From cea748676ea2f99343ec0f0dcbd5face9e114fe8 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 15:47:29 +0200 Subject: [PATCH 355/653] linux message queue update --- osal/linux/MessageQueue.cpp | 106 +++++++++++++++++++++++------------- osal/linux/MessageQueue.h | 30 ++++++---- 2 files changed, 87 insertions(+), 49 deletions(-) diff --git a/osal/linux/MessageQueue.cpp b/osal/linux/MessageQueue.cpp index e5c61cae..cfadb793 100644 --- a/osal/linux/MessageQueue.cpp +++ b/osal/linux/MessageQueue.cpp @@ -1,5 +1,6 @@ -#include "../../serviceinterface/ServiceInterfaceStream.h" #include "MessageQueue.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../objectmanager/ObjectManagerIF.h" #include @@ -9,9 +10,11 @@ #include + MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize): id(MessageQueueIF::NO_QUEUE),lastPartner(MessageQueueIF::NO_QUEUE), - defaultDestination(MessageQueueIF::NO_QUEUE) { + defaultDestination(MessageQueueIF::NO_QUEUE), + maxMessageSize(maxMessageSize) { //debug << "MessageQueue::MessageQueue: Creating a queue" << std::endl; mq_attr attributes; this->id = 0; @@ -46,7 +49,7 @@ MessageQueue::~MessageQueue() { status = mq_unlink(name); if(status != 0){ sif::error << "MessageQueue::Destructor: mq_unlink Failed with status: " - << strerror(errno) <> defaultMqMaxMsg and defaultMqMaxMsg < messageDepth) { - // See: https://www.man7.org/linux/man-pages/man3/mq_open.3.html - // This happens if the msg_max value is not large enough - // It is ignored if the executable is run in privileged mode. - // Run the unlockRealtime script or grant the mode manually by using: - // sudo setcap 'CAP_SYS_RESOURCE=+ep' + /* + See: https://www.man7.org/linux/man-pages/man3/mq_open.3.html + This happens if the msg_max value is not large enough + It is ignored if the executable is run in privileged mode. + Run the unlockRealtime script or grant the mode manually by using: + sudo setcap 'CAP_SYS_RESOURCE=+ep' - // Persistent solution for session: - // echo | sudo tee /proc/sys/fs/mqueue/msg_max + Persistent solution for session: + echo | sudo tee /proc/sys/fs/mqueue/msg_max - // Permanent solution: - // sudo nano /etc/sysctl.conf - // Append at end: fs/mqueue/msg_max = - // Apply changes with: sudo sysctl -p + Permanent solution: + sudo nano /etc/sysctl.conf + Append at end: fs/mqueue/msg_max = + Apply changes with: sudo sysctl -p + */ sif::error << "MessageQueue::MessageQueue: Default MQ size " << defaultMqMaxMsg << " is too small for requested size " << messageDepth << std::endl; + sif::error << "This error can be fixed by setting the maximum " + "allowed message size higher!" << std::endl; + } break; } @@ -118,15 +126,15 @@ ReturnValue_t MessageQueue::handleError(mq_attr* attributes, } ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, bool ignoreFault) { + MessageQueueMessageIF* message, bool ignoreFault) { return sendMessageFrom(sendTo, message, this->getId(), false); } -ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) { +ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) { return sendToDefaultFrom(message, this->getId()); } -ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) { +ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) { if (this->lastPartner != 0) { return sendMessageFrom(this->lastPartner, message, this->getId()); } else { @@ -134,21 +142,34 @@ ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) { } } -ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message, +ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message, MessageQueueId_t* receivedFrom) { ReturnValue_t status = this->receiveMessage(message); *receivedFrom = this->lastPartner; return status; } -ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) { +ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { + if(message == nullptr) { + sif::error << "MessageQueue::receiveMessage: Message is " + "nullptr!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + if(message->getMaximumMessageSize() < maxMessageSize) { + sif::error << "MessageQueue::receiveMessage: Message size " + << message->getMaximumMessageSize() + << " too small to receive data!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + unsigned int messagePriority = 0; int status = mq_receive(id,reinterpret_cast(message->getBuffer()), - message->MAX_MESSAGE_SIZE,&messagePriority); + message->getMaximumMessageSize(),&messagePriority); if (status > 0) { this->lastPartner = message->getSender(); //Check size of incoming message. - if (message->messageSize < message->getMinimumMessageSize()) { + if (message->getMessageSize() < message->getMinimumMessageSize()) { return HasReturnvaluesIF::RETURN_FAILED; } return HasReturnvaluesIF::RETURN_OK; @@ -158,7 +179,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) { } else { //No message was received. Keep lastPartner anyway, I might send //something later. But still, delete packet content. - memset(message->getData(), 0, message->MAX_DATA_SIZE); + memset(message->getData(), 0, message->getMaximumMessageSize()); switch(errno){ case EAGAIN: //O_NONBLOCK or MQ_NONBLOCK was set and there are no messages @@ -258,18 +279,19 @@ void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) { this->defaultDestination = defaultDestination; } -ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom, - bool ignoreFault) { - return sendMessageFromMessageQueue(sendTo,message,sentFrom,ignoreFault); - -} - -ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessage* message, +ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom, bool ignoreFault) { return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault); } + +ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + return sendMessageFromMessageQueue(sendTo,message, sentFrom,ignoreFault); + +} + MessageQueueId_t MessageQueue::getDefaultDestination() const { return this->defaultDestination; } @@ -281,11 +303,18 @@ bool MessageQueue::isDefaultDestinationSet() const { uint16_t MessageQueue::queueCounter = 0; ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, - MessageQueueMessage *message, MessageQueueId_t sentFrom, + MessageQueueMessageIF *message, MessageQueueId_t sentFrom, bool ignoreFault) { + if(message == nullptr) { + sif::error << "MessageQueue::sendMessageFromMessageQueue: Message is " + "nullptr!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + message->setSender(sentFrom); int result = mq_send(sendTo, - reinterpret_cast(message->getBuffer()), message->messageSize,0); + reinterpret_cast(message->getBuffer()), + message->getMessageSize(),0); //TODO: Check if we're in ISR. if (result != 0) { @@ -303,13 +332,16 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, //MQ_NONBLOCK flag was set in its attributes, and the //specified queue is full. return MessageQueueIF::FULL; - case EBADF: + case EBADF: { //mq_des doesn't represent a valid message queue descriptor, //or mq_des wasn't opened for writing. - sif::error << "MessageQueue::sendMessage: Configuration error " - << strerror(errno) << " in mq_send mqSendTo: " << sendTo - << " sent from " << sentFrom << std::endl; - /*NO BREAK*/ + sif::error << "MessageQueue::sendMessage: Configuration error, MQ" + << " destination invalid." << std::endl; + sif::error << strerror(errno) << " in " + <<"mq_send to: " << sendTo << " sent from " + << sentFrom << std::endl; + return DESTINVATION_INVALID; + } case EINTR: //The call was interrupted by a signal. case EINVAL: diff --git a/osal/linux/MessageQueue.h b/osal/linux/MessageQueue.h index 31cdca11..239bbbdb 100644 --- a/osal/linux/MessageQueue.h +++ b/osal/linux/MessageQueue.h @@ -1,5 +1,5 @@ -#ifndef MESSAGEQUEUE_H_ -#define MESSAGEQUEUE_H_ +#ifndef FSFW_OSAL_LINUX_MESSAGEQUEUE_H_ +#define FSFW_OSAL_LINUX_MESSAGEQUEUE_H_ #include "../../internalError/InternalErrorReporterIF.h" #include "../../ipc/MessageQueueIF.h" @@ -56,14 +56,14 @@ public: * @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. */ virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, bool ignoreFault = false ); + MessageQueueMessageIF* message, bool ignoreFault = false ); /** * @brief This operation sends a message to the default destination. * @details As in the sendMessage method, this function uses the sendToDefault call of the * MessageQueueSender parent class and adds its queue id as "sentFrom" information. * @param message A pointer to a previously created message, which is sent. */ - virtual ReturnValue_t sendToDefault( MessageQueueMessage* message ); + virtual ReturnValue_t sendToDefault( MessageQueueMessageIF* message ); /** * @brief This operation sends a message to the last communication partner. * @details This operation simplifies answering an incoming message by using the stored @@ -71,7 +71,7 @@ public: * (i.e. lastPartner is zero), an error code is returned. * @param message A pointer to a previously created message, which is sent. */ - ReturnValue_t reply( MessageQueueMessage* message ); + ReturnValue_t reply( MessageQueueMessageIF* message ); /** * @brief This function reads available messages from the message queue and returns the sender. @@ -80,7 +80,7 @@ public: * @param message A pointer to a message in which the received data is stored. * @param receivedFrom A pointer to a queue id in which the sender's id is stored. */ - ReturnValue_t receiveMessage(MessageQueueMessage* message, + ReturnValue_t receiveMessage(MessageQueueMessageIF* message, MessageQueueId_t *receivedFrom); /** @@ -91,7 +91,7 @@ public: * message's content is cleared and the function returns immediately. * @param message A pointer to a message in which the received data is stored. */ - ReturnValue_t receiveMessage(MessageQueueMessage* message); + ReturnValue_t receiveMessage(MessageQueueMessageIF* message); /** * Deletes all pending messages in the queue. * @param count The number of flushed messages. @@ -114,7 +114,9 @@ public: * This variable is set to zero by default. * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. */ - virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ); + virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault = false ); /** * \brief The sendToDefault method sends a queue message to the default destination. * \details In all other aspects, it works identical to the sendMessage method. @@ -122,7 +124,8 @@ public: * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. * This variable is set to zero by default. */ - virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); + virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message, + MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); /** * \brief This method is a simple setter for the default destination. */ @@ -145,7 +148,9 @@ protected: * This variable is set to zero by default. * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. */ - static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE,bool ignoreFault=false); + static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE, + bool ignoreFault=false); private: /** * @brief The class stores the queue id it got assigned from the operating system in this attribute. @@ -171,11 +176,12 @@ private: /** * The name of the message queue, stored for unlinking */ - char name[5]; + char name[16]; static uint16_t queueCounter; + const size_t maxMessageSize; ReturnValue_t handleError(mq_attr* attributes, uint32_t messageDepth); }; -#endif /* MESSAGEQUEUE_H_ */ +#endif /* FSFW_OSAL_LINUX_MESSAGEQUEUE_H_ */ From 8652f2f13f1ff7e358e6d0b803a04772b9b83e58 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 15:50:10 +0200 Subject: [PATCH 356/653] message queue IF update --- ipc/MessageQueueIF.h | 178 +++++++++++++++++++++++++++---------------- 1 file changed, 113 insertions(+), 65 deletions(-) diff --git a/ipc/MessageQueueIF.h b/ipc/MessageQueueIF.h index b0347db9..44b6f4c0 100644 --- a/ipc/MessageQueueIF.h +++ b/ipc/MessageQueueIF.h @@ -1,61 +1,77 @@ #ifndef FSFW_IPC_MESSAGEQUEUEIF_H_ #define FSFW_IPC_MESSAGEQUEUEIF_H_ -// COULDDO: We could support blocking calls - -#include "messageQueueDefinitions.h" -#include "MessageQueueMessage.h" +#include +#include "MessageQueueMessageIF.h" #include "../returnvalues/HasReturnvaluesIF.h" +#include + + +// COULDDO: We could support blocking calls +// semaphores are being implemented, which makes this idea even more iteresting. + +/** + * @defgroup message_queue Message Queue + * @brief Message Queue related software components + */ class MessageQueueIF { public: static const MessageQueueId_t NO_QUEUE = 0; static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF; - /** - * No new messages on the queue - */ + //! No new messages on the queue static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(1); - /** - * No space left for more messages - */ + //! No space left for more messages static const ReturnValue_t FULL = MAKE_RETURN_CODE(2); - /** - * Returned if a reply method was called without partner - */ + //! Returned if a reply method was called without partner static const ReturnValue_t NO_REPLY_PARTNER = MAKE_RETURN_CODE(3); + //! Returned if the target destination is invalid. + static constexpr ReturnValue_t DESTINVATION_INVALID = MAKE_RETURN_CODE(4); virtual ~MessageQueueIF() {} /** * @brief This operation sends a message to the last communication partner. - * @details This operation simplifies answering an incoming message by using the stored - * lastParnter information as destination. If there was no message received yet - * (i.e. lastPartner is zero), an error code is returned. - * @param message A pointer to a previously created message, which is sent. - * \return RETURN_OK if ok - * \return NO_REPLY_PARTNER Should return NO_REPLY_PARTNER if partner was found + * @details + * This operation simplifies answering an incoming message by using the + * stored lastParnter information as destination. If there was no message + * received yet (i.e. lastPartner is zero), an error code is returned. + * @param message + * A pointer to a previously created message, which is sent. + * @return + * -@c RETURN_OK if ok + * -@c NO_REPLY_PARTNER Should return NO_REPLY_PARTNER if partner was found. */ - virtual ReturnValue_t reply( MessageQueueMessage* message ) = 0; + virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0; /** - * @brief This function reads available messages from the message queue and returns the sender. - * @details It works identically to the other receiveMessage call, but in addition returns the - * sender's queue id. - * @param message A pointer to a message in which the received data is stored. - * @param receivedFrom A pointer to a queue id in which the sender's id is stored. + * @brief This function reads available messages from the message queue + * and returns the sender. + * @details + * It works identically to the other receiveMessage call, but in addition + * returns the sender's queue id. + * @param message + * A pointer to a message in which the received data is stored. + * @param receivedFrom + * A pointer to a queue id in which the sender's id is stored. */ - virtual ReturnValue_t receiveMessage(MessageQueueMessage* message, + virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message, MessageQueueId_t *receivedFrom) = 0; /** * @brief This function reads available messages from the message queue. - * @details If data is available it is stored in the passed message pointer. The message's - * original content is overwritten and the sendFrom information is stored in the - * lastPartner attribute. Else, the lastPartner information remains untouched, the - * message's content is cleared and the function returns immediately. - * @param message A pointer to a message in which the received data is stored. + * @details + * If data is available it is stored in the passed message pointer. + * The message's original content is overwritten and the sendFrom + * information is stored in theblastPartner attribute. Else, the lastPartner + * information remains untouched, the message's content is cleared and the + * function returns immediately. + * @param message + * A pointer to a message in which the received data is stored. + * @return -@c RETURN_OK on success + * -@c MessageQueueIF::EMPTY if queue is empty */ - virtual ReturnValue_t receiveMessage(MessageQueueMessage* message) = 0; + virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0; /** * Deletes all pending messages in the queue. * @param count The number of flushed messages. @@ -63,57 +79,89 @@ public: */ virtual ReturnValue_t flush(uint32_t* count) = 0; /** - * @brief This method returns the message queue id of the last communication partner. + * @brief This method returns the message queue + * id of the last communication partner. */ virtual MessageQueueId_t getLastPartner() const = 0; /** - * @brief This method returns the message queue id of this class's message queue. + * @brief This method returns the message queue + * id of this class's message queue. */ virtual MessageQueueId_t getId() const = 0; /** - * \brief With the sendMessage call, a queue message is sent to a receiving queue. - * \details This method takes the message provided, adds the sentFrom information and passes - * it on to the destination provided with an operating system call. The OS's return - * value is returned. - * \param sendTo This parameter specifies the message queue id to send the message to. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. - * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full (if implemented). + * @brief With the sendMessage call, a queue message + * is sent to a receiving queue. + * @details + * This method takes the message provided, adds the sentFrom information + * and passes it on to the destination provided with an operating system + * call. The OS's returnvalue is returned. + * @param sendTo + * This parameter specifies the message queue id to send the message to. + * @param message + * This is a pointer to a previously created message, which is sent. + * @param sentFrom + * The sentFrom information can be set to inject the sender's queue id + * into the message. This variable is set to zero by default. + * @param ignoreFault + * If set to true, the internal software fault counter is not incremented + * if queue is full (if implemented). + * @return -@c RETURN_OK on success + * -@c MessageQueueIF::FULL if queue is full */ - virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0; - /** - * @brief This operation sends a message to the given destination. - * @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes its - * queue id as "sentFrom" parameter. - * @param sendTo This parameter specifies the message queue id of the destination message queue. - * @param message A pointer to a previously created message, which is sent. - * @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. - */ - virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, MessageQueueMessage* message, bool ignoreFault = false ) = 0; + virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault = false ) = 0; /** - * \brief The sendToDefaultFrom method sends a queue message to the default destination. - * \details In all other aspects, it works identical to the sendMessage method. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. + * @brief This operation sends a message to the given destination. + * @details + * It directly uses the sendMessage call of the MessageQueueSender parent, + * but passes its queue id as "sentFrom" parameter. + * @param sendTo + * This parameter specifies the message queue id of the destination + * message queue. + * @param message + * A pointer to a previously created message, which is sent. + * @param ignoreFault + * If set to true, the internal software fault counter is not incremented + * if queue is full. */ - virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0; + virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, + MessageQueueMessageIF* message, bool ignoreFault = false ) = 0; + + /** + * @brief The sendToDefaultFrom method sends a queue message + * to the default destination. + * @details + * In all other aspects, it works identical to the sendMessage method. + * @param message + * This is a pointer to a previously created message, which is sent. + * @param sentFrom + * The sentFrom information can be set to inject the sender's queue id + * into the message. This variable is set to zero by default. + * @return -@c RETURN_OK on success + * -@c MessageQueueIF::FULL if queue is full + */ + virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message, + MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0; /** * @brief This operation sends a message to the default destination. - * @details As in the sendMessage method, this function uses the sendToDefault call of the - * Implementation class and adds its queue id as "sentFrom" information. + * @details + * As in the sendMessage method, this function uses the sendToDefault + * call of the Implementation class and adds its queue id as + * "sentFrom" information. * @param message A pointer to a previously created message, which is sent. + * @return -@c RETURN_OK on success + * -@c MessageQueueIF::FULL if queue is full */ - virtual ReturnValue_t sendToDefault( MessageQueueMessage* message ) = 0; + virtual ReturnValue_t sendToDefault( MessageQueueMessageIF* message ) = 0; /** - * \brief This method is a simple setter for the default destination. + * @brief This method is a simple setter for the default destination. */ virtual void setDefaultDestination(MessageQueueId_t defaultDestination) = 0; /** - * \brief This method is a simple getter for the default destination. + * @brief This method is a simple getter for the default destination. */ virtual MessageQueueId_t getDefaultDestination() const = 0; @@ -122,4 +170,4 @@ public: -#endif /* FRAMEWORK_IPC_MESSAGEQUEUEIF_H_ */ +#endif /* FSFW_IPC_MESSAGEQUEUEIF_H_ */ From 87fb17f39a4320eb8b40517ae79e170950b1b3a5 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 15:52:26 +0200 Subject: [PATCH 357/653] IF replacements --- ipc/MessageQueueSenderIF.h | 2 +- osal/FreeRTOS/QueueFactory.cpp | 2 +- osal/linux/Clock.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ipc/MessageQueueSenderIF.h b/ipc/MessageQueueSenderIF.h index 7eea5146..42d4078f 100644 --- a/ipc/MessageQueueSenderIF.h +++ b/ipc/MessageQueueSenderIF.h @@ -15,7 +15,7 @@ public: * Not sure whether this is actually a good idea. */ static ReturnValue_t sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom = MessageQueueIF::NO_QUEUE, bool ignoreFault = false); private: diff --git a/osal/FreeRTOS/QueueFactory.cpp b/osal/FreeRTOS/QueueFactory.cpp index 153d9b51..493ec925 100644 --- a/osal/FreeRTOS/QueueFactory.cpp +++ b/osal/FreeRTOS/QueueFactory.cpp @@ -8,7 +8,7 @@ QueueFactory* QueueFactory::factoryInstance = nullptr; ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, bool ignoreFault) { return MessageQueue::sendMessageFromMessageQueue(sendTo,message, sentFrom,ignoreFault); diff --git a/osal/linux/Clock.cpp b/osal/linux/Clock.cpp index b14f2a97..4de18f83 100644 --- a/osal/linux/Clock.cpp +++ b/osal/linux/Clock.cpp @@ -6,8 +6,8 @@ #include #include #include +#include -//#include uint16_t Clock::leapSeconds = 0; MutexIF* Clock::timeMutex = NULL; From 98333b92eff9389783a2b70c4979eed4b96d5e88 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 15:57:26 +0200 Subject: [PATCH 358/653] srv17 id added, include fix for linux --- objectmanager/frameworkObjects.h | 1 + osal/linux/Clock.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/objectmanager/frameworkObjects.h b/objectmanager/frameworkObjects.h index 4a30e70a..a7103018 100644 --- a/objectmanager/frameworkObjects.h +++ b/objectmanager/frameworkObjects.h @@ -8,6 +8,7 @@ enum framework_objects { PUS_SERVICE_2 = 0x53000002, PUS_SERVICE_5 = 0x53000005, PUS_SERVICE_8 = 0x53000008, + PUS_SERVICE_17 = 0x53000017, PUS_SERVICE_200 = 0x53000200, //Generic IDs for IPC, modes, health, events diff --git a/osal/linux/Clock.cpp b/osal/linux/Clock.cpp index b14f2a97..4de18f83 100644 --- a/osal/linux/Clock.cpp +++ b/osal/linux/Clock.cpp @@ -6,8 +6,8 @@ #include #include #include +#include -//#include uint16_t Clock::leapSeconds = 0; MutexIF* Clock::timeMutex = NULL; From ab0f4d8c87aedf5013debc6012da3aebb4389f8a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 16:01:34 +0200 Subject: [PATCH 359/653] service 9 ID added --- objectmanager/frameworkObjects.h | 1 + 1 file changed, 1 insertion(+) diff --git a/objectmanager/frameworkObjects.h b/objectmanager/frameworkObjects.h index a7103018..87439c88 100644 --- a/objectmanager/frameworkObjects.h +++ b/objectmanager/frameworkObjects.h @@ -8,6 +8,7 @@ enum framework_objects { PUS_SERVICE_2 = 0x53000002, PUS_SERVICE_5 = 0x53000005, PUS_SERVICE_8 = 0x53000008, + PUS_SERVICE_9 = 0x53000009, PUS_SERVICE_17 = 0x53000017, PUS_SERVICE_200 = 0x53000200, From de840dcf8df69d5b734951fa7128257fa472cd46 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 16:10:43 +0200 Subject: [PATCH 360/653] last fixes for linux --- ipc/QueueFactory.h | 8 +++++--- osal/linux/QueueFactory.cpp | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ipc/QueueFactory.h b/ipc/QueueFactory.h index 4f4d72c7..0310e534 100644 --- a/ipc/QueueFactory.h +++ b/ipc/QueueFactory.h @@ -1,7 +1,9 @@ -#ifndef FRAMEWORK_IPC_QUEUEFACTORY_H_ -#define FRAMEWORK_IPC_QUEUEFACTORY_H_ +#ifndef FSFW_IPC_QUEUEFACTORY_H_ +#define FSFW_IPC_QUEUEFACTORY_H_ + #include "MessageQueueIF.h" +#include "../ipc/MessageQueueMessage.h" #include /** * Creates message queues. @@ -30,4 +32,4 @@ private: static QueueFactory* factoryInstance; }; -#endif /* FRAMEWORK_IPC_QUEUEFACTORY_H_ */ +#endif /* FSFW_IPC_QUEUEFACTORY_H_ */ diff --git a/osal/linux/QueueFactory.cpp b/osal/linux/QueueFactory.cpp index 0860950c..44def48a 100644 --- a/osal/linux/QueueFactory.cpp +++ b/osal/linux/QueueFactory.cpp @@ -15,7 +15,7 @@ QueueFactory* QueueFactory::factoryInstance = nullptr; ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, bool ignoreFault) { return MessageQueue::sendMessageFromMessageQueue(sendTo,message, sentFrom,ignoreFault); From ed80768c66335e7404e905a94db33ae0e0cc2f78 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 22 Sep 2020 16:13:45 +0200 Subject: [PATCH 361/653] Fixes #194 --- container/ArrayList.h | 5 ++--- container/FixedOrderedMultimap.h | 7 +++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/container/ArrayList.h b/container/ArrayList.h index be89761e..37df6d54 100644 --- a/container/ArrayList.h +++ b/container/ArrayList.h @@ -95,10 +95,9 @@ public: //SHOULDDO this should be implemented as non-member bool operator!=(const typename ArrayList::Iterator& other) const { - return !(*this == other); + return !(*this ==other); } - } - ; + }; /** * Number of Elements stored in this List diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 31282f80..c5fd2184 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -10,10 +10,9 @@ template> class FixedOrderedMultimap { public: - 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); + static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP; + static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01); + static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02); private: typedef KEY_COMPARE compare; From 0bc3807c18d9ec2b254a53a4d62d8da22626ad10 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 16:22:37 +0200 Subject: [PATCH 362/653] added FIFO --- container/SharedRingBuffer.cpp | 25 +++++++++++++++++++++++++ container/SharedRingBuffer.h | 16 ++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/container/SharedRingBuffer.cpp b/container/SharedRingBuffer.cpp index 800e75d3..48bdb9df 100644 --- a/container/SharedRingBuffer.cpp +++ b/container/SharedRingBuffer.cpp @@ -9,6 +9,7 @@ SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size, mutex = MutexFactory::instance()->createMutex(); } + SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer, const size_t size, bool overwriteOld, size_t maxExcessBytes): SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld, @@ -16,6 +17,11 @@ SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer, mutex = MutexFactory::instance()->createMutex(); } + +void SharedRingBuffer::setToUseReceiveSizeFIFO(uint32_t fifoDepth) { + this->fifoDepth = fifoDepth; +} + ReturnValue_t SharedRingBuffer::lockRingBufferMutex( MutexIF::TimeoutType timeoutType, dur_millis_t timeout) { return mutex->lockMutex(timeoutType, timeout); @@ -25,6 +31,25 @@ ReturnValue_t SharedRingBuffer::unlockRingBufferMutex() { return mutex->unlockMutex(); } + + MutexIF* SharedRingBuffer::getMutexHandle() const { return mutex; } + +ReturnValue_t SharedRingBuffer::initialize() { + if(fifoDepth > 0) { + receiveSizesFIFO = new DynamicFIFO(fifoDepth); + } + return SystemObject::initialize(); +} + +DynamicFIFO* SharedRingBuffer::getReceiveSizesFIFO() { + if(receiveSizesFIFO == nullptr) { + // Configuration error. + sif::warning << "SharedRingBuffer::getReceiveSizesFIFO: Ring buffer" + << " was not configured to have sizes FIFO, returning nullptr!" + << std::endl; + } + return receiveSizesFIFO; +} diff --git a/container/SharedRingBuffer.h b/container/SharedRingBuffer.h index 80c068b3..c9e0ae3f 100644 --- a/container/SharedRingBuffer.h +++ b/container/SharedRingBuffer.h @@ -1,6 +1,7 @@ #ifndef FSFW_CONTAINER_SHAREDRINGBUFFER_H_ #define FSFW_CONTAINER_SHAREDRINGBUFFER_H_ +#include #include "SimpleRingBuffer.h" #include "../ipc/MutexIF.h" #include "../objectmanager/SystemObject.h" @@ -26,6 +27,8 @@ public: SharedRingBuffer(object_id_t objectId, const size_t size, bool overwriteOld, size_t maxExcessBytes); + void setToUseReceiveSizeFIFO(uint32_t fifoDepth); + /** * This constructor takes an external buffer with the specified size. * @param buffer @@ -59,8 +62,21 @@ public: * @return */ MutexIF* getMutexHandle() const; + + ReturnValue_t initialize() override; + + /** + * If the shared ring buffer was configured to have a sizes FIFO, a handle + * to that FIFO can be retrieved with this function. + * Do not forget to protect access with a lock if required! + * @return + */ + DynamicFIFO* getReceiveSizesFIFO(); private: MutexIF* mutex = nullptr; + + size_t fifoDepth = 0; + DynamicFIFO* receiveSizesFIFO = nullptr; }; From 74a4c98ca73b25de31e2ec678aeb9aff5f900e96 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 22 Sep 2020 16:23:35 +0200 Subject: [PATCH 363/653] Small format stuff --- container/ArrayList.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/ArrayList.h b/container/ArrayList.h index 37df6d54..19454777 100644 --- a/container/ArrayList.h +++ b/container/ArrayList.h @@ -95,7 +95,7 @@ public: //SHOULDDO this should be implemented as non-member bool operator!=(const typename ArrayList::Iterator& other) const { - return !(*this ==other); + return !(*this == other); } }; From 2f73841580339d39d0e784b60a4bc49867eff112 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 16:24:40 +0200 Subject: [PATCH 364/653] include fix --- container/SharedRingBuffer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/SharedRingBuffer.h b/container/SharedRingBuffer.h index c9e0ae3f..fdc9d626 100644 --- a/container/SharedRingBuffer.h +++ b/container/SharedRingBuffer.h @@ -1,8 +1,8 @@ #ifndef FSFW_CONTAINER_SHAREDRINGBUFFER_H_ #define FSFW_CONTAINER_SHAREDRINGBUFFER_H_ -#include #include "SimpleRingBuffer.h" +#include "DynamicFIFO.h" #include "../ipc/MutexIF.h" #include "../objectmanager/SystemObject.h" #include "../timemanager/Clock.h" From 978d7514a486482869a31852c571ea0009f0ffa0 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 16:32:59 +0200 Subject: [PATCH 365/653] added doc, changed type --- container/SharedRingBuffer.cpp | 2 +- container/SharedRingBuffer.h | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/container/SharedRingBuffer.cpp b/container/SharedRingBuffer.cpp index 48bdb9df..6ddb3d3e 100644 --- a/container/SharedRingBuffer.cpp +++ b/container/SharedRingBuffer.cpp @@ -18,7 +18,7 @@ SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer, } -void SharedRingBuffer::setToUseReceiveSizeFIFO(uint32_t fifoDepth) { +void SharedRingBuffer::setToUseReceiveSizeFIFO(size_t fifoDepth) { this->fifoDepth = fifoDepth; } diff --git a/container/SharedRingBuffer.h b/container/SharedRingBuffer.h index fdc9d626..64d7ee29 100644 --- a/container/SharedRingBuffer.h +++ b/container/SharedRingBuffer.h @@ -27,7 +27,15 @@ public: SharedRingBuffer(object_id_t objectId, const size_t size, bool overwriteOld, size_t maxExcessBytes); - void setToUseReceiveSizeFIFO(uint32_t fifoDepth); + /** + * @brief This function can be used to add an optional FIFO to the class + * @details + * This FIFO will be allocated in the initialize function (and will + * have a fixed maximum size after that). It can be used to store + * values like packet sizes, for example for a shared ring buffer + * used by producer/consumer tasks. + */ + void setToUseReceiveSizeFIFO(size_t fifoDepth); /** * This constructor takes an external buffer with the specified size. From 59f72d1031a20e403cd52d2e3922e28c293b6537 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 22 Sep 2020 16:59:13 +0200 Subject: [PATCH 366/653] Small fix with new pus services --- events/fwSubsystemIdRanges.h | 1 + returnvalues/FwClassIds.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/events/fwSubsystemIdRanges.h b/events/fwSubsystemIdRanges.h index 5e086f0e..1b0b238e 100644 --- a/events/fwSubsystemIdRanges.h +++ b/events/fwSubsystemIdRanges.h @@ -19,6 +19,7 @@ enum { SYSTEM_MANAGER_1 = 75, SYSTEM_1 = 79, PUS_SERVICE_1 = 80, + PUS_SERVICE_9 = 89, PUS_SERVICE_17 = 97, FW_SUBSYSTEM_ID_RANGE }; diff --git a/returnvalues/FwClassIds.h b/returnvalues/FwClassIds.h index e547025b..53add6a0 100644 --- a/returnvalues/FwClassIds.h +++ b/returnvalues/FwClassIds.h @@ -56,7 +56,6 @@ enum { DEVICE_COMMUNICATION_IF, //DC BSP, //BSP TIME_STAMPER_IF, //TSI 53 - //TODO This will shift all IDs for FLP SGP4PROPAGATOR_CLASS, //SGP4 54 MUTEX_IF, //MUX 55 MESSAGE_QUEUE_IF,//MQI 56 From 4d1492f130e64a4e8ec803814ca6f4bf9bcaccbc Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 26 Sep 2020 14:13:20 +0200 Subject: [PATCH 367/653] event cfg file loc not explicit anymore --- events/Event.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/events/Event.h b/events/Event.h index e22c9db1..f8410f32 100644 --- a/events/Event.h +++ b/events/Event.h @@ -4,7 +4,7 @@ #include #include "fwSubsystemIdRanges.h" //could be move to more suitable location -#include +#include typedef uint16_t EventId_t; typedef uint8_t EventSeverity_t; From 22d9b771654aba5698c6e4f94d8eb7a925d159e2 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 26 Sep 2020 14:19:51 +0200 Subject: [PATCH 368/653] added documentation --- tasks/FixedSlotSequence.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tasks/FixedSlotSequence.h b/tasks/FixedSlotSequence.h index 19a05f21..077dd10b 100644 --- a/tasks/FixedSlotSequence.h +++ b/tasks/FixedSlotSequence.h @@ -139,6 +139,15 @@ public: */ ReturnValue_t checkSequence() const; + /** + * @brief A custom check can be injected for the respective slot list. + * @details + * This can be used by the developer to check the validity of a certain + * sequence. The function will be run in the #checkSequence function. + * The general check will be continued for now if the custom check function + * fails but a diagnostic debug output will be given. + * @param customCheckFunction + */ void addCustomCheck(ReturnValue_t (*customCheckFunction)(const SlotList &)); /** From 13b68f10a017adb82e5f9158af72a13eff3cf5cb Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 26 Sep 2020 14:24:09 +0200 Subject: [PATCH 369/653] added usage of new interface --- osal/FreeRTOS/MessageQueue.cpp | 131 ++++++++++++------ osal/FreeRTOS/MessageQueue.h | 243 ++++++++++++++++----------------- osal/FreeRTOS/QueueFactory.cpp | 17 ++- 3 files changed, 213 insertions(+), 178 deletions(-) diff --git a/osal/FreeRTOS/MessageQueue.cpp b/osal/FreeRTOS/MessageQueue.cpp index 3bbd4d9d..2dfe5ab6 100644 --- a/osal/FreeRTOS/MessageQueue.cpp +++ b/osal/FreeRTOS/MessageQueue.cpp @@ -1,41 +1,76 @@ #include "MessageQueue.h" - +#include "../../objectmanager/ObjectManagerIF.h" #include "../../serviceinterface/ServiceInterfaceStream.h" -// TODO I guess we should have a way of checking if we are in an ISR and then use the "fromISR" versions of all calls - -MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size) : -defaultDestination(0),lastPartner(0) { - handle = xQueueCreate(message_depth, max_message_size); - if (handle == NULL) { - sif::error << "MessageQueue creation failed" << std::endl; +// TODO I guess we should have a way of checking if we are in an ISR and then +// use the "fromISR" versions of all calls +// As a first step towards this, introduces system context variable which needs +// to be switched manually +// Haven't found function to find system context. +MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize): + maxMessageSize(maxMessageSize) { + handle = xQueueCreate(messageDepth, maxMessageSize); + if (handle == nullptr) { + sif::error << "MessageQueue::MessageQueue Creation failed" << std::endl; } } MessageQueue::~MessageQueue() { - if (handle != NULL) { + if (handle != nullptr) { vQueueDelete(handle); } } +void MessageQueue::switchSystemContext(CallContext callContext) { + this->callContext = callContext; +} + ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, bool ignoreFault) { + MessageQueueMessageIF* message, bool ignoreFault) { return sendMessageFrom(sendTo, message, this->getId(), ignoreFault); } -ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) { +ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) { return sendToDefaultFrom(message, this->getId()); } -ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) { - if (this->lastPartner != 0) { +ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message, + MessageQueueId_t sentFrom, bool ignoreFault) { + return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault); +} + +ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) { + if (this->lastPartner != MessageQueueIF::NO_QUEUE) { return sendMessageFrom(this->lastPartner, message, this->getId()); } else { return NO_REPLY_PARTNER; } } -ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message, +ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault, + callContext); +} + + +ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault) { + if (result != pdPASS) { + if (not ignoreFault) { + InternalErrorReporterIF* internalErrorReporter = objectManager-> + get( + objects::INTERNAL_ERROR_REPORTER); + if (internalErrorReporter != nullptr) { + internalErrorReporter->queueMessageNotSent(); + } + } + return MessageQueueIF::FULL; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message, MessageQueueId_t* receivedFrom) { ReturnValue_t status = this->receiveMessage(message); if(status == HasReturnvaluesIF::RETURN_OK) { @@ -44,8 +79,9 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message, return status; } -ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) { - BaseType_t result = xQueueReceive(handle,reinterpret_cast(message->getBuffer()), 0); +ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { + BaseType_t result = xQueueReceive(handle,reinterpret_cast( + message->getBuffer()), 0); if (result == pdPASS){ this->lastPartner = message->getSender(); return HasReturnvaluesIF::RETURN_OK; @@ -66,50 +102,55 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) { } MessageQueueId_t MessageQueue::getId() const { - return (MessageQueueId_t) handle; + return reinterpret_cast(handle); } void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) { + defaultDestinationSet = true; this->defaultDestination = defaultDestination; } -ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom, - bool ignoreFault) { - return sendMessageFromMessageQueue(sendTo,message,sentFrom,ignoreFault); -} - -ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessage* message, - MessageQueueId_t sentFrom, bool ignoreFault) { - return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault); -} - MessageQueueId_t MessageQueue::getDefaultDestination() const { return defaultDestination; } bool MessageQueue::isDefaultDestinationSet() const { - return 0; + return defaultDestinationSet; } + +// static core function to send messages. ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, - MessageQueueMessage *message, MessageQueueId_t sentFrom, - bool ignoreFault) { - message->setSender(sentFrom); + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault, CallContext callContext) { + BaseType_t result = pdFALSE; + QueueHandle_t destination = nullptr; - BaseType_t result = xQueueSendToBack(reinterpret_cast(sendTo), - reinterpret_cast(message->getBuffer()), 0); - if (result != pdPASS) { - if (!ignoreFault) { - InternalErrorReporterIF* internalErrorReporter = objectManager->get( - objects::INTERNAL_ERROR_REPORTER); - if (internalErrorReporter != NULL) { - internalErrorReporter->queueMessageNotSent(); - } - } - return MessageQueueIF::FULL; + if(sendTo == MessageQueueIF::NO_QUEUE or sendTo == 0x00) { + return MessageQueueIF::DESTINVATION_INVALID; + } + else { + destination = reinterpret_cast(sendTo); } - return HasReturnvaluesIF::RETURN_OK; + message->setSender(sentFrom); + + + if(callContext == CallContext::TASK) { + result = xQueueSendToBack(destination, + static_cast(message->getBuffer()), 0); + } + else { + /* If the call context is from an interrupt, + * request a context switch if a higher priority task + * was blocked by the interrupt. */ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + result = xQueueSendFromISR(reinterpret_cast(sendTo), + static_cast(message->getBuffer()), + &xHigherPriorityTaskWoken); + if(xHigherPriorityTaskWoken == pdTRUE) { + TaskManagement::requestContextSwitch(callContext); + } + } + return handleSendResult(result, ignoreFault); } - diff --git a/osal/FreeRTOS/MessageQueue.h b/osal/FreeRTOS/MessageQueue.h index aa3d54c1..b99bf7c8 100644 --- a/osal/FreeRTOS/MessageQueue.h +++ b/osal/FreeRTOS/MessageQueue.h @@ -1,159 +1,150 @@ -#ifndef MESSAGEQUEUE_H_ -#define MESSAGEQUEUE_H_ +#ifndef FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_ +#define FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_ #include "../../internalError/InternalErrorReporterIF.h" #include "../../ipc/MessageQueueIF.h" -#include "../../ipc/MessageQueueMessage.h" +#include "../../ipc/MessageQueueMessageIF.h" +#include "../../osal/FreeRTOS/TaskManagement.h" -#include -#include +#include +#include +#include -//TODO this class assumes that MessageQueueId_t is the same size as void* (the FreeRTOS handle type), compiler will catch this but it might be nice to have something checking or even an always working solution +// TODO: this class assumes that MessageQueueId_t is the same size as void* +// (the FreeRTOS handle type), compiler will catch this but it might be nice +// to have something checking or even an always working solution // https://scaryreasoner.wordpress.com/2009/02/28/checking-sizeof-at-compile-time/ /** - * @brief This class manages sending and receiving of message queue messages. + * @brief This class manages sending and receiving of + * message queue messages. + * @details + * Message queues are used to pass asynchronous messages between processes. + * They work like post boxes, where all incoming messages are stored in FIFO + * order. This class creates a new receiving queue and provides methods to fetch + * received messages. Being a child of MessageQueueSender, this class also + * provides methods to send a message to a user-defined or a default destination. + * In addition it also provides a reply method to answer to the queue it + * received its last message from. * - * @details Message queues are used to pass asynchronous messages between processes. - * They work like post boxes, where all incoming messages are stored in FIFO - * order. This class creates a new receiving queue and provides methods to fetch - * received messages. Being a child of MessageQueueSender, this class also provides - * methods to send a message to a user-defined or a default destination. In addition - * it also provides a reply method to answer to the queue it received its last message - * from. - * The MessageQueue should be used as "post box" for a single owning object. So all - * message queue communication is "n-to-one". - * For creating the queue, as well as sending and receiving messages, the class makes - * use of the operating system calls provided. - * \ingroup message_queue + * The MessageQueue should be used as "post box" for a single owning object. + * So all message queue communication is "n-to-one". + * For creating the queue, as well as sending and receiving messages, the class + * makes use of the operating system calls provided. + * + * Please keep in mind that FreeRTOS offers different calls for message queue + * operations if called from an ISR. + * For now, the system context needs to be switched manually. + * @ingroup osal + * @ingroup message_queue */ class MessageQueue : public MessageQueueIF { friend class MessageQueueSenderIF; public: /** * @brief The constructor initializes and configures the message queue. - * @details By making use of the according operating system call, a message queue is created - * and initialized. The message depth - the maximum number of messages to be - * buffered - may be set with the help of a parameter, whereas the message size is - * automatically set to the maximum message queue message size. The operating system - * sets the message queue id, or i case of failure, it is set to zero. - * @param message_depth The number of messages to be buffered before passing an error to the - * sender. Default is three. - * @param max_message_size With this parameter, the maximum message size can be adjusted. - * This should be left default. + * @details + * By making use of the according operating system call, a message queue + * is created and initialized. The message depth - the maximum number of + * messages to be buffered - may be set with the help of a parameter, + * whereas the message size is automatically set to the maximum message + * queue message size. The operating system sets the message queue id, or + * in case of failure, it is set to zero. + * @param message_depth + * The number of messages to be buffered before passing an error to the + * sender. Default is three. + * @param max_message_size + * With this parameter, the maximum message size can be adjusted. + * This should be left default. */ - MessageQueue( size_t message_depth = 3, size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE ); + MessageQueue( size_t messageDepth = 3, + size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE ); + + /** Copying message queues forbidden */ + MessageQueue(const MessageQueue&) = delete; + MessageQueue& operator=(const MessageQueue&) = delete; + /** * @brief The destructor deletes the formerly created message queue. - * @details This is accomplished by using the delete call provided by the operating system. + * @details This is accomplished by using the delete call provided + * by the operating system. */ virtual ~MessageQueue(); + /** - * @brief This operation sends a message to the given destination. - * @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes its - * queue id as "sentFrom" parameter. - * @param sendTo This parameter specifies the message queue id of the destination message queue. - * @param message A pointer to a previously created message, which is sent. - * @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. + * This function is used to switch the call context. This has to be called + * if a message is sent or received from an ISR! + * @param callContext */ + void switchSystemContext(CallContext callContext); + + /** MessageQueueIF implementation */ ReturnValue_t sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, bool ignoreFault = false ); - /** - * @brief This operation sends a message to the default destination. - * @details As in the sendMessage method, this function uses the sendToDefault call of the - * MessageQueueSender parent class and adds its queue id as "sentFrom" information. - * @param message A pointer to a previously created message, which is sent. - */ - ReturnValue_t sendToDefault( MessageQueueMessage* message ); - /** - * @brief This operation sends a message to the last communication partner. - * @details This operation simplifies answering an incoming message by using the stored - * lastParnter information as destination. If there was no message received yet - * (i.e. lastPartner is zero), an error code is returned. - * @param message A pointer to a previously created message, which is sent. - */ - ReturnValue_t reply( MessageQueueMessage* message ); + MessageQueueMessageIF* message, bool ignoreFault = false) override; - /** - * @brief This function reads available messages from the message queue and returns the sender. - * @details It works identically to the other receiveMessage call, but in addition returns the - * sender's queue id. - * @param message A pointer to a message in which the received data is stored. - * @param receivedFrom A pointer to a queue id in which the sender's id is stored. - */ - ReturnValue_t receiveMessage(MessageQueueMessage* message, - MessageQueueId_t *receivedFrom); + ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override; - /** - * @brief This function reads available messages from the message queue. - * @details If data is available it is stored in the passed message pointer. The message's - * original content is overwritten and the sendFrom information is stored in the - * lastPartner attribute. Else, the lastPartner information remains untouched, the - * message's content is cleared and the function returns immediately. - * @param message A pointer to a message in which the received data is stored. - */ - ReturnValue_t receiveMessage(MessageQueueMessage* message); - /** - * Deletes all pending messages in the queue. - * @param count The number of flushed messages. - * @return RETURN_OK on success. - */ - ReturnValue_t flush(uint32_t* count); - /** - * @brief This method returns the message queue id of the last communication partner. - */ - MessageQueueId_t getLastPartner() const; - /** - * @brief This method returns the message queue id of this class's message queue. - */ - MessageQueueId_t getId() const; - /** - * \brief With the sendMessage call, a queue message is sent to a receiving queue. - * \details This method takes the message provided, adds the sentFrom information and passes - * it on to the destination provided with an operating system call. The OS's return - * value is returned. - * \param sendTo This parameter specifies the message queue id to send the message to. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. - * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. - */ - virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); - /** - * \brief The sendToDefault method sends a queue message to the default destination. - * \details In all other aspects, it works identical to the sendMessage method. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. - */ - virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); - /** - * \brief This method is a simple setter for the default destination. - */ - void setDefaultDestination(MessageQueueId_t defaultDestination); - /** - * \brief This method is a simple getter for the default destination. - */ - MessageQueueId_t getDefaultDestination() const; + ReturnValue_t reply(MessageQueueMessageIF* message) override; + virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, + MessageQueueId_t sentFrom = NO_QUEUE, + bool ignoreFault = false) override; + + virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message, + MessageQueueId_t sentFrom = NO_QUEUE, + bool ignoreFault = false) override; + + ReturnValue_t receiveMessage(MessageQueueMessageIF* message, + MessageQueueId_t *receivedFrom) override; + + ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override; + + ReturnValue_t flush(uint32_t* count) override; + + MessageQueueId_t getLastPartner() const override; + + MessageQueueId_t getId() const override; + + void setDefaultDestination(MessageQueueId_t defaultDestination) override; + + MessageQueueId_t getDefaultDestination() const override; + + bool isDefaultDestinationSet() const override; - bool isDefaultDestinationSet() const; protected: /** - * Implementation to be called from any send Call within MessageQueue and MessageQueueSenderIF - * \details This method takes the message provided, adds the sentFrom information and passes - * it on to the destination provided with an operating system call. The OS's return - * value is returned. - * \param sendTo This parameter specifies the message queue id to send the message to. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. - * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. + * @brief Implementation to be called from any send Call within + * MessageQueue and MessageQueueSenderIF. + * @details + * This method takes the message provided, adds the sentFrom information and + * passes it on to the destination provided with an operating system call. + * The OS's return value is returned. + * @param sendTo + * This parameter specifies the message queue id to send the message to. + * @param message + * This is a pointer to a previously created message, which is sent. + * @param sentFrom + * The sentFrom information can be set to inject the sender's queue id into + * the message. This variable is set to zero by default. + * @param ignoreFault + * If set to true, the internal software fault counter is not incremented + * if queue is full. + * @param context Specify whether call is made from task or from an ISR. */ - static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE,bool ignoreFault=false); + static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE, + bool ignoreFault=false, CallContext callContext = CallContext::TASK); + + static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault); + private: + bool defaultDestinationSet = false; QueueHandle_t handle; - MessageQueueId_t defaultDestination; - MessageQueueId_t lastPartner; + MessageQueueId_t defaultDestination = MessageQueueIF::NO_QUEUE; + MessageQueueId_t lastPartner = MessageQueueIF::NO_QUEUE; + const size_t maxMessageSize; + //! Stores the current system context + CallContext callContext = CallContext::TASK; }; -#endif /* MESSAGEQUEUE_H_ */ +#endif /* FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_ */ diff --git a/osal/FreeRTOS/QueueFactory.cpp b/osal/FreeRTOS/QueueFactory.cpp index e639179a..5b3c73dc 100644 --- a/osal/FreeRTOS/QueueFactory.cpp +++ b/osal/FreeRTOS/QueueFactory.cpp @@ -1,18 +1,21 @@ +#include "../../ipc/MessageQueueSenderIF.h" #include "../../ipc/QueueFactory.h" -#include "MessageQueue.h" +#include "../../osal/FreeRTOS/MessageQueue.h" -QueueFactory* QueueFactory::factoryInstance = NULL; +QueueFactory* QueueFactory::factoryInstance = nullptr; ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom,bool ignoreFault) { - return MessageQueue::sendMessageFromMessageQueue(sendTo,message,sentFrom,ignoreFault); + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + return MessageQueue::sendMessageFromMessageQueue(sendTo,message, + sentFrom,ignoreFault); } QueueFactory* QueueFactory::instance() { - if (factoryInstance == NULL) { + if (factoryInstance == nullptr) { factoryInstance = new QueueFactory; } return factoryInstance; @@ -24,9 +27,9 @@ QueueFactory::QueueFactory() { QueueFactory::~QueueFactory() { } -MessageQueueIF* QueueFactory::createMessageQueue(uint32_t message_depth, +MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) { - return new MessageQueue(message_depth, maxMessageSize); + return new MessageQueue(messageDepth, maxMessageSize); } void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { From a0bc6b3c1fb3a5f8ef268b2b71d731786d51b3c2 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 26 Sep 2020 14:34:49 +0200 Subject: [PATCH 370/653] MQM IF update --- ipc/MessageQueueIF.h | 176 +++++++++++++++++++++++++++---------------- 1 file changed, 112 insertions(+), 64 deletions(-) diff --git a/ipc/MessageQueueIF.h b/ipc/MessageQueueIF.h index b0347db9..1c06521c 100644 --- a/ipc/MessageQueueIF.h +++ b/ipc/MessageQueueIF.h @@ -1,61 +1,77 @@ #ifndef FSFW_IPC_MESSAGEQUEUEIF_H_ #define FSFW_IPC_MESSAGEQUEUEIF_H_ -// COULDDO: We could support blocking calls - #include "messageQueueDefinitions.h" -#include "MessageQueueMessage.h" +#include "MessageQueueMessageIF.h" #include "../returnvalues/HasReturnvaluesIF.h" +#include + + +// COULDDO: We could support blocking calls +// semaphores are being implemented, which makes this idea even more iteresting. + +/** + * @defgroup message_queue Message Queue + * @brief Message Queue related software components + */ class MessageQueueIF { public: static const MessageQueueId_t NO_QUEUE = 0; static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF; - /** - * No new messages on the queue - */ + //! No new messages on the queue static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(1); - /** - * No space left for more messages - */ + //! No space left for more messages static const ReturnValue_t FULL = MAKE_RETURN_CODE(2); - /** - * Returned if a reply method was called without partner - */ + //! Returned if a reply method was called without partner static const ReturnValue_t NO_REPLY_PARTNER = MAKE_RETURN_CODE(3); + //! Returned if the target destination is invalid. + static constexpr ReturnValue_t DESTINVATION_INVALID = MAKE_RETURN_CODE(4); virtual ~MessageQueueIF() {} /** * @brief This operation sends a message to the last communication partner. - * @details This operation simplifies answering an incoming message by using the stored - * lastParnter information as destination. If there was no message received yet - * (i.e. lastPartner is zero), an error code is returned. - * @param message A pointer to a previously created message, which is sent. - * \return RETURN_OK if ok - * \return NO_REPLY_PARTNER Should return NO_REPLY_PARTNER if partner was found + * @details + * This operation simplifies answering an incoming message by using the + * stored lastParnter information as destination. If there was no message + * received yet (i.e. lastPartner is zero), an error code is returned. + * @param message + * A pointer to a previously created message, which is sent. + * @return + * -@c RETURN_OK if ok + * -@c NO_REPLY_PARTNER Should return NO_REPLY_PARTNER if partner was found. */ - virtual ReturnValue_t reply( MessageQueueMessage* message ) = 0; + virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0; /** - * @brief This function reads available messages from the message queue and returns the sender. - * @details It works identically to the other receiveMessage call, but in addition returns the - * sender's queue id. - * @param message A pointer to a message in which the received data is stored. - * @param receivedFrom A pointer to a queue id in which the sender's id is stored. + * @brief This function reads available messages from the message queue + * and returns the sender. + * @details + * It works identically to the other receiveMessage call, but in addition + * returns the sender's queue id. + * @param message + * A pointer to a message in which the received data is stored. + * @param receivedFrom + * A pointer to a queue id in which the sender's id is stored. */ - virtual ReturnValue_t receiveMessage(MessageQueueMessage* message, + virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message, MessageQueueId_t *receivedFrom) = 0; /** * @brief This function reads available messages from the message queue. - * @details If data is available it is stored in the passed message pointer. The message's - * original content is overwritten and the sendFrom information is stored in the - * lastPartner attribute. Else, the lastPartner information remains untouched, the - * message's content is cleared and the function returns immediately. - * @param message A pointer to a message in which the received data is stored. + * @details + * If data is available it is stored in the passed message pointer. + * The message's original content is overwritten and the sendFrom + * information is stored in theblastPartner attribute. Else, the lastPartner + * information remains untouched, the message's content is cleared and the + * function returns immediately. + * @param message + * A pointer to a message in which the received data is stored. + * @return -@c RETURN_OK on success + * -@c MessageQueueIF::EMPTY if queue is empty */ - virtual ReturnValue_t receiveMessage(MessageQueueMessage* message) = 0; + virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0; /** * Deletes all pending messages in the queue. * @param count The number of flushed messages. @@ -63,57 +79,89 @@ public: */ virtual ReturnValue_t flush(uint32_t* count) = 0; /** - * @brief This method returns the message queue id of the last communication partner. + * @brief This method returns the message queue + * id of the last communication partner. */ virtual MessageQueueId_t getLastPartner() const = 0; /** - * @brief This method returns the message queue id of this class's message queue. + * @brief This method returns the message queue + * id of this class's message queue. */ virtual MessageQueueId_t getId() const = 0; /** - * \brief With the sendMessage call, a queue message is sent to a receiving queue. - * \details This method takes the message provided, adds the sentFrom information and passes - * it on to the destination provided with an operating system call. The OS's return - * value is returned. - * \param sendTo This parameter specifies the message queue id to send the message to. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. - * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full (if implemented). + * @brief With the sendMessage call, a queue message + * is sent to a receiving queue. + * @details + * This method takes the message provided, adds the sentFrom information + * and passes it on to the destination provided with an operating system + * call. The OS's returnvalue is returned. + * @param sendTo + * This parameter specifies the message queue id to send the message to. + * @param message + * This is a pointer to a previously created message, which is sent. + * @param sentFrom + * The sentFrom information can be set to inject the sender's queue id + * into the message. This variable is set to zero by default. + * @param ignoreFault + * If set to true, the internal software fault counter is not incremented + * if queue is full (if implemented). + * @return -@c RETURN_OK on success + * -@c MessageQueueIF::FULL if queue is full */ - virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0; - /** - * @brief This operation sends a message to the given destination. - * @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes its - * queue id as "sentFrom" parameter. - * @param sendTo This parameter specifies the message queue id of the destination message queue. - * @param message A pointer to a previously created message, which is sent. - * @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. - */ - virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, MessageQueueMessage* message, bool ignoreFault = false ) = 0; + virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault = false ) = 0; /** - * \brief The sendToDefaultFrom method sends a queue message to the default destination. - * \details In all other aspects, it works identical to the sendMessage method. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. + * @brief This operation sends a message to the given destination. + * @details + * It directly uses the sendMessage call of the MessageQueueSender parent, + * but passes its queue id as "sentFrom" parameter. + * @param sendTo + * This parameter specifies the message queue id of the destination + * message queue. + * @param message + * A pointer to a previously created message, which is sent. + * @param ignoreFault + * If set to true, the internal software fault counter is not incremented + * if queue is full. */ - virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0; + virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, + MessageQueueMessageIF* message, bool ignoreFault = false ) = 0; + + /** + * @brief The sendToDefaultFrom method sends a queue message + * to the default destination. + * @details + * In all other aspects, it works identical to the sendMessage method. + * @param message + * This is a pointer to a previously created message, which is sent. + * @param sentFrom + * The sentFrom information can be set to inject the sender's queue id + * into the message. This variable is set to zero by default. + * @return -@c RETURN_OK on success + * -@c MessageQueueIF::FULL if queue is full + */ + virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message, + MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0; /** * @brief This operation sends a message to the default destination. - * @details As in the sendMessage method, this function uses the sendToDefault call of the - * Implementation class and adds its queue id as "sentFrom" information. + * @details + * As in the sendMessage method, this function uses the sendToDefault + * call of the Implementation class and adds its queue id as + * "sentFrom" information. * @param message A pointer to a previously created message, which is sent. + * @return -@c RETURN_OK on success + * -@c MessageQueueIF::FULL if queue is full */ - virtual ReturnValue_t sendToDefault( MessageQueueMessage* message ) = 0; + virtual ReturnValue_t sendToDefault( MessageQueueMessageIF* message ) = 0; /** - * \brief This method is a simple setter for the default destination. + * @brief This method is a simple setter for the default destination. */ virtual void setDefaultDestination(MessageQueueId_t defaultDestination) = 0; /** - * \brief This method is a simple getter for the default destination. + * @brief This method is a simple getter for the default destination. */ virtual MessageQueueId_t getDefaultDestination() const = 0; @@ -122,4 +170,4 @@ public: -#endif /* FRAMEWORK_IPC_MESSAGEQUEUEIF_H_ */ +#endif /* FSFW_IPC_MESSAGEQUEUEIF_H_ */ From bf5688c8d8399817d276b58ff22768c54d311df9 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 26 Sep 2020 14:36:56 +0200 Subject: [PATCH 371/653] last fixes --- ipc/MessageQueueSenderIF.h | 6 +++--- ipc/QueueFactory.h | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/ipc/MessageQueueSenderIF.h b/ipc/MessageQueueSenderIF.h index 7eea5146..683c2908 100644 --- a/ipc/MessageQueueSenderIF.h +++ b/ipc/MessageQueueSenderIF.h @@ -1,8 +1,8 @@ #ifndef FSFW_IPC_MESSAGEQUEUESENDERIF_H_ #define FSFW_IPC_MESSAGEQUEUESENDERIF_H_ -#include "../ipc/MessageQueueIF.h" -#include "../ipc/MessageQueueMessageIF.h" +#include "MessageQueueIF.h" +#include "MessageQueueMessageIF.h" #include "../objectmanager/ObjectManagerIF.h" class MessageQueueSenderIF { @@ -15,7 +15,7 @@ public: * Not sure whether this is actually a good idea. */ static ReturnValue_t sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom = MessageQueueIF::NO_QUEUE, bool ignoreFault = false); private: diff --git a/ipc/QueueFactory.h b/ipc/QueueFactory.h index 4f4d72c7..9853d256 100644 --- a/ipc/QueueFactory.h +++ b/ipc/QueueFactory.h @@ -1,8 +1,10 @@ -#ifndef FRAMEWORK_IPC_QUEUEFACTORY_H_ -#define FRAMEWORK_IPC_QUEUEFACTORY_H_ +#ifndef FSFW_IPC_QUEUEFACTORY_H_ +#define FSFW_IPC_QUEUEFACTORY_H_ #include "MessageQueueIF.h" -#include +#include "MessageQueueMessage.h" +#include + /** * Creates message queues. * This class is a "singleton" interface, i.e. it provides an @@ -30,4 +32,4 @@ private: static QueueFactory* factoryInstance; }; -#endif /* FRAMEWORK_IPC_QUEUEFACTORY_H_ */ +#endif /* FSFW_IPC_QUEUEFACTORY_H_ */ From 7b57f372bfa3347eb01d22d6e666446f468a3bb2 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 26 Sep 2020 14:51:00 +0200 Subject: [PATCH 372/653] starting convergence --- memory/AcceptsMemoryMessagesIF.h | 13 ++---- memory/MemoryHelper.cpp | 47 ++++++++++---------- memory/MemoryHelper.h | 42 +++++++++++------- memory/MemoryMessage.cpp | 13 +++--- memory/MemoryMessage.h | 43 ++++++++++-------- memory/MemoryProxyIF.h | 2 +- modes/HasModesIF.h | 16 +++---- modes/ModeHelper.cpp | 75 ++++++++++++++++++++------------ modes/ModeHelper.h | 10 +++-- modes/ModeMessage.cpp | 2 +- 10 files changed, 147 insertions(+), 116 deletions(-) diff --git a/memory/AcceptsMemoryMessagesIF.h b/memory/AcceptsMemoryMessagesIF.h index a1cbddf8..cf8aa5ec 100644 --- a/memory/AcceptsMemoryMessagesIF.h +++ b/memory/AcceptsMemoryMessagesIF.h @@ -1,12 +1,5 @@ -/** - * @file AcceptsMemoryMessagesIF.h - * @brief This file defines the AcceptsMemoryMessagesIF class. - * @date 11.07.2013 - * @author baetz - */ - -#ifndef ACCEPTSMEMORYMESSAGESIF_H_ -#define ACCEPTSMEMORYMESSAGESIF_H_ +#ifndef FSFW_MEMORY_ACCEPTSMEMORYMESSAGESIF_H_ +#define FSFW_MEMORY_ACCEPTSMEMORYMESSAGESIF_H_ #include "HasMemoryIF.h" #include "MemoryMessage.h" @@ -18,4 +11,4 @@ public: }; -#endif /* ACCEPTSMEMORYMESSAGESIF_H_ */ +#endif /* AFSFW_MEMORY_ACCEPTSMEMORYMESSAGESIF_H_ */ diff --git a/memory/MemoryHelper.cpp b/memory/MemoryHelper.cpp index 48a605be..6b11882f 100644 --- a/memory/MemoryHelper.cpp +++ b/memory/MemoryHelper.cpp @@ -1,14 +1,15 @@ -#include "../globalfunctions/CRC.h" #include "MemoryHelper.h" #include "MemoryMessage.h" + +#include "../globalfunctions/CRC.h" #include "../objectmanager/ObjectManagerIF.h" #include "../serialize/EndianConverter.h" #include "../serviceinterface/ServiceInterfaceStream.h" -MemoryHelper::MemoryHelper(HasMemoryIF* workOnThis, MessageQueueIF* useThisQueue) : - workOnThis(workOnThis), queueToUse(useThisQueue), ipcStore(NULL), ipcAddress(), lastCommand( - CommandMessage::CMD_NONE), lastSender(0), reservedSpaceInIPC( - NULL), busy(false) { +MemoryHelper::MemoryHelper(HasMemoryIF* workOnThis, + MessageQueueIF* useThisQueue): + workOnThis(workOnThis), queueToUse(useThisQueue), ipcAddress(), + lastCommand(CommandMessage::CMD_NONE), busy(false) { } ReturnValue_t MemoryHelper::handleMemoryCommand(CommandMessage* message) { @@ -33,17 +34,8 @@ ReturnValue_t MemoryHelper::handleMemoryCommand(CommandMessage* message) { } } -ReturnValue_t MemoryHelper::initialize() { - ipcStore = objectManager->get(objects::IPC_STORE); - if (ipcStore != NULL) { - return RETURN_OK; - } else { - return RETURN_FAILED; - } -} - void MemoryHelper::completeLoad(ReturnValue_t errorCode, - const uint8_t* dataToCopy, const uint32_t size, uint8_t* copyHere) { + const uint8_t* dataToCopy, const size_t size, uint8_t* copyHere) { busy = false; switch (errorCode) { case HasMemoryIF::DO_IT_MYSELF: @@ -67,13 +59,13 @@ void MemoryHelper::completeLoad(ReturnValue_t errorCode, return; } //Only reached on success - CommandMessage reply(CommandMessage::REPLY_COMMAND_OK, 0, 0); + CommandMessage reply( CommandMessage::REPLY_COMMAND_OK, 0, 0); queueToUse->sendMessage(lastSender, &reply); ipcStore->deleteData(ipcAddress); } void MemoryHelper::completeDump(ReturnValue_t errorCode, - const uint8_t* dataToCopy, const uint32_t size) { + const uint8_t* dataToCopy, const size_t size) { busy = false; CommandMessage reply; MemoryMessage::setMemoryReplyFailed(&reply, errorCode, lastCommand); @@ -125,12 +117,12 @@ void MemoryHelper::completeDump(ReturnValue_t errorCode, break; } if (queueToUse->sendMessage(lastSender, &reply) != RETURN_OK) { - reply.clearCommandMessage(); + reply.clear(); } } void MemoryHelper::swapMatrixCopy(uint8_t* out, const uint8_t *in, - uint32_t totalSize, uint8_t datatypeSize) { + size_t totalSize, uint8_t datatypeSize) { if (totalSize % datatypeSize != 0){ return; } @@ -185,11 +177,18 @@ void MemoryHelper::handleMemoryCheckOrDump(CommandMessage* message) { } ReturnValue_t MemoryHelper::initialize(MessageQueueIF* queueToUse_) { - if(queueToUse_!=NULL){ - this->queueToUse = queueToUse_; - }else{ - return MessageQueueIF::NO_QUEUE; + if(queueToUse_ == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; } - + this->queueToUse = queueToUse_; return initialize(); } + +ReturnValue_t MemoryHelper::initialize() { + ipcStore = objectManager->get(objects::IPC_STORE); + if (ipcStore != nullptr) { + return RETURN_OK; + } else { + return RETURN_FAILED; + } +} diff --git a/memory/MemoryHelper.h b/memory/MemoryHelper.h index 5e1a99b6..a651861c 100644 --- a/memory/MemoryHelper.h +++ b/memory/MemoryHelper.h @@ -1,11 +1,16 @@ -#ifndef MEMORYHELPER_H_ -#define MEMORYHELPER_H_ -#include "../ipc/CommandMessage.h" +#ifndef FSFW_MEMORY_MEMORYHELPER_H_ +#define FSFW_MEMORY_MEMORYHELPER_H_ + #include "AcceptsMemoryMessagesIF.h" + +#include "../ipc/CommandMessage.h" #include "../returnvalues/HasReturnvaluesIF.h" #include "../storagemanager/StorageManagerIF.h" #include "../ipc/MessageQueueIF.h" +/** + * @brief TODO: documentation. + */ class MemoryHelper : public HasReturnvaluesIF { public: static const uint8_t INTERFACE_ID = CLASS_ID::MEMORY_HELPER; @@ -13,25 +18,32 @@ public: static const ReturnValue_t INVALID_ADDRESS = MAKE_RETURN_CODE(0xE1); static const ReturnValue_t INVALID_SIZE = MAKE_RETURN_CODE(0xE2); static const ReturnValue_t STATE_MISMATCH = MAKE_RETURN_CODE(0xE3); + + MemoryHelper(HasMemoryIF* workOnThis, MessageQueueIF* useThisQueue); + ~MemoryHelper(); + + ReturnValue_t handleMemoryCommand(CommandMessage* message); + void completeLoad(ReturnValue_t errorCode, + const uint8_t* dataToCopy = nullptr, const size_t size = 0, + uint8_t* copyHere = nullptr); + void completeDump(ReturnValue_t errorCode, + const uint8_t* dataToCopy = nullptr, const size_t size = 0); + void swapMatrixCopy(uint8_t *out, const uint8_t *in, size_t totalSize, + uint8_t datatypeSize); + ReturnValue_t initialize(MessageQueueIF* queueToUse_); + private: HasMemoryIF* workOnThis; MessageQueueIF* queueToUse; - StorageManagerIF* ipcStore; + StorageManagerIF* ipcStore = nullptr; store_address_t ipcAddress; Command_t lastCommand; - MessageQueueId_t lastSender; - uint8_t* reservedSpaceInIPC; + MessageQueueId_t lastSender = MessageQueueIF::NO_QUEUE; + uint8_t* reservedSpaceInIPC = nullptr; bool busy; void handleMemoryLoad(CommandMessage* message); void handleMemoryCheckOrDump(CommandMessage* message); ReturnValue_t initialize(); -public: - ReturnValue_t handleMemoryCommand(CommandMessage* message); - void completeLoad( ReturnValue_t errorCode, const uint8_t* dataToCopy = NULL, const uint32_t size = 0, uint8_t* copyHere = NULL ); - void completeDump( ReturnValue_t errorCode, const uint8_t* dataToCopy = NULL, const uint32_t size = 0); - void swapMatrixCopy( uint8_t *out, const uint8_t *in, uint32_t totalSize, uint8_t datatypeSize); - ReturnValue_t initialize(MessageQueueIF* queueToUse_); - MemoryHelper( HasMemoryIF* workOnThis, MessageQueueIF* useThisQueue ); - ~MemoryHelper(); + }; -#endif /* MEMORYHELPER_H_ */ +#endif /* FSFW_MEMORY_MEMORYHELPER_H_ */ diff --git a/memory/MemoryMessage.cpp b/memory/MemoryMessage.cpp index 741565fc..e1db004a 100644 --- a/memory/MemoryMessage.cpp +++ b/memory/MemoryMessage.cpp @@ -1,7 +1,6 @@ #include "MemoryMessage.h" + #include "../objectmanager/ObjectManagerIF.h" -MemoryMessage::MemoryMessage() { -} uint32_t MemoryMessage::getAddress(const CommandMessage* message) { return message->getParameter(); @@ -17,26 +16,24 @@ uint32_t MemoryMessage::getLength(const CommandMessage* message) { return message->getParameter2(); } -ReturnValue_t MemoryMessage::setMemoryDumpCommand(CommandMessage* message, +void MemoryMessage::setMemoryDumpCommand(CommandMessage* message, uint32_t address, uint32_t length) { message->setCommand(CMD_MEMORY_DUMP); message->setParameter( address ); message->setParameter2( length ); - return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t MemoryMessage::setMemoryDumpReply(CommandMessage* message, store_address_t storageID) { +void MemoryMessage::setMemoryDumpReply(CommandMessage* message, + store_address_t storageID) { message->setCommand(REPLY_MEMORY_DUMP); message->setParameter2( storageID.raw ); - return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t MemoryMessage::setMemoryLoadCommand(CommandMessage* message, +void MemoryMessage::setMemoryLoadCommand(CommandMessage* message, uint32_t address, store_address_t storageID) { message->setCommand(CMD_MEMORY_LOAD); message->setParameter( address ); message->setParameter2( storageID.raw ); - return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t MemoryMessage::getErrorCode(const CommandMessage* message) { diff --git a/memory/MemoryMessage.h b/memory/MemoryMessage.h index a4c2de63..207e539f 100644 --- a/memory/MemoryMessage.h +++ b/memory/MemoryMessage.h @@ -1,14 +1,15 @@ -#ifndef MEMORYMESSAGE_H_ -#define MEMORYMESSAGE_H_ +#ifndef FSFW_MEMORY_MEMORYMESSAGE_H_ +#define FSFW_MEMORY_MEMORYMESSAGE_H_ #include "../ipc/CommandMessage.h" #include "../storagemanager/StorageManagerIF.h" class MemoryMessage { -private: - MemoryMessage(); //A private ctor inhibits instantiation public: + // Instantiation forbidden. + MemoryMessage() = delete; + static const uint8_t MESSAGE_ID = messagetypes::MEMORY; static const Command_t CMD_MEMORY_LOAD = MAKE_COMMAND_ID( 0x01 ); static const Command_t CMD_MEMORY_DUMP = MAKE_COMMAND_ID( 0x02 ); @@ -19,21 +20,29 @@ public: static const Command_t END_OF_MEMORY_COPY = MAKE_COMMAND_ID(0xF0); static uint32_t getAddress( const CommandMessage* message ); - static store_address_t getStoreID( const CommandMessage* message ); + static store_address_t getStoreID(const CommandMessage* message); static uint32_t getLength( const CommandMessage* message ); - static ReturnValue_t getErrorCode( const CommandMessage* message ); - static ReturnValue_t setMemoryDumpCommand( CommandMessage* message, uint32_t address, uint32_t length ); - static ReturnValue_t setMemoryDumpReply( CommandMessage* message, store_address_t storageID ); - static ReturnValue_t setMemoryLoadCommand( CommandMessage* message, uint32_t address, store_address_t storageID ); - static ReturnValue_t setMemoryCheckCommand( CommandMessage* message, uint32_t address, uint32_t length ); - static ReturnValue_t setMemoryCheckReply( CommandMessage* message, uint16_t crc ); - static ReturnValue_t setMemoryReplyFailed( CommandMessage* message, ReturnValue_t errorCode, Command_t initialCommand ); - static ReturnValue_t setMemoryCopyEnd( CommandMessage* message); + static ReturnValue_t getErrorCode(const CommandMessage* message); + static uint16_t getCrc(const CommandMessage* message ); + static ReturnValue_t getCrcReturnValue(const CommandMessage* message); + static Command_t getInitialCommand(const CommandMessage* message); + + static void setMemoryDumpCommand(CommandMessage* message, + uint32_t address, uint32_t length ); + static void setMemoryDumpReply(CommandMessage* message, + store_address_t storageID); + static void setMemoryLoadCommand(CommandMessage* message, + uint32_t address, store_address_t storageID ); + static ReturnValue_t setMemoryCheckCommand(CommandMessage* message, + uint32_t address, uint32_t length); + static ReturnValue_t setMemoryCheckReply(CommandMessage* message, + uint16_t crc); + static ReturnValue_t setMemoryReplyFailed(CommandMessage* message, + ReturnValue_t errorCode, Command_t initialCommand); + static ReturnValue_t setMemoryCopyEnd(CommandMessage* message); static void setCrcReturnValue(CommandMessage*, ReturnValue_t returnValue); - static uint16_t getCrc( const CommandMessage* message ); - static ReturnValue_t getCrcReturnValue(const CommandMessage* message); - static Command_t getInitialCommand( const CommandMessage* message ); + static void clear(CommandMessage* message); }; -#endif /* MEMORYMESSAGE_H_ */ +#endif /* FSFW_MEMORY_MEMORYMESSAGE_H_ */ diff --git a/memory/MemoryProxyIF.h b/memory/MemoryProxyIF.h index 1494d523..31045d3f 100644 --- a/memory/MemoryProxyIF.h +++ b/memory/MemoryProxyIF.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_MEMORY_MEMORYPROXYIF_H_ #define FRAMEWORK_MEMORY_MEMORYPROXYIF_H_ -#include "AcceptsMemoryMessagesIF.h" +#include "../memory/AcceptsMemoryMessagesIF.h" /** * This was a nice idea to transparently forward incoming messages to another object. diff --git a/modes/HasModesIF.h b/modes/HasModesIF.h index 4381046c..39a50c2a 100644 --- a/modes/HasModesIF.h +++ b/modes/HasModesIF.h @@ -9,8 +9,8 @@ #define HASMODESIF_H_ #include "../events/Event.h" -#include "ModeHelper.h" -#include "ModeMessage.h" +#include "../modes/ModeHelper.h" +#include "../modes/ModeMessage.h" #include "../returnvalues/HasReturnvaluesIF.h" #include @@ -46,12 +46,12 @@ protected: uint32_t *msToReachTheMode) { return HasReturnvaluesIF::RETURN_FAILED; } - virtual void startTransition(Mode_t mode, Submode_t submode) { - } - virtual void setToExternalControl() { - } - virtual void announceMode(bool recursive) { - } + + virtual void startTransition(Mode_t mode, Submode_t submode) {} + + virtual void setToExternalControl() {} + + virtual void announceMode(bool recursive) {} }; #endif /* HASMODESIF_H_ */ diff --git a/modes/ModeHelper.cpp b/modes/ModeHelper.cpp index cb62c468..68f009e7 100644 --- a/modes/ModeHelper.cpp +++ b/modes/ModeHelper.cpp @@ -1,48 +1,47 @@ -#include "HasModesIF.h" -#include "ModeHelper.h" #include "../ipc/MessageQueueSenderIF.h" +#include "../modes/HasModesIF.h" +#include "../modes/ModeHelper.h" +#include "../serviceinterface/ServiceInterfaceStream.h" ModeHelper::ModeHelper(HasModesIF *owner) : - theOneWhoCommandedAMode(0), commandedMode(HasModesIF::MODE_OFF), commandedSubmode( - HasModesIF::SUBMODE_NONE), owner(owner), parentQueueId(0), forced( - false) { -} + commandedMode(HasModesIF::MODE_OFF), + commandedSubmode(HasModesIF::SUBMODE_NONE), + owner(owner), forced(false) {} ModeHelper::~ModeHelper() { } -ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* message) { +ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* command) { CommandMessage reply; Mode_t mode; Submode_t submode; - switch (message->getCommand()) { + switch (command->getCommand()) { case ModeMessage::CMD_MODE_COMMAND_FORCED: forced = true; /* NO BREAK falls through*/ case ModeMessage::CMD_MODE_COMMAND: { - mode = ModeMessage::getMode(message); - submode = ModeMessage::getSubmode(message); + mode = ModeMessage::getMode(command); + submode = ModeMessage::getSubmode(command); uint32_t timeout; ReturnValue_t result = owner->checkModeCommand(mode, submode, &timeout); if (result != HasReturnvaluesIF::RETURN_OK) { ModeMessage::cantReachMode(&reply, result); - MessageQueueSenderIF::sendMessage(message->getSender(), &reply, - owner->getCommandQueue()); + MessageQueueSenderIF::sendMessage(command->getSender(), &reply, + owner->getCommandQueue()); break; } //Free to start transition - theOneWhoCommandedAMode = message->getSender(); + theOneWhoCommandedAMode = command->getSender(); commandedMode = mode; commandedSubmode = submode; - if ((parentQueueId != MessageQueueSenderIF::NO_QUEUE) + if ((parentQueueId != MessageQueueIF::NO_QUEUE) && (theOneWhoCommandedAMode != parentQueueId)) { owner->setToExternalControl(); } countdown.setTimeout(timeout); - owner->startTransition(mode, submode); } break; @@ -50,8 +49,8 @@ ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* message) { owner->getMode(&mode, &submode); ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_REPLY, mode, submode); - MessageQueueSenderIF::sendMessage(message->getSender(), &reply, - owner->getCommandQueue()); + MessageQueueSenderIF::sendMessage(command->getSender(), &reply, + owner->getCommandQueue()); } break; case ModeMessage::CMD_MODE_ANNOUNCE: @@ -71,27 +70,45 @@ ReturnValue_t ModeHelper::initialize(MessageQueueId_t parentQueueId) { return initialize(); } -void ModeHelper::modeChanged(Mode_t mode, Submode_t submode) { +void ModeHelper::modeChanged(Mode_t ownerMode, Submode_t ownerSubmode) { forced = false; + sendModeReplyMessage(ownerMode, ownerSubmode); + sendModeInfoMessage(ownerMode, ownerSubmode); + theOneWhoCommandedAMode = MessageQueueIF::NO_QUEUE; +} + +void ModeHelper::sendModeReplyMessage(Mode_t ownerMode, + Submode_t ownerSubmode) { CommandMessage reply; - if (theOneWhoCommandedAMode != MessageQueueSenderIF::NO_QUEUE) { - if ((mode != commandedMode) || (submode != commandedSubmode)) { + if (theOneWhoCommandedAMode != MessageQueueIF::NO_QUEUE) + { + if (ownerMode != commandedMode or ownerSubmode != commandedSubmode) + { ModeMessage::setModeMessage(&reply, - ModeMessage::REPLY_WRONG_MODE_REPLY, mode, submode); - } else { + ModeMessage::REPLY_WRONG_MODE_REPLY, ownerMode, + ownerSubmode); + } + else + { ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_REPLY, - mode, submode); + ownerMode, ownerSubmode); } MessageQueueSenderIF::sendMessage(theOneWhoCommandedAMode, &reply, - owner->getCommandQueue()); + owner->getCommandQueue()); } +} + +void ModeHelper::sendModeInfoMessage(Mode_t ownerMode, + Submode_t ownerSubmode) { + CommandMessage reply; if (theOneWhoCommandedAMode != parentQueueId - && parentQueueId != MessageQueueSenderIF::NO_QUEUE) { - ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_INFO, mode, - submode); - MessageQueueSenderIF::sendMessage(parentQueueId, &reply, owner->getCommandQueue()); + and parentQueueId != MessageQueueIF::NO_QUEUE) + { + ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_INFO, + ownerMode, ownerSubmode); + MessageQueueSenderIF::sendMessage(parentQueueId, &reply, + owner->getCommandQueue()); } - theOneWhoCommandedAMode = MessageQueueSenderIF::NO_QUEUE; } void ModeHelper::startTimer(uint32_t timeoutMs) { diff --git a/modes/ModeHelper.h b/modes/ModeHelper.h index 542fe780..02cf5799 100644 --- a/modes/ModeHelper.h +++ b/modes/ModeHelper.h @@ -1,7 +1,8 @@ #ifndef MODEHELPER_H_ #define MODEHELPER_H_ -#include "ModeMessage.h" +#include "../ipc/MessageQueueIF.h" +#include "../modes/ModeMessage.h" #include "../returnvalues/HasReturnvaluesIF.h" #include "../timemanager/Countdown.h" @@ -9,7 +10,7 @@ class HasModesIF; class ModeHelper { public: - MessageQueueId_t theOneWhoCommandedAMode; + MessageQueueId_t theOneWhoCommandedAMode = MessageQueueIF::NO_QUEUE; Mode_t commandedMode; Submode_t commandedSubmode; @@ -39,11 +40,14 @@ public: void setForced(bool forced); protected: HasModesIF *owner; - MessageQueueId_t parentQueueId; + MessageQueueId_t parentQueueId = MessageQueueIF::NO_QUEUE; Countdown countdown; bool forced; +private: + void sendModeReplyMessage(Mode_t ownerMode, Submode_t ownerSubmode); + void sendModeInfoMessage(Mode_t ownerMode, Submode_t ownerSubmode); }; #endif /* MODEHELPER_H_ */ diff --git a/modes/ModeMessage.cpp b/modes/ModeMessage.cpp index 14dbbb31..7ad7d06f 100644 --- a/modes/ModeMessage.cpp +++ b/modes/ModeMessage.cpp @@ -1,4 +1,4 @@ -#include "ModeMessage.h" +#include "../modes/ModeMessage.h" Mode_t ModeMessage::getMode(const CommandMessage* message) { return message->getParameter(); From 9d4c2b90f375ed5b5940b33a6087067294388179 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 26 Sep 2020 14:54:23 +0200 Subject: [PATCH 373/653] removed proxy/ not used&working? --- memory/MemoryMessage.cpp | 15 ++++++--------- memory/MemoryMessage.h | 8 ++++---- memory/MemoryProxyIF.h | 22 ---------------------- 3 files changed, 10 insertions(+), 35 deletions(-) delete mode 100644 memory/MemoryProxyIF.h diff --git a/memory/MemoryMessage.cpp b/memory/MemoryMessage.cpp index e1db004a..94fa4691 100644 --- a/memory/MemoryMessage.cpp +++ b/memory/MemoryMessage.cpp @@ -62,22 +62,21 @@ void MemoryMessage::clear(CommandMessage* message) { } } -ReturnValue_t MemoryMessage::setMemoryCheckCommand(CommandMessage* message, +void MemoryMessage::setMemoryCheckCommand(CommandMessage* message, uint32_t address, uint32_t length) { message->setCommand(CMD_MEMORY_CHECK); message->setParameter( address ); message->setParameter2( length ); - return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t MemoryMessage::setMemoryCheckReply(CommandMessage* message, +void MemoryMessage::setMemoryCheckReply(CommandMessage* message, uint16_t crc) { message->setCommand(REPLY_MEMORY_CHECK); message->setParameter( crc ); - return HasReturnvaluesIF::RETURN_OK; } -void MemoryMessage::setCrcReturnValue(CommandMessage* message, ReturnValue_t returnValue){ +void MemoryMessage::setCrcReturnValue(CommandMessage* message, + ReturnValue_t returnValue){ message->setParameter(returnValue<<16); }; @@ -93,18 +92,16 @@ Command_t MemoryMessage::getInitialCommand(const CommandMessage* message) { return message->getParameter2(); } -ReturnValue_t MemoryMessage::setMemoryReplyFailed(CommandMessage* message, +void MemoryMessage::setMemoryReplyFailed(CommandMessage* message, ReturnValue_t errorCode, Command_t initialCommand) { message->setCommand(REPLY_MEMORY_FAILED); message->setParameter(errorCode); message->setParameter2(initialCommand); - return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t MemoryMessage::setMemoryCopyEnd(CommandMessage* message) { +void MemoryMessage::setMemoryCopyEnd(CommandMessage* message) { message->setCommand(END_OF_MEMORY_COPY); message->setParameter(0); message->setParameter2(0); - return HasReturnvaluesIF::RETURN_OK; } diff --git a/memory/MemoryMessage.h b/memory/MemoryMessage.h index 207e539f..05b9926d 100644 --- a/memory/MemoryMessage.h +++ b/memory/MemoryMessage.h @@ -33,13 +33,13 @@ public: store_address_t storageID); static void setMemoryLoadCommand(CommandMessage* message, uint32_t address, store_address_t storageID ); - static ReturnValue_t setMemoryCheckCommand(CommandMessage* message, + static void setMemoryCheckCommand(CommandMessage* message, uint32_t address, uint32_t length); - static ReturnValue_t setMemoryCheckReply(CommandMessage* message, + static void setMemoryCheckReply(CommandMessage* message, uint16_t crc); - static ReturnValue_t setMemoryReplyFailed(CommandMessage* message, + static void setMemoryReplyFailed(CommandMessage* message, ReturnValue_t errorCode, Command_t initialCommand); - static ReturnValue_t setMemoryCopyEnd(CommandMessage* message); + static void setMemoryCopyEnd(CommandMessage* message); static void setCrcReturnValue(CommandMessage*, ReturnValue_t returnValue); static void clear(CommandMessage* message); diff --git a/memory/MemoryProxyIF.h b/memory/MemoryProxyIF.h deleted file mode 100644 index 31045d3f..00000000 --- a/memory/MemoryProxyIF.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef FRAMEWORK_MEMORY_MEMORYPROXYIF_H_ -#define FRAMEWORK_MEMORY_MEMORYPROXYIF_H_ - -#include "../memory/AcceptsMemoryMessagesIF.h" - -/** - * This was a nice idea to transparently forward incoming messages to another object. - * But it doesn't work like that. - */ -class MemoryProxyIF : public AcceptsMemoryMessagesIF { -public: - virtual MessageQueueId_t getProxyQueue() const = 0; - MessageQueueId_t getCommandQueue() const { - return getProxyQueue(); - } - virtual ~MemoryProxyIF() {} - -}; - - - -#endif /* FRAMEWORK_MEMORY_MEMORYPROXYIF_H_ */ From 6d2266f7d0c9b4c8e219e00afebb6bff41b16d9f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 26 Sep 2020 14:58:53 +0200 Subject: [PATCH 374/653] equalization complete --- modes/HasModesIF.h | 24 +++++++++--------------- modes/ModeHelper.cpp | 7 ++++--- modes/ModeHelper.h | 14 +++++++------- modes/ModeMessage.cpp | 10 +++++----- modes/ModeMessage.h | 20 +++++++------------- 5 files changed, 32 insertions(+), 43 deletions(-) diff --git a/modes/HasModesIF.h b/modes/HasModesIF.h index 39a50c2a..34a15937 100644 --- a/modes/HasModesIF.h +++ b/modes/HasModesIF.h @@ -1,18 +1,11 @@ -/** - * @file HasModesIF.h - * @brief This file defines the HasModesIF class. - * @date 20.06.2013 - * @author baetz - */ - -#ifndef HASMODESIF_H_ -#define HASMODESIF_H_ +#ifndef FSFW_MODES_HASMODESIF_H_ +#define FSFW_MODES_HASMODESIF_H_ +#include "ModeHelper.h" +#include "ModeMessage.h" #include "../events/Event.h" -#include "../modes/ModeHelper.h" -#include "../modes/ModeMessage.h" #include "../returnvalues/HasReturnvaluesIF.h" -#include +#include class HasModesIF { @@ -37,10 +30,11 @@ public: static const Mode_t MODE_ON = 1; //!< 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 static const Mode_t MODE_OFF = 0; //!< The device is powered off. The only command accepted in this mode is a mode change to on. static const Submode_t SUBMODE_NONE = 0; //!< To avoid checks against magic number "0". - virtual ~HasModesIF() { - } + + virtual ~HasModesIF() {} virtual MessageQueueId_t getCommandQueue() const = 0; virtual void getMode(Mode_t *mode, Submode_t *submode) = 0; + protected: virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode) { @@ -54,4 +48,4 @@ protected: virtual void announceMode(bool recursive) {} }; -#endif /* HASMODESIF_H_ */ +#endif /*FSFW_MODES_HASMODESIF_H_ */ diff --git a/modes/ModeHelper.cpp b/modes/ModeHelper.cpp index 68f009e7..6be4f776 100644 --- a/modes/ModeHelper.cpp +++ b/modes/ModeHelper.cpp @@ -1,6 +1,7 @@ +#include "HasModesIF.h" +#include "ModeHelper.h" + #include "../ipc/MessageQueueSenderIF.h" -#include "../modes/HasModesIF.h" -#include "../modes/ModeHelper.h" #include "../serviceinterface/ServiceInterfaceStream.h" ModeHelper::ModeHelper(HasModesIF *owner) : @@ -26,7 +27,7 @@ ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* command) { uint32_t timeout; ReturnValue_t result = owner->checkModeCommand(mode, submode, &timeout); if (result != HasReturnvaluesIF::RETURN_OK) { - ModeMessage::cantReachMode(&reply, result); + ModeMessage::setCantReachMode(&reply, result); MessageQueueSenderIF::sendMessage(command->getSender(), &reply, owner->getCommandQueue()); break; diff --git a/modes/ModeHelper.h b/modes/ModeHelper.h index 02cf5799..c2f089ec 100644 --- a/modes/ModeHelper.h +++ b/modes/ModeHelper.h @@ -1,8 +1,8 @@ -#ifndef MODEHELPER_H_ -#define MODEHELPER_H_ +#ifndef FSFW_MODES_MODEHELPER_H_ +#define FSFW_MODES_MODEHELPER_H_ +#include "ModeMessage.h" #include "../ipc/MessageQueueIF.h" -#include "../modes/ModeMessage.h" #include "../returnvalues/HasReturnvaluesIF.h" #include "../timemanager/Countdown.h" @@ -20,14 +20,14 @@ public: ReturnValue_t handleModeCommand(CommandMessage *message); /** - * - * @param parentQueue the Queue id of the parent object. Set to 0 if no parent present + * @param parentQueue the Queue id of the parent object. + * Set to 0 if no parent present */ void setParentQueue(MessageQueueId_t parentQueueId); ReturnValue_t initialize(MessageQueueId_t parentQueueId); - ReturnValue_t initialize(void); //void is there to stop eclipse CODAN from falsely reporting an error + ReturnValue_t initialize(void); void modeChanged(Mode_t mode, Submode_t submode); @@ -50,4 +50,4 @@ private: void sendModeInfoMessage(Mode_t ownerMode, Submode_t ownerSubmode); }; -#endif /* MODEHELPER_H_ */ +#endif /* FSFW_MODES_MODEHELPER_H_ */ diff --git a/modes/ModeMessage.cpp b/modes/ModeMessage.cpp index 7ad7d06f..b33bba60 100644 --- a/modes/ModeMessage.cpp +++ b/modes/ModeMessage.cpp @@ -1,4 +1,4 @@ -#include "../modes/ModeMessage.h" +#include "ModeMessage.h" Mode_t ModeMessage::getMode(const CommandMessage* message) { return message->getParameter(); @@ -8,12 +8,11 @@ Submode_t ModeMessage::getSubmode(const CommandMessage* message) { return message->getParameter2(); } -ReturnValue_t ModeMessage::setModeMessage(CommandMessage* message, Command_t command, - Mode_t mode, Submode_t submode) { +void ModeMessage::setModeMessage(CommandMessage* message, + Command_t command, Mode_t mode, Submode_t submode) { message->setCommand( command ); message->setParameter( mode ); message->setParameter2( submode ); - return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t ModeMessage::getCantReachModeReason(const CommandMessage* message) { @@ -24,7 +23,8 @@ void ModeMessage::clear(CommandMessage* message) { message->setCommand(CommandMessage::CMD_NONE); } -void ModeMessage::cantReachMode(CommandMessage* message, ReturnValue_t reason) { +void ModeMessage::setCantReachMode(CommandMessage* message, + ReturnValue_t reason) { message->setCommand(REPLY_CANT_REACH_MODE); message->setParameter(reason); message->setParameter2(0); diff --git a/modes/ModeMessage.h b/modes/ModeMessage.h index 925f3fc1..856996cf 100644 --- a/modes/ModeMessage.h +++ b/modes/ModeMessage.h @@ -1,12 +1,5 @@ -/** - * @file ModeMessage.h - * @brief This file defines the ModeMessage class. - * @date 17.07.2013 - * @author baetz - */ - -#ifndef MODEMESSAGE_H_ -#define MODEMESSAGE_H_ +#ifndef FSFW_MODES_MODEMESSAGE_H_ +#define FSFW_MODES_MODEMESSAGE_H_ #include "../ipc/CommandMessage.h" @@ -30,11 +23,12 @@ public: static Mode_t getMode(const CommandMessage* message); static Submode_t getSubmode(const CommandMessage* message); - static ReturnValue_t setModeMessage(CommandMessage* message, + static ReturnValue_t getCantReachModeReason(const CommandMessage* message); + + static void setModeMessage(CommandMessage* message, Command_t command, Mode_t mode, Submode_t submode); - static void cantReachMode(CommandMessage* message, ReturnValue_t reason); - static ReturnValue_t getCantReachModeReason(const CommandMessage* message); + static void setCantReachMode(CommandMessage* message, ReturnValue_t reason); static void clear(CommandMessage* message); }; -#endif /* MODEMESSAGE_H_ */ +#endif /* FSFW_MODES_MODEMESSAGE_H_ */ From 183b6a419338dbc2680526ab02314b62b1f3fa1d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 13:34:27 +0200 Subject: [PATCH 375/653] small bugfix --- objectmanager/frameworkObjects.h | 14 ++--- tmtcservices/VerificationReporter.cpp | 77 +++++++++++++++------------ tmtcservices/VerificationReporter.h | 41 ++++++++++---- 3 files changed, 81 insertions(+), 51 deletions(-) diff --git a/objectmanager/frameworkObjects.h b/objectmanager/frameworkObjects.h index 87439c88..4d08f084 100644 --- a/objectmanager/frameworkObjects.h +++ b/objectmanager/frameworkObjects.h @@ -4,13 +4,13 @@ namespace objects { enum framework_objects { // Default verification reporter. - PUS_SERVICE_1 = 0x53000001, - PUS_SERVICE_2 = 0x53000002, - PUS_SERVICE_5 = 0x53000005, - PUS_SERVICE_8 = 0x53000008, - PUS_SERVICE_9 = 0x53000009, - PUS_SERVICE_17 = 0x53000017, - PUS_SERVICE_200 = 0x53000200, + PUS_SERVICE_1_VERIFICATION = 0x53000001, + PUS_SERVICE_2_DEVICE_ACCESS = 0x53000002, + PUS_SERVICE_5_EVENT_REPORTING = 0x53000005, + PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008, + PUS_SERVICE_9_TIME_MGMT = 0x53000009, + PUS_SERVICE_17_TEST = 0x53000017, + PUS_SERVICE_200_MODE_MGMT = 0x53000200, //Generic IDs for IPC, modes, health, events HEALTH_TABLE = 0x53010000, diff --git a/tmtcservices/VerificationReporter.cpp b/tmtcservices/VerificationReporter.cpp index 43e712a2..7e40bd27 100644 --- a/tmtcservices/VerificationReporter.cpp +++ b/tmtcservices/VerificationReporter.cpp @@ -1,55 +1,59 @@ -#include "../serviceinterface/ServiceInterfaceStream.h" +#include "VerificationReporter.h" #include "AcceptsVerifyMessageIF.h" #include "PusVerificationReport.h" -#include "VerificationReporter.h" -object_id_t VerificationReporter::messageReceiver = 0; +#include "../ipc/MessageQueueIF.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../objectmanager/frameworkObjects.h" + +object_id_t VerificationReporter::messageReceiver = + objects::PUS_SERVICE_1_VERIFICATION; VerificationReporter::VerificationReporter() : - acknowledgeQueue() { + acknowledgeQueue(MessageQueueIF::NO_QUEUE) { } -VerificationReporter::~VerificationReporter() { - //Default, empty -} +VerificationReporter::~VerificationReporter() {} void VerificationReporter::sendSuccessReport(uint8_t set_report_id, TcPacketBase* current_packet, uint8_t set_step) { - if (this->acknowledgeQueue == 0) { + if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) { this->initialize(); } PusVerificationMessage message(set_report_id, current_packet->getAcknowledgeFlags(), current_packet->getPacketId(), current_packet->getPacketSequenceControl(), 0, set_step); - ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message); + ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, + &message); if (status != HasReturnvaluesIF::RETURN_OK) { - sif::error - << "VerificationReporter::sendSuccessReport: Error writing to queue. Code: " - << (uint16_t) status << std::endl; + sif::error << "VerificationReporter::sendSuccessReport: Error writing " + << "to queue. Code: " << std::hex << status << std::dec + << std::endl; } } void VerificationReporter::sendSuccessReport(uint8_t set_report_id, uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, uint8_t set_step) { - if (this->acknowledgeQueue == 0) { + if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) { this->initialize(); } PusVerificationMessage message(set_report_id, ackFlags, tcPacketId, tcSequenceControl, 0, set_step); - ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message); + ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, + &message); if (status != HasReturnvaluesIF::RETURN_OK) { - sif::error - << "VerificationReporter::sendSuccessReport: Error writing to queue. Code: " - << (uint16_t) status << std::endl; + sif::error << "VerificationReporter::sendSuccessReport: Error writing " + << "to queue. Code: " << std::hex << status << std::dec + << std::endl; } } void VerificationReporter::sendFailureReport(uint8_t report_id, TcPacketBase* current_packet, ReturnValue_t error_code, uint8_t step, uint32_t parameter1, uint32_t parameter2) { - if (this->acknowledgeQueue == 0) { + if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) { this->initialize(); } PusVerificationMessage message(report_id, @@ -57,11 +61,12 @@ void VerificationReporter::sendFailureReport(uint8_t report_id, current_packet->getPacketId(), current_packet->getPacketSequenceControl(), error_code, step, parameter1, parameter2); - ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message); + ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, + &message); if (status != HasReturnvaluesIF::RETURN_OK) { - sif::error - << "VerificationReporter::sendFailureReport Error writing to queue. Code: " - << (uint16_t) status << std::endl; + sif::error << "VerificationReporter::sendFailureReport: Error writing " + << "to queue. Code: " << std::hex << "0x" << status << std::dec + << std::endl; } } @@ -69,27 +74,33 @@ void VerificationReporter::sendFailureReport(uint8_t report_id, uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, ReturnValue_t error_code, uint8_t step, uint32_t parameter1, uint32_t parameter2) { - if (this->acknowledgeQueue == 0) { + if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) { this->initialize(); } PusVerificationMessage message(report_id, ackFlags, tcPacketId, tcSequenceControl, error_code, step, parameter1, parameter2); - ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message); + ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, + &message); if (status != HasReturnvaluesIF::RETURN_OK) { - sif::error - << "VerificationReporter::sendFailureReport Error writing to queue. Code: " - << (uint16_t) status << std::endl; + sif::error << "VerificationReporter::sendFailureReport: Error writing " + << "to queue. Code: " << std::hex << "0x" << status << std::dec + << std::endl; } } void VerificationReporter::initialize() { + if(messageReceiver == objects::NO_OBJECT) { + sif::warning << "VerificationReporter::initialize: Verification message" + " receiver object ID not set yet in Factory!" << std::endl; + return; + } AcceptsVerifyMessageIF* temp = objectManager->get( messageReceiver); - if (temp != NULL) { - this->acknowledgeQueue = temp->getVerificationQueue(); - } else { - sif::error - << "VerificationReporter::VerificationReporter: Configuration error." - << std::endl; + if (temp == nullptr) { + sif::error << "VerificationReporter::initialize: Message " + << "receiver invalid. Make sure it is set up properly and " + << "implementsAcceptsVerifyMessageIF" << std::endl; + return; } + this->acknowledgeQueue = temp->getVerificationQueue(); } diff --git a/tmtcservices/VerificationReporter.h b/tmtcservices/VerificationReporter.h index 29a273c5..f26fa54f 100644 --- a/tmtcservices/VerificationReporter.h +++ b/tmtcservices/VerificationReporter.h @@ -1,31 +1,50 @@ -#ifndef VERIFICATIONREPORTER_H_ -#define VERIFICATIONREPORTER_H_ +#ifndef FSFW_TMTCSERVICES_VERIFICATIONREPORTER_H_ +#define FSFW_TMTCSERVICES_VERIFICATIONREPORTER_H_ -#include "../objectmanager/ObjectManagerIF.h" #include "PusVerificationReport.h" +#include "../objectmanager/ObjectManagerIF.h" namespace Factory{ void setStaticFrameworkObjectIds(); } +/** + * @brief This helper object is used to forward verification messages + * which are generated by the Flight Software Framework. + * @details + * The messages can be relayed to an arbitrary object, for example a dedicated + * Verification Reporter. The destination is set by setting the static framework + * Id VerificationReporter::messageReceiver. The default verification reporter + * will be the PUS service 1, which sends verification messages according + * to the PUS standard. + * + */ class VerificationReporter { friend void (Factory::setStaticFrameworkObjectIds)(); public: VerificationReporter(); virtual ~VerificationReporter(); - void sendSuccessReport( uint8_t set_report_id, TcPacketBase* current_packet, uint8_t set_step = 0 ); - void sendSuccessReport(uint8_t set_report_id, uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, uint8_t set_step = 0); - void sendFailureReport( uint8_t report_id, TcPacketBase* current_packet, ReturnValue_t error_code = 0, - uint8_t step = 0, uint32_t parameter1 = 0, uint32_t parameter2 = 0 ); + + void sendSuccessReport( uint8_t set_report_id, TcPacketBase* current_packet, + uint8_t set_step = 0 ); + void sendSuccessReport(uint8_t set_report_id, uint8_t ackFlags, + uint16_t tcPacketId, uint16_t tcSequenceControl, + uint8_t set_step = 0); + + void sendFailureReport( uint8_t report_id, TcPacketBase* current_packet, + ReturnValue_t error_code = 0, + uint8_t step = 0, uint32_t parameter1 = 0, + uint32_t parameter2 = 0 ); void sendFailureReport(uint8_t report_id, - uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, ReturnValue_t error_code = 0, uint8_t step = 0, + uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, + ReturnValue_t error_code = 0, uint8_t step = 0, uint32_t parameter1 = 0, uint32_t parameter2 = 0); + void initialize(); + private: static object_id_t messageReceiver; MessageQueueId_t acknowledgeQueue; - - }; -#endif /* VERIFICATIONREPORTER_H_ */ +#endif /* FSFW_TMTCSERVICES_VERIFICATIONREPORTER_H_ */ From 7dbb73b7d8e7cb9e655327e7341aeb5a23c1b046 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 14:29:57 +0200 Subject: [PATCH 376/653] removed dbeug printout --- osal/FreeRTOS/FixedTimeslotTask.cpp | 9 --------- osal/FreeRTOS/PeriodicTask.cpp | 4 ---- 2 files changed, 13 deletions(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index 309574eb..062686e2 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -150,15 +150,6 @@ void FixedTimeslotTask::handleMissedDeadline() { if(deadlineMissedFunc != nullptr) { this->deadlineMissedFunc(); } - -#ifdef DEBUG - object_id_t handlerId = pst.current->handlerId; - sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) << " with" - << " object ID 0x" << std::setfill('0') << std::setw(8) << std::hex - << handlerId << " missed deadline!" << std::setfill(' ') - << std::dec << std::endl; -#endif - } ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { diff --git a/osal/FreeRTOS/PeriodicTask.cpp b/osal/FreeRTOS/PeriodicTask.cpp index 990d38d6..5c0a840d 100644 --- a/osal/FreeRTOS/PeriodicTask.cpp +++ b/osal/FreeRTOS/PeriodicTask.cpp @@ -133,10 +133,6 @@ TaskHandle_t PeriodicTask::getTaskHandle() { } void PeriodicTask::handleMissedDeadline() { -#ifdef DEBUG - sif::warning << "PeriodicTask: " << pcTaskGetName(NULL) << - " missed deadline!\n" << std::flush; -#endif if(deadlineMissedFunc != nullptr) { this->deadlineMissedFunc(); } From cef84b13d923524e10e497602b6b6c27a62a34d0 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 14:35:05 +0200 Subject: [PATCH 377/653] renormalization --- ipc/messageQueueDefinitions.h | 38 +-- storagemanager/ConstStorageAccessor.cpp | 174 ++++++------ storagemanager/ConstStorageAccessor.h | 232 ++++++++-------- storagemanager/StorageAccessor.cpp | 134 +++++----- storagemanager/StorageAccessor.h | 90 +++---- storagemanager/StorageManagerIF.h | 334 ++++++++++++------------ 6 files changed, 501 insertions(+), 501 deletions(-) diff --git a/ipc/messageQueueDefinitions.h b/ipc/messageQueueDefinitions.h index 60c09b05..b4f861b8 100644 --- a/ipc/messageQueueDefinitions.h +++ b/ipc/messageQueueDefinitions.h @@ -1,19 +1,19 @@ -#ifndef FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ -#define FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ - -#include - -/* - * TODO: Actually, the definition of this ID to be a uint32_t is not ideal and - * breaks layering. However, it is difficult to keep layering, as the ID is - * stored in many places and sent around in MessageQueueMessage. - * Ideally, one would use the (current) object_id_t only, however, doing a - * lookup of queueIDs for every call does not sound ideal. - * In a first step, I'll circumvent the issue by not touching it, - * maybe in a second step. This also influences Interface design - * (getCommandQueue) and some other issues.. - */ -using MessageQueueId_t = uint32_t; - - -#endif /* FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ */ +#ifndef FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ +#define FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ + +#include + +/* + * TODO: Actually, the definition of this ID to be a uint32_t is not ideal and + * breaks layering. However, it is difficult to keep layering, as the ID is + * stored in many places and sent around in MessageQueueMessage. + * Ideally, one would use the (current) object_id_t only, however, doing a + * lookup of queueIDs for every call does not sound ideal. + * In a first step, I'll circumvent the issue by not touching it, + * maybe in a second step. This also influences Interface design + * (getCommandQueue) and some other issues.. + */ +using MessageQueueId_t = uint32_t; + + +#endif /* FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ */ diff --git a/storagemanager/ConstStorageAccessor.cpp b/storagemanager/ConstStorageAccessor.cpp index ea9f2e44..4ada7f80 100644 --- a/storagemanager/ConstStorageAccessor.cpp +++ b/storagemanager/ConstStorageAccessor.cpp @@ -1,87 +1,87 @@ -#include "../serviceinterface/ServiceInterfaceStream.h" -#include "../storagemanager/ConstStorageAccessor.h" -#include "../storagemanager/StorageManagerIF.h" -#include "../globalfunctions/arrayprinter.h" - -ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): - storeId(storeId) {} - -ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId, - StorageManagerIF* store): - storeId(storeId), store(store) { - internalState = AccessState::ASSIGNED; -} - -ConstStorageAccessor::~ConstStorageAccessor() { - if(deleteData and store != nullptr) { - sif::debug << "deleting store data" << std::endl; - store->deleteData(storeId); - } -} - -ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other): - constDataPointer(other.constDataPointer), storeId(other.storeId), - size_(other.size_), store(other.store), deleteData(other.deleteData), - internalState(other.internalState) { - // This prevent premature deletion - other.store = nullptr; -} - -ConstStorageAccessor& ConstStorageAccessor::operator=( - ConstStorageAccessor&& other) { - constDataPointer = other.constDataPointer; - storeId = other.storeId; - store = other.store; - size_ = other.size_; - deleteData = other.deleteData; - this->store = other.store; - // This prevents premature deletion - other.store = nullptr; - return *this; -} - -const uint8_t* ConstStorageAccessor::data() const { - return constDataPointer; -} - -size_t ConstStorageAccessor::size() const { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - } - return size_; -} - -ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t *pointer, - size_t maxSize) { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - if(size_ > maxSize) { - sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - std::copy(constDataPointer, constDataPointer + size_, pointer); - return HasReturnvaluesIF::RETURN_OK; -} - -void ConstStorageAccessor::release() { - deleteData = false; -} - -store_address_t ConstStorageAccessor::getId() const { - return storeId; -} - -void ConstStorageAccessor::print() const { - if(internalState == AccessState::UNINIT or constDataPointer == nullptr) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return; - } - arrayprinter::print(constDataPointer, size_); -} - -void ConstStorageAccessor::assignStore(StorageManagerIF* store) { - internalState = AccessState::ASSIGNED; - this->store = store; -} +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../storagemanager/ConstStorageAccessor.h" +#include "../storagemanager/StorageManagerIF.h" +#include "../globalfunctions/arrayprinter.h" + +ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): + storeId(storeId) {} + +ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId, + StorageManagerIF* store): + storeId(storeId), store(store) { + internalState = AccessState::ASSIGNED; +} + +ConstStorageAccessor::~ConstStorageAccessor() { + if(deleteData and store != nullptr) { + sif::debug << "deleting store data" << std::endl; + store->deleteData(storeId); + } +} + +ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other): + constDataPointer(other.constDataPointer), storeId(other.storeId), + size_(other.size_), store(other.store), deleteData(other.deleteData), + internalState(other.internalState) { + // This prevent premature deletion + other.store = nullptr; +} + +ConstStorageAccessor& ConstStorageAccessor::operator=( + ConstStorageAccessor&& other) { + constDataPointer = other.constDataPointer; + storeId = other.storeId; + store = other.store; + size_ = other.size_; + deleteData = other.deleteData; + this->store = other.store; + // This prevents premature deletion + other.store = nullptr; + return *this; +} + +const uint8_t* ConstStorageAccessor::data() const { + return constDataPointer; +} + +size_t ConstStorageAccessor::size() const { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + } + return size_; +} + +ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t *pointer, + size_t maxSize) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(size_ > maxSize) { + sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(constDataPointer, constDataPointer + size_, pointer); + return HasReturnvaluesIF::RETURN_OK; +} + +void ConstStorageAccessor::release() { + deleteData = false; +} + +store_address_t ConstStorageAccessor::getId() const { + return storeId; +} + +void ConstStorageAccessor::print() const { + if(internalState == AccessState::UNINIT or constDataPointer == nullptr) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return; + } + arrayprinter::print(constDataPointer, size_); +} + +void ConstStorageAccessor::assignStore(StorageManagerIF* store) { + internalState = AccessState::ASSIGNED; + this->store = store; +} diff --git a/storagemanager/ConstStorageAccessor.h b/storagemanager/ConstStorageAccessor.h index ec2da8ce..573892da 100644 --- a/storagemanager/ConstStorageAccessor.h +++ b/storagemanager/ConstStorageAccessor.h @@ -1,116 +1,116 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ -#define FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ - -#include "../storagemanager/storeAddress.h" -#include "../returnvalues/HasReturnvaluesIF.h" -#include - -class StorageManagerIF; - -/** - * @brief Helper classes to facilitate safe access to storages which is also - * conforming to RAII principles - * @details - * Accessor class which can be returned by pool manager or passed and set by - * pool managers to have safe access to the pool resources. - * - * These helper can be used together with the StorageManager classes to manage - * access to a storage. It can take care of thread-safety while also providing - * mechanisms to automatically clear storage data. - */ -class ConstStorageAccessor { - //! StorageManager classes have exclusive access to private variables. - template - friend class PoolManager; - template - friend class LocalPool; -public: - /** - * @brief Simple constructor which takes the store ID of the storage - * entry to access. - * @param storeId - */ - ConstStorageAccessor(store_address_t storeId); - ConstStorageAccessor(store_address_t storeId, StorageManagerIF* store); - - /** - * @brief The destructor in default configuration takes care of - * deleting the accessed pool entry and unlocking the mutex - */ - virtual ~ConstStorageAccessor(); - - /** - * @brief Returns a pointer to the read-only data - * @return - */ - const uint8_t* data() const; - - /** - * @brief Copies the read-only data to the supplied pointer - * @param pointer - */ - virtual ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize); - - /** - * @brief Calling this will prevent the Accessor from deleting the data - * when the destructor is called. - */ - void release(); - - /** - * Get the size of the data - * @return - */ - size_t size() const; - - /** - * Get the storage ID. - * @return - */ - store_address_t getId() const; - - void print() const; - - /** - * @brief Move ctor and move assignment allow returning accessors as - * a returnvalue. They prevent resource being free prematurely. - * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ - * move-constructors-and-move-assignment-operators-cpp.md - * @param - * @return - */ - ConstStorageAccessor& operator= (ConstStorageAccessor&&); - ConstStorageAccessor(ConstStorageAccessor&&); - - //! The copy ctor and copy assignemnt should be deleted implicitely - //! according to https://foonathan.net/2019/02/special-member-functions/ - //! but I still deleted them to make it more explicit. (remember rule of 5). - ConstStorageAccessor& operator=(const ConstStorageAccessor&) = delete; - ConstStorageAccessor(const ConstStorageAccessor&) = delete; -protected: - const uint8_t* constDataPointer = nullptr; - store_address_t storeId; - size_t size_ = 0; - //! Managing pool, has to assign itself. - StorageManagerIF* store = nullptr; - bool deleteData = true; - - enum class AccessState { - UNINIT, - ASSIGNED - }; - //! Internal state for safety reasons. - AccessState internalState = AccessState::UNINIT; - /** - * Used by the pool manager instances to assign themselves to the - * accessor. This is necessary to delete the data when the acessor - * exits the scope ! The internal state will be considered read - * when this function is called, so take care all data is set properly as - * well. - * @param - */ - void assignStore(StorageManagerIF*); -}; - - -#endif /* FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ */ +#ifndef FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ +#define FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ + +#include "../storagemanager/storeAddress.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include + +class StorageManagerIF; + +/** + * @brief Helper classes to facilitate safe access to storages which is also + * conforming to RAII principles + * @details + * Accessor class which can be returned by pool manager or passed and set by + * pool managers to have safe access to the pool resources. + * + * These helper can be used together with the StorageManager classes to manage + * access to a storage. It can take care of thread-safety while also providing + * mechanisms to automatically clear storage data. + */ +class ConstStorageAccessor { + //! StorageManager classes have exclusive access to private variables. + template + friend class PoolManager; + template + friend class LocalPool; +public: + /** + * @brief Simple constructor which takes the store ID of the storage + * entry to access. + * @param storeId + */ + ConstStorageAccessor(store_address_t storeId); + ConstStorageAccessor(store_address_t storeId, StorageManagerIF* store); + + /** + * @brief The destructor in default configuration takes care of + * deleting the accessed pool entry and unlocking the mutex + */ + virtual ~ConstStorageAccessor(); + + /** + * @brief Returns a pointer to the read-only data + * @return + */ + const uint8_t* data() const; + + /** + * @brief Copies the read-only data to the supplied pointer + * @param pointer + */ + virtual ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize); + + /** + * @brief Calling this will prevent the Accessor from deleting the data + * when the destructor is called. + */ + void release(); + + /** + * Get the size of the data + * @return + */ + size_t size() const; + + /** + * Get the storage ID. + * @return + */ + store_address_t getId() const; + + void print() const; + + /** + * @brief Move ctor and move assignment allow returning accessors as + * a returnvalue. They prevent resource being free prematurely. + * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ + * move-constructors-and-move-assignment-operators-cpp.md + * @param + * @return + */ + ConstStorageAccessor& operator= (ConstStorageAccessor&&); + ConstStorageAccessor(ConstStorageAccessor&&); + + //! The copy ctor and copy assignemnt should be deleted implicitely + //! according to https://foonathan.net/2019/02/special-member-functions/ + //! but I still deleted them to make it more explicit. (remember rule of 5). + ConstStorageAccessor& operator=(const ConstStorageAccessor&) = delete; + ConstStorageAccessor(const ConstStorageAccessor&) = delete; +protected: + const uint8_t* constDataPointer = nullptr; + store_address_t storeId; + size_t size_ = 0; + //! Managing pool, has to assign itself. + StorageManagerIF* store = nullptr; + bool deleteData = true; + + enum class AccessState { + UNINIT, + ASSIGNED + }; + //! Internal state for safety reasons. + AccessState internalState = AccessState::UNINIT; + /** + * Used by the pool manager instances to assign themselves to the + * accessor. This is necessary to delete the data when the acessor + * exits the scope ! The internal state will be considered read + * when this function is called, so take care all data is set properly as + * well. + * @param + */ + void assignStore(StorageManagerIF*); +}; + + +#endif /* FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ */ diff --git a/storagemanager/StorageAccessor.cpp b/storagemanager/StorageAccessor.cpp index d4d2a54d..60bd4130 100644 --- a/storagemanager/StorageAccessor.cpp +++ b/storagemanager/StorageAccessor.cpp @@ -1,67 +1,67 @@ -#include "../storagemanager/StorageAccessor.h" -#include "../storagemanager/StorageManagerIF.h" -#include "../serviceinterface/ServiceInterfaceStream.h" - -StorageAccessor::StorageAccessor(store_address_t storeId): - ConstStorageAccessor(storeId) { -} - -StorageAccessor::StorageAccessor(store_address_t storeId, - StorageManagerIF* store): - ConstStorageAccessor(storeId, store) { -} - -StorageAccessor& StorageAccessor::operator =( - StorageAccessor&& other) { - // Call the parent move assignment and also assign own member. - dataPointer = other.dataPointer; - StorageAccessor::operator=(std::move(other)); - return * this; -} - -// Call the parent move ctor and also transfer own member. -StorageAccessor::StorageAccessor(StorageAccessor&& other): - ConstStorageAccessor(std::move(other)), dataPointer(other.dataPointer) { -} - -ReturnValue_t StorageAccessor::getDataCopy(uint8_t *pointer, size_t maxSize) { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - if(size_ > maxSize) { - sif::error << "StorageAccessor: Supplied buffer not large " - "enough" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - std::copy(dataPointer, dataPointer + size_, pointer); - return HasReturnvaluesIF::RETURN_OK; -} - -uint8_t* StorageAccessor::data() { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - } - return dataPointer; -} - -ReturnValue_t StorageAccessor::write(uint8_t *data, size_t size, - uint16_t offset) { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - if(offset + size > size_) { - sif::error << "StorageAccessor: Data too large for pool " - "entry!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - std::copy(data, data + size, dataPointer + offset); - return HasReturnvaluesIF::RETURN_OK; -} - -void StorageAccessor::assignConstPointer() { - constDataPointer = dataPointer; -} - - +#include "../storagemanager/StorageAccessor.h" +#include "../storagemanager/StorageManagerIF.h" +#include "../serviceinterface/ServiceInterfaceStream.h" + +StorageAccessor::StorageAccessor(store_address_t storeId): + ConstStorageAccessor(storeId) { +} + +StorageAccessor::StorageAccessor(store_address_t storeId, + StorageManagerIF* store): + ConstStorageAccessor(storeId, store) { +} + +StorageAccessor& StorageAccessor::operator =( + StorageAccessor&& other) { + // Call the parent move assignment and also assign own member. + dataPointer = other.dataPointer; + StorageAccessor::operator=(std::move(other)); + return * this; +} + +// Call the parent move ctor and also transfer own member. +StorageAccessor::StorageAccessor(StorageAccessor&& other): + ConstStorageAccessor(std::move(other)), dataPointer(other.dataPointer) { +} + +ReturnValue_t StorageAccessor::getDataCopy(uint8_t *pointer, size_t maxSize) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(size_ > maxSize) { + sif::error << "StorageAccessor: Supplied buffer not large " + "enough" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(dataPointer, dataPointer + size_, pointer); + return HasReturnvaluesIF::RETURN_OK; +} + +uint8_t* StorageAccessor::data() { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + } + return dataPointer; +} + +ReturnValue_t StorageAccessor::write(uint8_t *data, size_t size, + uint16_t offset) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(offset + size > size_) { + sif::error << "StorageAccessor: Data too large for pool " + "entry!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(data, data + size, dataPointer + offset); + return HasReturnvaluesIF::RETURN_OK; +} + +void StorageAccessor::assignConstPointer() { + constDataPointer = dataPointer; +} + + diff --git a/storagemanager/StorageAccessor.h b/storagemanager/StorageAccessor.h index 1ca5f7dd..a65427b8 100644 --- a/storagemanager/StorageAccessor.h +++ b/storagemanager/StorageAccessor.h @@ -1,45 +1,45 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ -#define FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ - -#include "../storagemanager/ConstStorageAccessor.h" - -class StorageManagerIF; - -/** - * @brief Child class for modifyable data. Also has a normal pointer member. - */ -class StorageAccessor: public ConstStorageAccessor { - //! StorageManager classes have exclusive access to private variables. - template - friend class PoolManager; - template - friend class LocalPool; -public: - StorageAccessor(store_address_t storeId); - StorageAccessor(store_address_t storeId, StorageManagerIF* store); - - /** - * @brief Move ctor and move assignment allow returning accessors as - * a returnvalue. They prevent resource being freed prematurely. - * See: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ - * move-constructors-and-move-assignment-operators-cpp.md - * @param - * @return - */ - StorageAccessor& operator=(StorageAccessor&&); - StorageAccessor(StorageAccessor&&); - - ReturnValue_t write(uint8_t *data, size_t size, - uint16_t offset = 0); - uint8_t* data(); - ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize) override; - -private: - //! Non-const pointer for modifyable data. - uint8_t* dataPointer = nullptr; - //! For modifyable data, the const pointer is assigned to the normal - //! pointer by the pool manager so both access functions can be used safely - void assignConstPointer(); -}; - -#endif /* TEST_PROTOTYPES_STORAGEACCESSOR_H_ */ +#ifndef FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ +#define FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ + +#include "../storagemanager/ConstStorageAccessor.h" + +class StorageManagerIF; + +/** + * @brief Child class for modifyable data. Also has a normal pointer member. + */ +class StorageAccessor: public ConstStorageAccessor { + //! StorageManager classes have exclusive access to private variables. + template + friend class PoolManager; + template + friend class LocalPool; +public: + StorageAccessor(store_address_t storeId); + StorageAccessor(store_address_t storeId, StorageManagerIF* store); + + /** + * @brief Move ctor and move assignment allow returning accessors as + * a returnvalue. They prevent resource being freed prematurely. + * See: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ + * move-constructors-and-move-assignment-operators-cpp.md + * @param + * @return + */ + StorageAccessor& operator=(StorageAccessor&&); + StorageAccessor(StorageAccessor&&); + + ReturnValue_t write(uint8_t *data, size_t size, + uint16_t offset = 0); + uint8_t* data(); + ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize) override; + +private: + //! Non-const pointer for modifyable data. + uint8_t* dataPointer = nullptr; + //! For modifyable data, the const pointer is assigned to the normal + //! pointer by the pool manager so both access functions can be used safely + void assignConstPointer(); +}; + +#endif /* TEST_PROTOTYPES_STORAGEACCESSOR_H_ */ diff --git a/storagemanager/StorageManagerIF.h b/storagemanager/StorageManagerIF.h index 85341f2e..2229cdf8 100644 --- a/storagemanager/StorageManagerIF.h +++ b/storagemanager/StorageManagerIF.h @@ -1,167 +1,167 @@ -#ifndef STORAGEMANAGERIF_H_H -#define STORAGEMANAGERIF_H_H - -#include "../events/Event.h" -#include "../returnvalues/HasReturnvaluesIF.h" -#include "../storagemanager/StorageAccessor.h" -#include "../storagemanager/storeAddress.h" -#include -#include - -using AccessorPair = std::pair; -using ConstAccessorPair = std::pair; - -/** - * @brief This class provides an interface for intermediate data storage. - * @details The Storage manager classes shall be used to store larger chunks of - * data in RAM for exchange between tasks. This interface expects the - * data to be stored in one consecutive block of memory, so tasks can - * write directly to the destination pointer. - * For interprocess communication, the stores must be locked during - * insertion and deletion. If the receiving storage identifier is - * passed token-like between tasks, a lock during read and write - * operations is not necessary. - * @author Bastian Baetz - * @date 18.09.2012 - */ -class StorageManagerIF : public HasReturnvaluesIF { -public: - static const uint8_t INTERFACE_ID = CLASS_ID::STORAGE_MANAGER_IF; //!< The unique ID for return codes for this interface. - static const ReturnValue_t DATA_TOO_LARGE = MAKE_RETURN_CODE(1); //!< This return code indicates that the data to be stored is too large for the store. - static const ReturnValue_t DATA_STORAGE_FULL = MAKE_RETURN_CODE(2); //!< This return code indicates that a data storage is full. - static const ReturnValue_t ILLEGAL_STORAGE_ID = MAKE_RETURN_CODE(3); //!< This return code indicates that data was requested with an illegal storage ID. - static const ReturnValue_t DATA_DOES_NOT_EXIST = MAKE_RETURN_CODE(4); //!< This return code indicates that the requested ID was valid, but no data is stored there. - static const ReturnValue_t ILLEGAL_ADDRESS = MAKE_RETURN_CODE(5); - static const ReturnValue_t POOL_TOO_LARGE = MAKE_RETURN_CODE(6); //!< Pool size too large on initialization. - - static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::OBSW; - static const Event GET_DATA_FAILED = MAKE_EVENT(0, SEVERITY::LOW); - static const Event STORE_DATA_FAILED = MAKE_EVENT(1, SEVERITY::LOW); - - static const uint32_t INVALID_ADDRESS = 0xFFFFFFFF; //!< Indicates an invalid (i.e unused) storage address. - /** - * @brief This is the empty virtual destructor as required for C++ interfaces. - */ - virtual ~StorageManagerIF() { - } - ; - /** - * @brief With addData, a free storage position is allocated and data - * stored there. - * @details During the allocation, the StorageManager is blocked. - * @param storageId A pointer to the storageId to retrieve. - * @param data The data to be stored in the StorageManager. - * @param size The amount of data to be stored. - * @return Returns @li RETURN_OK if data was added. - * @li RETURN_FAILED if data could not be added. - * storageId is unchanged then. - */ - virtual ReturnValue_t addData(store_address_t* storageId, - const uint8_t * data, size_t size, bool ignoreFault = false) = 0; - /** - * @brief With deleteData, the storageManager frees the memory region - * identified by packet_id. - * @param packet_id The identifier of the memory region to be freed. - * @return @li RETURN_OK on success. - * @li RETURN_FAILED if deletion did not work - * (e.g. an illegal packet_id was passed). - */ - virtual ReturnValue_t deleteData(store_address_t packet_id) = 0; - /** - * @brief Another deleteData which uses the pointer and size of the - * stored data to delete the content. - * @param buffer Pointer to the data. - * @param size Size of data to be stored. - * @param storeId Store id of the deleted element (optional) - * @return @li RETURN_OK on success. - * @li failure code if deletion did not work - */ - virtual ReturnValue_t deleteData(uint8_t* buffer, size_t size, - store_address_t* storeId = nullptr) = 0; - - - /** - * @brief Access the data by supplying a store ID. - * @details - * A pair consisting of the retrieval result and an instance of a - * ConstStorageAccessor class is returned - * @param storeId - * @return Pair of return value and a ConstStorageAccessor instance - */ - virtual ConstAccessorPair getData(store_address_t storeId) = 0; - - /** - * @brief Access the data by supplying a store ID and a helper - * instance - * @param storeId - * @param constAccessor Wrapper function to access store data. - * @return - */ - virtual ReturnValue_t getData(store_address_t storeId, - ConstStorageAccessor& constAccessor) = 0; - - - /** - * @brief getData returns an address to data and the size of the data - * for a given packet_id. - * @param packet_id The id of the data to be returned - * @param packet_ptr The passed pointer address is set to the the memory - * position - * @param size The exact size of the stored data is returned here. - * @return @li RETURN_OK on success. - * @li RETURN_FAILED if fetching data did not work - * (e.g. an illegal packet_id was passed). - */ - virtual ReturnValue_t getData(store_address_t packet_id, - const uint8_t** packet_ptr, size_t* size) = 0; - - - /** - * Modify data by supplying a store ID - * @param storeId - * @return Pair of return value and StorageAccessor helper - */ - virtual AccessorPair modifyData(store_address_t storeId) = 0; - - /** - * Modify data by supplying a store ID and a StorageAccessor helper instance. - * @param storeId - * @param accessor Helper class to access the modifiable data. - * @return - */ - virtual ReturnValue_t modifyData(store_address_t storeId, - StorageAccessor& accessor) = 0; - - /** - * Get pointer and size of modifiable data by supplying the storeId - * @param packet_id - * @param packet_ptr [out] Pointer to pointer of data to set - * @param size [out] Pointer to size to set - * @return - */ - virtual ReturnValue_t modifyData(store_address_t packet_id, - uint8_t** packet_ptr, size_t* size) = 0; - /** - * This method reserves an element of \c size. - * - * It returns the packet id of this element as well as a direct pointer to the - * data of the element. It must be assured that exactly \c size data is - * written to p_data! - * @param storageId A pointer to the storageId to retrieve. - * @param size The size of the space to be reserved. - * @param p_data A pointer to the element data is returned here. - * @return Returns @li RETURN_OK if data was added. - * @li RETURN_FAILED if data could not be added. - * storageId is unchanged then. - */ - virtual ReturnValue_t getFreeElement(store_address_t* storageId, - const size_t size, uint8_t** p_data, bool ignoreFault = false ) = 0; - - /** - * Clears the whole store. - * Use with care! - */ - virtual void clearStore() = 0; -}; - -#endif /* STORAGEMANAGERIF_H_ */ +#ifndef STORAGEMANAGERIF_H_H +#define STORAGEMANAGERIF_H_H + +#include "../events/Event.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../storagemanager/StorageAccessor.h" +#include "../storagemanager/storeAddress.h" +#include +#include + +using AccessorPair = std::pair; +using ConstAccessorPair = std::pair; + +/** + * @brief This class provides an interface for intermediate data storage. + * @details The Storage manager classes shall be used to store larger chunks of + * data in RAM for exchange between tasks. This interface expects the + * data to be stored in one consecutive block of memory, so tasks can + * write directly to the destination pointer. + * For interprocess communication, the stores must be locked during + * insertion and deletion. If the receiving storage identifier is + * passed token-like between tasks, a lock during read and write + * operations is not necessary. + * @author Bastian Baetz + * @date 18.09.2012 + */ +class StorageManagerIF : public HasReturnvaluesIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::STORAGE_MANAGER_IF; //!< The unique ID for return codes for this interface. + static const ReturnValue_t DATA_TOO_LARGE = MAKE_RETURN_CODE(1); //!< This return code indicates that the data to be stored is too large for the store. + static const ReturnValue_t DATA_STORAGE_FULL = MAKE_RETURN_CODE(2); //!< This return code indicates that a data storage is full. + static const ReturnValue_t ILLEGAL_STORAGE_ID = MAKE_RETURN_CODE(3); //!< This return code indicates that data was requested with an illegal storage ID. + static const ReturnValue_t DATA_DOES_NOT_EXIST = MAKE_RETURN_CODE(4); //!< This return code indicates that the requested ID was valid, but no data is stored there. + static const ReturnValue_t ILLEGAL_ADDRESS = MAKE_RETURN_CODE(5); + static const ReturnValue_t POOL_TOO_LARGE = MAKE_RETURN_CODE(6); //!< Pool size too large on initialization. + + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::OBSW; + static const Event GET_DATA_FAILED = MAKE_EVENT(0, SEVERITY::LOW); + static const Event STORE_DATA_FAILED = MAKE_EVENT(1, SEVERITY::LOW); + + static const uint32_t INVALID_ADDRESS = 0xFFFFFFFF; //!< Indicates an invalid (i.e unused) storage address. + /** + * @brief This is the empty virtual destructor as required for C++ interfaces. + */ + virtual ~StorageManagerIF() { + } + ; + /** + * @brief With addData, a free storage position is allocated and data + * stored there. + * @details During the allocation, the StorageManager is blocked. + * @param storageId A pointer to the storageId to retrieve. + * @param data The data to be stored in the StorageManager. + * @param size The amount of data to be stored. + * @return Returns @li RETURN_OK if data was added. + * @li RETURN_FAILED if data could not be added. + * storageId is unchanged then. + */ + virtual ReturnValue_t addData(store_address_t* storageId, + const uint8_t * data, size_t size, bool ignoreFault = false) = 0; + /** + * @brief With deleteData, the storageManager frees the memory region + * identified by packet_id. + * @param packet_id The identifier of the memory region to be freed. + * @return @li RETURN_OK on success. + * @li RETURN_FAILED if deletion did not work + * (e.g. an illegal packet_id was passed). + */ + virtual ReturnValue_t deleteData(store_address_t packet_id) = 0; + /** + * @brief Another deleteData which uses the pointer and size of the + * stored data to delete the content. + * @param buffer Pointer to the data. + * @param size Size of data to be stored. + * @param storeId Store id of the deleted element (optional) + * @return @li RETURN_OK on success. + * @li failure code if deletion did not work + */ + virtual ReturnValue_t deleteData(uint8_t* buffer, size_t size, + store_address_t* storeId = nullptr) = 0; + + + /** + * @brief Access the data by supplying a store ID. + * @details + * A pair consisting of the retrieval result and an instance of a + * ConstStorageAccessor class is returned + * @param storeId + * @return Pair of return value and a ConstStorageAccessor instance + */ + virtual ConstAccessorPair getData(store_address_t storeId) = 0; + + /** + * @brief Access the data by supplying a store ID and a helper + * instance + * @param storeId + * @param constAccessor Wrapper function to access store data. + * @return + */ + virtual ReturnValue_t getData(store_address_t storeId, + ConstStorageAccessor& constAccessor) = 0; + + + /** + * @brief getData returns an address to data and the size of the data + * for a given packet_id. + * @param packet_id The id of the data to be returned + * @param packet_ptr The passed pointer address is set to the the memory + * position + * @param size The exact size of the stored data is returned here. + * @return @li RETURN_OK on success. + * @li RETURN_FAILED if fetching data did not work + * (e.g. an illegal packet_id was passed). + */ + virtual ReturnValue_t getData(store_address_t packet_id, + const uint8_t** packet_ptr, size_t* size) = 0; + + + /** + * Modify data by supplying a store ID + * @param storeId + * @return Pair of return value and StorageAccessor helper + */ + virtual AccessorPair modifyData(store_address_t storeId) = 0; + + /** + * Modify data by supplying a store ID and a StorageAccessor helper instance. + * @param storeId + * @param accessor Helper class to access the modifiable data. + * @return + */ + virtual ReturnValue_t modifyData(store_address_t storeId, + StorageAccessor& accessor) = 0; + + /** + * Get pointer and size of modifiable data by supplying the storeId + * @param packet_id + * @param packet_ptr [out] Pointer to pointer of data to set + * @param size [out] Pointer to size to set + * @return + */ + virtual ReturnValue_t modifyData(store_address_t packet_id, + uint8_t** packet_ptr, size_t* size) = 0; + /** + * This method reserves an element of \c size. + * + * It returns the packet id of this element as well as a direct pointer to the + * data of the element. It must be assured that exactly \c size data is + * written to p_data! + * @param storageId A pointer to the storageId to retrieve. + * @param size The size of the space to be reserved. + * @param p_data A pointer to the element data is returned here. + * @return Returns @li RETURN_OK if data was added. + * @li RETURN_FAILED if data could not be added. + * storageId is unchanged then. + */ + virtual ReturnValue_t getFreeElement(store_address_t* storageId, + const size_t size, uint8_t** p_data, bool ignoreFault = false ) = 0; + + /** + * Clears the whole store. + * Use with care! + */ + virtual void clearStore() = 0; +}; + +#endif /* STORAGEMANAGERIF_H_ */ From 1ff85c88b2e05749050aabea2dcb91ed544f9ab3 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 14:42:48 +0200 Subject: [PATCH 378/653] store accessor small changes --- storagemanager/ConstStorageAccessor.cpp | 5 +++-- storagemanager/ConstStorageAccessor.h | 8 ++++---- storagemanager/LocalPool.h | 6 +++--- storagemanager/LocalPool.tpp | 8 ++++---- storagemanager/PoolManager.h | 19 ++++++++++++------- storagemanager/PoolManager.tpp | 4 ++-- storagemanager/StorageAccessor.cpp | 4 ++-- storagemanager/StorageAccessor.h | 8 ++++---- storagemanager/StorageManagerIF.h | 12 +++++++----- 9 files changed, 41 insertions(+), 33 deletions(-) diff --git a/storagemanager/ConstStorageAccessor.cpp b/storagemanager/ConstStorageAccessor.cpp index 4ada7f80..71d732bf 100644 --- a/storagemanager/ConstStorageAccessor.cpp +++ b/storagemanager/ConstStorageAccessor.cpp @@ -1,6 +1,7 @@ +#include "ConstStorageAccessor.h" +#include "StorageManagerIF.h" + #include "../serviceinterface/ServiceInterfaceStream.h" -#include "../storagemanager/ConstStorageAccessor.h" -#include "../storagemanager/StorageManagerIF.h" #include "../globalfunctions/arrayprinter.h" ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): diff --git a/storagemanager/ConstStorageAccessor.h b/storagemanager/ConstStorageAccessor.h index 573892da..96d2dca2 100644 --- a/storagemanager/ConstStorageAccessor.h +++ b/storagemanager/ConstStorageAccessor.h @@ -1,7 +1,7 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ -#define FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ +#ifndef FSFW_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ +#define FSFW_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ -#include "../storagemanager/storeAddress.h" +#include "storeAddress.h" #include "../returnvalues/HasReturnvaluesIF.h" #include @@ -113,4 +113,4 @@ protected: }; -#endif /* FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ */ +#endif /* FSFW_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ */ diff --git a/storagemanager/LocalPool.h b/storagemanager/LocalPool.h index 8d300f8f..3a94c03d 100644 --- a/storagemanager/LocalPool.h +++ b/storagemanager/LocalPool.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ -#define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ +#ifndef FSFW_STORAGEMANAGER_LOCALPOOL_H_ +#define FSFW_STORAGEMANAGER_LOCALPOOL_H_ #include "StorageManagerIF.h" #include "../objectmanager/SystemObject.h" @@ -187,4 +187,4 @@ private: #include "LocalPool.tpp" -#endif /* FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ */ +#endif /* FSFW_STORAGEMANAGER_LOCALPOOL_H_ */ diff --git a/storagemanager/LocalPool.tpp b/storagemanager/LocalPool.tpp index 764bd7be..83c7a718 100644 --- a/storagemanager/LocalPool.tpp +++ b/storagemanager/LocalPool.tpp @@ -1,7 +1,7 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ -#define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ +#ifndef FSFW_STORAGEMANAGER_LOCALPOOL_TPP_ +#define FSFW_STORAGEMANAGER_LOCALPOOL_TPP_ -#ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ +#ifndef FSFW_STORAGEMANAGER_LOCALPOOL_H_ #error Include LocalPool.h before LocalPool.tpp! #endif @@ -301,4 +301,4 @@ inline ReturnValue_t LocalPool::initialize() { return RETURN_OK; } -#endif +#endif /* FSFW_STORAGEMANAGER_LOCALPOOL_TPP_ */ diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index ae719e87..84c88682 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -1,9 +1,9 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_ -#define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_ +#ifndef FSFW_STORAGEMANAGER_POOLMANAGER_H_ +#define FSFW_STORAGEMANAGER_POOLMANAGER_H_ #include "LocalPool.h" +#include "StorageAccessor.h" #include "../ipc/MutexHelper.h" -#include "../storagemanager/StorageAccessor.h" /** @@ -20,11 +20,16 @@ public: const uint16_t element_sizes[NUMBER_OF_POOLS], const uint16_t n_elements[NUMBER_OF_POOLS]); - //! @brief In the PoolManager's destructor all allocated memory is freed. + /** + * @brief In the PoolManager's destructor all allocated memory + * is freed. + */ virtual ~PoolManager(); - //! @brief LocalPool overrides for thread-safety. Decorator function which - //! wraps LocalPool calls with a mutex protection. + /** + * @brief LocalPool overrides for thread-safety. Decorator function + * which wraps LocalPool calls with a mutex protection. + */ ReturnValue_t deleteData(store_address_t) override; ReturnValue_t deleteData(uint8_t* buffer, size_t size, store_address_t* storeId = nullptr) override; @@ -47,4 +52,4 @@ protected: #include "PoolManager.tpp" -#endif /* POOLMANAGER_H_ */ +#endif /* FSFW_STORAGEMANAGER_POOLMANAGER_H_ */ diff --git a/storagemanager/PoolManager.tpp b/storagemanager/PoolManager.tpp index d72346d3..ba7f63b7 100644 --- a/storagemanager/PoolManager.tpp +++ b/storagemanager/PoolManager.tpp @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ #define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ -#ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_ +#ifndef FSFW_STORAGEMANAGER_POOLMANAGER_H_ #error Include PoolManager.h before PoolManager.tpp! #endif @@ -48,4 +48,4 @@ inline ReturnValue_t PoolManager::deleteData(uint8_t* buffer, } -#endif +#endif /* FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ */ diff --git a/storagemanager/StorageAccessor.cpp b/storagemanager/StorageAccessor.cpp index 60bd4130..9c2f936a 100644 --- a/storagemanager/StorageAccessor.cpp +++ b/storagemanager/StorageAccessor.cpp @@ -1,5 +1,5 @@ -#include "../storagemanager/StorageAccessor.h" -#include "../storagemanager/StorageManagerIF.h" +#include "StorageAccessor.h" +#include "StorageManagerIF.h" #include "../serviceinterface/ServiceInterfaceStream.h" StorageAccessor::StorageAccessor(store_address_t storeId): diff --git a/storagemanager/StorageAccessor.h b/storagemanager/StorageAccessor.h index a65427b8..5cf15d50 100644 --- a/storagemanager/StorageAccessor.h +++ b/storagemanager/StorageAccessor.h @@ -1,7 +1,7 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ -#define FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ +#ifndef FSFW_STORAGEMANAGER_STORAGEACCESSOR_H_ +#define FSFW_STORAGEMANAGER_STORAGEACCESSOR_H_ -#include "../storagemanager/ConstStorageAccessor.h" +#include "ConstStorageAccessor.h" class StorageManagerIF; @@ -42,4 +42,4 @@ private: void assignConstPointer(); }; -#endif /* TEST_PROTOTYPES_STORAGEACCESSOR_H_ */ +#endif /* FSFW_STORAGEMANAGER_STORAGEACCESSOR_H_ */ diff --git a/storagemanager/StorageManagerIF.h b/storagemanager/StorageManagerIF.h index 2229cdf8..834e7563 100644 --- a/storagemanager/StorageManagerIF.h +++ b/storagemanager/StorageManagerIF.h @@ -1,10 +1,12 @@ -#ifndef STORAGEMANAGERIF_H_H -#define STORAGEMANAGERIF_H_H +#ifndef FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_ +#define FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_ + +#include "StorageAccessor.h" +#include "storeAddress.h" #include "../events/Event.h" #include "../returnvalues/HasReturnvaluesIF.h" -#include "../storagemanager/StorageAccessor.h" -#include "../storagemanager/storeAddress.h" + #include #include @@ -164,4 +166,4 @@ public: virtual void clearStore() = 0; }; -#endif /* STORAGEMANAGERIF_H_ */ +#endif /* FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_ */ From bed4e7affa0b0a832f877768b18a57a463a89b0a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 14:43:23 +0200 Subject: [PATCH 379/653] nullptr replacement --- storagemanager/LocalPool.tpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storagemanager/LocalPool.tpp b/storagemanager/LocalPool.tpp index 83c7a718..7a6c5c9c 100644 --- a/storagemanager/LocalPool.tpp +++ b/storagemanager/LocalPool.tpp @@ -171,7 +171,7 @@ inline ReturnValue_t LocalPool::getData(store_address_t storeId template inline ReturnValue_t LocalPool::getData( store_address_t packet_id, const uint8_t** packet_ptr, size_t* size) { - uint8_t* tempData = NULL; + uint8_t* tempData = nullptr; ReturnValue_t status = modifyData(packet_id, &tempData, size); *packet_ptr = tempData; return status; From 622c7a5a0d5db90cf27a8b06a21888dd3ffd0eb8 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 14:45:23 +0200 Subject: [PATCH 380/653] debug output removed --- storagemanager/ConstStorageAccessor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storagemanager/ConstStorageAccessor.cpp b/storagemanager/ConstStorageAccessor.cpp index 71d732bf..842f1ce8 100644 --- a/storagemanager/ConstStorageAccessor.cpp +++ b/storagemanager/ConstStorageAccessor.cpp @@ -15,7 +15,6 @@ ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId, ConstStorageAccessor::~ConstStorageAccessor() { if(deleteData and store != nullptr) { - sif::debug << "deleting store data" << std::endl; store->deleteData(storeId); } } @@ -59,7 +58,8 @@ ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t *pointer, return HasReturnvaluesIF::RETURN_FAILED; } if(size_ > maxSize) { - sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; + sif::error << "StorageAccessor: Supplied buffer not large enough" + << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } std::copy(constDataPointer, constDataPointer + size_, pointer); From a58e47623f7bfec389da6d05d35fe1e9831cb462 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 14:50:16 +0200 Subject: [PATCH 381/653] update --- storagemanager/LocalPool.tpp | 7 ++++--- storagemanager/PoolManager.h | 3 ++- storagemanager/PoolManager.tpp | 11 ++++++++--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/storagemanager/LocalPool.tpp b/storagemanager/LocalPool.tpp index 7a6c5c9c..5e61efe4 100644 --- a/storagemanager/LocalPool.tpp +++ b/storagemanager/LocalPool.tpp @@ -125,9 +125,10 @@ inline LocalPool::~LocalPool(void) { } } -template inline -ReturnValue_t LocalPool::addData(store_address_t* storageId, - const uint8_t* data, size_t size, bool ignoreFault) { +template +inline ReturnValue_t LocalPool::addData( + store_address_t* storageId, const uint8_t* data, size_t size, + bool ignoreFault) { ReturnValue_t status = reserveSpace(size, storageId, ignoreFault); if (status == RETURN_OK) { write(*storageId, data, size); diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index 84c88682..8cc6c065 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -34,9 +34,10 @@ public: ReturnValue_t deleteData(uint8_t* buffer, size_t size, store_address_t* storeId = nullptr) override; + void setMutexTimeout(uint32_t mutexTimeoutMs); protected: //! Default mutex timeout value to prevent permanent blocking. - static constexpr uint32_t mutexTimeout = 50; + uint32_t mutexTimeoutMs = 20; ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault) override; diff --git a/storagemanager/PoolManager.tpp b/storagemanager/PoolManager.tpp index ba7f63b7..2be44ece 100644 --- a/storagemanager/PoolManager.tpp +++ b/storagemanager/PoolManager.tpp @@ -21,7 +21,7 @@ inline PoolManager::~PoolManager(void) { template inline ReturnValue_t PoolManager::reserveSpace( const uint32_t size, store_address_t* address, bool ignoreFault) { - MutexHelper mutexHelper(mutex,MutexIF::BLOCKING); + MutexHelper mutexHelper(mutex,MutexIF::WAITING, mutexTimeoutMs); ReturnValue_t status = LocalPool::reserveSpace(size, address,ignoreFault); return status; @@ -33,7 +33,7 @@ inline ReturnValue_t PoolManager::deleteData( // debug << "PoolManager( " << translateObject(getObjectId()) << // " )::deleteData from store " << packet_id.pool_index << // ". id is "<< packet_id.packet_index << std::endl; - MutexHelper mutexHelper(mutex,MutexIF::BLOCKING); + MutexHelper mutexHelper(mutex,MutexIF::WAITING, mutexTimeoutMs); ReturnValue_t status = LocalPool::deleteData(packet_id); return status; } @@ -41,11 +41,16 @@ inline ReturnValue_t PoolManager::deleteData( template inline ReturnValue_t PoolManager::deleteData(uint8_t* buffer, size_t size, store_address_t* storeId) { - MutexHelper mutexHelper(mutex,MutexIF::BLOCKING); + MutexHelper mutexHelper(mutex,MutexIF::WAITING, mutexTimeoutMs); ReturnValue_t status = LocalPool::deleteData(buffer, size, storeId); return status; } +template +inline void PoolManager::setMutexTimeout( + uint32_t mutexTimeoutMs) { + this->mutexTimeout = mutexTimeoutMs; +} #endif /* FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ */ From 1ed1b7ea06fca6199ea5957e0b91affb4dfce47f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 14:51:08 +0200 Subject: [PATCH 382/653] include guard fix --- storagemanager/storeAddress.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/storagemanager/storeAddress.h b/storagemanager/storeAddress.h index 5dd785a3..044c0790 100644 --- a/storagemanager/storeAddress.h +++ b/storagemanager/storeAddress.h @@ -1,5 +1,6 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_STOREADDRESS_H_ -#define FRAMEWORK_STORAGEMANAGER_STOREADDRESS_H_ +#ifndef FSFW_STORAGEMANAGER_STOREADDRESS_H_ +#define FSFW_STORAGEMANAGER_STOREADDRESS_H_ + #include /** @@ -51,4 +52,4 @@ union store_address_t { } }; -#endif /* FRAMEWORK_STORAGEMANAGER_STOREADDRESS_H_ */ +#endif /* FSFW_STORAGEMANAGER_STOREADDRESS_H_ */ From 352ce13fb391d13b3b4ccfd94437e9b3a189bc03 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 14:55:17 +0200 Subject: [PATCH 383/653] removed line break --- ipc/messageQueueDefinitions.h | 1 - 1 file changed, 1 deletion(-) diff --git a/ipc/messageQueueDefinitions.h b/ipc/messageQueueDefinitions.h index b4f861b8..d250da8a 100644 --- a/ipc/messageQueueDefinitions.h +++ b/ipc/messageQueueDefinitions.h @@ -15,5 +15,4 @@ */ using MessageQueueId_t = uint32_t; - #endif /* FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ */ From 6a5268f5b0439ed1b368c311dd45b4e2fb7012d9 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 15:05:18 +0200 Subject: [PATCH 384/653] typo fix --- memory/AcceptsMemoryMessagesIF.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/memory/AcceptsMemoryMessagesIF.h b/memory/AcceptsMemoryMessagesIF.h index cf8aa5ec..7491f47d 100644 --- a/memory/AcceptsMemoryMessagesIF.h +++ b/memory/AcceptsMemoryMessagesIF.h @@ -11,4 +11,4 @@ public: }; -#endif /* AFSFW_MEMORY_ACCEPTSMEMORYMESSAGESIF_H_ */ +#endif /* FSFW_MEMORY_ACCEPTSMEMORYMESSAGESIF_H_ */ From a71528551ae4f821d029994d13000942e592a215 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 15:10:08 +0200 Subject: [PATCH 385/653] include added --- tmtcservices/PusVerificationReport.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tmtcservices/PusVerificationReport.h b/tmtcservices/PusVerificationReport.h index b4739577..9dce95ac 100644 --- a/tmtcservices/PusVerificationReport.h +++ b/tmtcservices/PusVerificationReport.h @@ -1,9 +1,11 @@ -#ifndef PUSVERIFICATIONREPORT_H_ -#define PUSVERIFICATIONREPORT_H_ +#ifndef FSFW_TMTCSERVICES_PUSVERIFICATIONREPORT_H_ +#define FSFW_TMTCSERVICES_PUSVERIFICATIONREPORT_H_ + +#include "VerificationCodes.h" #include "../ipc/MessageQueueMessage.h" #include "../tmtcpacket/pus/TcPacketBase.h" -#include "VerificationCodes.h" +#include "../returnvalues/HasReturnvaluesIF.h" class PusVerificationMessage: public MessageQueueMessage { private: @@ -30,7 +32,7 @@ private: public: static const uint8_t VERIFICATION_MIN_SIZE = 6; PusVerificationMessage(); -// PusVerificationMessage( uint8_t set_report_id, TcPacketBase* current_packet, ReturnValue_t set_error_code = 0, uint8_t set_step = 0, uint32_t parameter1 = 0, uint32_t parameter2 = 0 ); + PusVerificationMessage(uint8_t set_report_id, uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, ReturnValue_t set_error_code = 0, uint8_t set_step = 0, @@ -74,4 +76,4 @@ public: uint8_t* getReport(); }; -#endif /* PUSVERIFICATIONREPORT_H_ */ +#endif /* FSFW_TMTCSERVICES_PUSVERIFICATIONREPORT_H_ */ From 6879045ef3866e5631e617b2400ce1e8ce381573 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 15:21:33 +0200 Subject: [PATCH 386/653] include fix --- ipc/MessageQueueIF.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipc/MessageQueueIF.h b/ipc/MessageQueueIF.h index 44b6f4c0..1c06521c 100644 --- a/ipc/MessageQueueIF.h +++ b/ipc/MessageQueueIF.h @@ -1,7 +1,7 @@ #ifndef FSFW_IPC_MESSAGEQUEUEIF_H_ #define FSFW_IPC_MESSAGEQUEUEIF_H_ -#include +#include "messageQueueDefinitions.h" #include "MessageQueueMessageIF.h" #include "../returnvalues/HasReturnvaluesIF.h" From 47c21cfc6c693614c1ed0627d94643d08aeeba0a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 15:22:38 +0200 Subject: [PATCH 387/653] include fix --- ipc/QueueFactory.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ipc/QueueFactory.h b/ipc/QueueFactory.h index 0310e534..9853d256 100644 --- a/ipc/QueueFactory.h +++ b/ipc/QueueFactory.h @@ -1,10 +1,10 @@ #ifndef FSFW_IPC_QUEUEFACTORY_H_ #define FSFW_IPC_QUEUEFACTORY_H_ - #include "MessageQueueIF.h" -#include "../ipc/MessageQueueMessage.h" -#include +#include "MessageQueueMessage.h" +#include + /** * Creates message queues. * This class is a "singleton" interface, i.e. it provides an From e71020d631c6875427aa590ed7c2e68a77b50af1 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 29 Sep 2020 15:24:29 +0200 Subject: [PATCH 388/653] Removed comments and added include --- tmtcservices/PusVerificationReport.cpp | 25 ------------------------- tmtcservices/PusVerificationReport.h | 2 ++ 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/tmtcservices/PusVerificationReport.cpp b/tmtcservices/PusVerificationReport.cpp index b047576b..bfad9ec5 100644 --- a/tmtcservices/PusVerificationReport.cpp +++ b/tmtcservices/PusVerificationReport.cpp @@ -4,31 +4,6 @@ PusVerificationMessage::PusVerificationMessage() { } -//PusVerificationMessage::PusVerificationMessage(uint8_t set_report_id, -// TcPacketBase* current_packet, ReturnValue_t set_error_code, -// uint8_t set_step, uint32_t parameter1, uint32_t parameter2) { -// uint8_t ackFlags = current_packet->getAcknowledgeFlags(); -// uint16_t tcPacketId = current_packet->getPacketId(); -// uint16_t tcSequenceControl = current_packet->getPacketSequenceControl(); -// uint8_t* data = this->getBuffer(); -// data[messageSize] = set_report_id; -// messageSize += sizeof(set_report_id); -// data[messageSize] = ackFlags; -// messageSize += sizeof(ackFlags); -// memcpy(&data[messageSize], &tcPacketId, sizeof(tcPacketId)); -// messageSize += sizeof(tcPacketId); -// memcpy(&data[messageSize], &tcSequenceControl, sizeof(tcSequenceControl)); -// messageSize += sizeof(tcSequenceControl); -// data[messageSize] = set_step; -// messageSize += sizeof(set_step); -// memcpy(&data[messageSize], &set_error_code, sizeof(set_error_code)); -// messageSize += sizeof(set_error_code); -// memcpy(&data[messageSize], ¶meter1, sizeof(parameter1)); -// messageSize += sizeof(parameter1); -// memcpy(&data[messageSize], ¶meter2, sizeof(parameter2)); -// messageSize += sizeof(parameter2); -//} - PusVerificationMessage::PusVerificationMessage(uint8_t set_report_id, uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, ReturnValue_t set_error_code, uint8_t set_step, uint32_t parameter1, diff --git a/tmtcservices/PusVerificationReport.h b/tmtcservices/PusVerificationReport.h index 9dce95ac..88954cfd 100644 --- a/tmtcservices/PusVerificationReport.h +++ b/tmtcservices/PusVerificationReport.h @@ -7,6 +7,8 @@ #include "../tmtcpacket/pus/TcPacketBase.h" #include "../returnvalues/HasReturnvaluesIF.h" +#include + class PusVerificationMessage: public MessageQueueMessage { private: struct verifciationMessageContent { From 72f924813d337bc60d415b2a641afdf132a57f80 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 15:36:54 +0200 Subject: [PATCH 389/653] .mk fix --- fsfw.mk | 1 - 1 file changed, 1 deletion(-) diff --git a/fsfw.mk b/fsfw.mk index bf95727c..3639717b 100644 --- a/fsfw.mk +++ b/fsfw.mk @@ -9,7 +9,6 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/controller/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/coordinates/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datalinklayer/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapool/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/housekeeping/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/devicehandlers/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/eventmatching/*.cpp) From 1bdccedabe963f93d14fe58ae162bccc7f26360b Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 29 Sep 2020 15:39:24 +0200 Subject: [PATCH 390/653] Fixes #86 --- pus/CService200ModeCommanding.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/pus/CService200ModeCommanding.cpp b/pus/CService200ModeCommanding.cpp index 32f7e5a7..c63b47a6 100644 --- a/pus/CService200ModeCommanding.cpp +++ b/pus/CService200ModeCommanding.cpp @@ -107,13 +107,23 @@ ReturnValue_t CService200ModeCommanding::prepareWrongModeReply( const CommandMessage *reply, object_id_t objectId) { ModePacket wrongModeReply(objectId, ModeMessage::getMode(reply), ModeMessage::getSubmode(reply)); - return sendTmPacket(Subservice::REPLY_WRONG_MODE_REPLY, &wrongModeReply); + ReturnValue_t result = sendTmPacket(Subservice::REPLY_WRONG_MODE_REPLY, &wrongModeReply); + if(result == RETURN_OK){ + // We want to produce an error here in any case because the mode was not correct + return RETURN_FAILED; + } + return result; } ReturnValue_t CService200ModeCommanding::prepareCantReachModeReply( const CommandMessage *reply, object_id_t objectId) { CantReachModePacket cantReachModePacket(objectId, ModeMessage::getCantReachModeReason(reply)); - return sendTmPacket(Subservice::REPLY_CANT_REACH_MODE, + ReturnValue_t result = sendTmPacket(Subservice::REPLY_CANT_REACH_MODE, &cantReachModePacket); + if(result == RETURN_OK){ + // We want to produce an error here in any case because the mode was not reached + return RETURN_FAILED; + } + return result; } From 17d5de15c990be42ad98da412059d7588ded15bd Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 16:10:35 +0200 Subject: [PATCH 391/653] slight changes ,size t replacement --- container/ArrayList.h | 218 +++++++++++++++++++++--------------------- 1 file changed, 107 insertions(+), 111 deletions(-) diff --git a/container/ArrayList.h b/container/ArrayList.h index 19454777..f347da8e 100644 --- a/container/ArrayList.h +++ b/container/ArrayList.h @@ -1,15 +1,15 @@ -#ifndef ARRAYLIST_H_ -#define ARRAYLIST_H_ +#ifndef FSFW_CONTAINER_ARRAYLIST_H_ +#define FSFW_CONTAINER_ARRAYLIST_H_ #include "../returnvalues/HasReturnvaluesIF.h" #include "../serialize/SerializeAdapter.h" #include "../serialize/SerializeIF.h" /** - * A List that stores its values in an array. - * - * The backend is an array that can be allocated by the class itself or supplied via ctor. - * + * @brief A List that stores its values in an array. + * @details + * The underlying storage is an array that can be allocated by the class + * itself or supplied via ctor. * * @ingroup container */ @@ -21,94 +21,8 @@ public: static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01); /** - * An Iterator to go trough an ArrayList - * - * It stores a pointer to an element and increments the - * pointer when incremented itself. - */ - class Iterator { - public: - /** - * Empty ctor, points to NULL - */ - Iterator() : - value(0) { - - } - - /** - * Initializes the Iterator to point to an element - * - * @param initialize - */ - Iterator(T *initialize) { - value = initialize; - } - - /** - * The current element the iterator points to - */ - T *value; - - Iterator& operator++() { - value++; - return *this; - } - - Iterator operator++(int) { - Iterator tmp(*this); - operator++(); - return tmp; - } - - Iterator& operator--() { - value--; - return *this; - } - - Iterator operator--(int) { - Iterator tmp(*this); - operator--(); - return tmp; - } - - T& operator*(){ - return *value; - } - - const T& operator*() const{ - return *value; - } - - T *operator->(){ - return value; - } - - const T *operator->() const{ - return value; - } - - //SHOULDDO this should be implemented as non-member - bool operator==(const typename ArrayList::Iterator& other) const{ - return (value == other.value); - } - - //SHOULDDO this should be implemented as non-member - bool operator!=(const typename ArrayList::Iterator& other) const { - return !(*this == other); - } - }; - - /** - * Number of Elements stored in this List - */ - count_t size; - - /** - * This is the allocating constructor; - * + * This is the allocating constructor. * It allocates an array of the specified size. - * * @param maxSize */ ArrayList(count_t maxSize) : @@ -119,7 +33,8 @@ public: /** * This is the non-allocating constructor * - * It expects a pointer to an array of a certain size and initializes itself to it. + * It expects a pointer to an array of a certain size and initializes + * itself to it. * * @param storage the array to use as backend * @param maxSize size of storage @@ -129,6 +44,20 @@ public: size(size), entries(storage), maxSize_(maxSize), allocated(false) { } + /** + * Copying is forbiden by declaring copy ctor and copy assignment deleted + * It is too ambigous in this case. + * (Allocate a new backend? Use the same? What to do in an modifying call?) + */ + ArrayList(const ArrayList& other) = delete; + const ArrayList& operator=(const ArrayList& other) = delete; + + /** + * Number of Elements stored in this List + */ + count_t size; + + /** * Destructor, if the allocating constructor was used, it deletes the array. */ @@ -138,6 +67,85 @@ public: } } + /** + * An Iterator to go trough an ArrayList + * + * It stores a pointer to an element and increments the + * pointer when incremented itself. + */ + class Iterator { + public: + /** + * Empty ctor, points to NULL + */ + Iterator(): value(0) {} + + /** + * Initializes the Iterator to point to an element + * + * @param initialize + */ + Iterator(T *initialize) { + value = initialize; + } + + /** + * The current element the iterator points to + */ + T *value; + + Iterator& operator++() { + value++; + return *this; + } + + Iterator operator++(int) { + Iterator tmp(*this); + operator++(); + return tmp; + } + + Iterator& operator--() { + value--; + return *this; + } + + Iterator operator--(int) { + Iterator tmp(*this); + operator--(); + return tmp; + } + + T& operator*() { + return *value; + } + + const T& operator*() const { + return *value; + } + + T *operator->() { + return value; + } + + const T *operator->() const { + return value; + } + + + //SHOULDDO this should be implemented as non-member + bool operator==(const typename + ArrayList::Iterator& other) const { + return (value == other.value); + } + + //SHOULDDO this should be implemented as non-member + bool operator!=(const typename + ArrayList::Iterator& other) const { + return !(*this == other); + } + }; + /** * Iterator pointing to the first stored elmement * @@ -191,7 +199,7 @@ public: * * @return maximum number of elements */ - uint32_t maxSize() const { + size_t maxSize() const { return this->maxSize_; } @@ -226,19 +234,7 @@ public: count_t remaining() { return (maxSize_ - size); } -private: - /** - * This is the copy constructor - * - * It is private, as copying is too ambigous in this case. (Allocate a new backend? Use the same? - * What to do in an modifying call?) - * - * @param other - */ - ArrayList(const ArrayList& other) : - size(other.size), entries(other.entries), maxSize_(other.maxSize_), allocated( - false) { - } + protected: /** * pointer to the array in which the entries are stored @@ -247,12 +243,12 @@ protected: /** * remembering the maximum size */ - uint32_t maxSize_; + size_t maxSize_; /** * true if the array was allocated and needs to be deleted in the destructor. */ bool allocated; - }; -#endif /* ARRAYLIST_H_ */ + +#endif /* FSFW_CONTAINER_ARRAYLIST_H_ */ From 4eef7bfc0133f56021914028818107cbe0e41b64 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 16:12:43 +0200 Subject: [PATCH 392/653] changes taken over --- container/ArrayList.h | 144 +++++++++++++++++++++--------------------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/container/ArrayList.h b/container/ArrayList.h index f347da8e..426e02b3 100644 --- a/container/ArrayList.h +++ b/container/ArrayList.h @@ -26,7 +26,7 @@ public: * @param maxSize */ ArrayList(count_t maxSize) : - size(0), maxSize_(maxSize), allocated(true) { + size(0), maxSize_(maxSize), allocated(true) { entries = new T[maxSize]; } @@ -41,14 +41,14 @@ public: * @param size size of data already present in storage */ ArrayList(T *storage, count_t maxSize, count_t size = 0) : - size(size), entries(storage), maxSize_(maxSize), allocated(false) { + size(size), entries(storage), maxSize_(maxSize), allocated(false) { } - /** - * Copying is forbiden by declaring copy ctor and copy assignment deleted - * It is too ambigous in this case. - * (Allocate a new backend? Use the same? What to do in an modifying call?) - */ + /** + * Copying is forbiden by declaring copy ctor and copy assignment deleted + * It is too ambigous in this case. + * (Allocate a new backend? Use the same? What to do in an modifying call?) + */ ArrayList(const ArrayList& other) = delete; const ArrayList& operator=(const ArrayList& other) = delete; @@ -67,84 +67,84 @@ public: } } - /** - * An Iterator to go trough an ArrayList - * - * It stores a pointer to an element and increments the - * pointer when incremented itself. - */ - class Iterator { - public: - /** - * Empty ctor, points to NULL - */ - Iterator(): value(0) {} + /** + * An Iterator to go trough an ArrayList + * + * It stores a pointer to an element and increments the + * pointer when incremented itself. + */ + class Iterator { + public: + /** + * Empty ctor, points to NULL + */ + Iterator(): value(0) {} - /** - * Initializes the Iterator to point to an element - * - * @param initialize - */ - Iterator(T *initialize) { - value = initialize; - } + /** + * Initializes the Iterator to point to an element + * + * @param initialize + */ + Iterator(T *initialize) { + value = initialize; + } - /** - * The current element the iterator points to - */ - T *value; + /** + * The current element the iterator points to + */ + T *value; - Iterator& operator++() { - value++; - return *this; - } + Iterator& operator++() { + value++; + return *this; + } - Iterator operator++(int) { - Iterator tmp(*this); - operator++(); - return tmp; - } + Iterator operator++(int) { + Iterator tmp(*this); + operator++(); + return tmp; + } - Iterator& operator--() { - value--; - return *this; - } + Iterator& operator--() { + value--; + return *this; + } - Iterator operator--(int) { - Iterator tmp(*this); - operator--(); - return tmp; - } + Iterator operator--(int) { + Iterator tmp(*this); + operator--(); + return tmp; + } - T& operator*() { - return *value; - } + T& operator*() { + return *value; + } - const T& operator*() const { - return *value; - } + const T& operator*() const { + return *value; + } - T *operator->() { - return value; - } + T *operator->() { + return value; + } - const T *operator->() const { - return value; - } + const T *operator->() const { + return value; + } - //SHOULDDO this should be implemented as non-member - bool operator==(const typename - ArrayList::Iterator& other) const { - return (value == other.value); - } + //SHOULDDO this should be implemented as non-member + bool operator==(const typename + ArrayList::Iterator& other) const { + return (value == other.value); + } - //SHOULDDO this should be implemented as non-member - bool operator!=(const typename - ArrayList::Iterator& other) const { - return !(*this == other); - } - }; + //SHOULDDO this should be implemented as non-member + bool operator!=(const typename + ArrayList::Iterator& other) const { + return !(*this == other); + } + }; /** * Iterator pointing to the first stored elmement From 4fce0377a951b1a2b27a128b09baf949f6b7415d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 17:28:02 +0200 Subject: [PATCH 393/653] missing include for linux --- osal/linux/MessageQueue.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osal/linux/MessageQueue.cpp b/osal/linux/MessageQueue.cpp index e5c61cae..f2e5a5ec 100644 --- a/osal/linux/MessageQueue.cpp +++ b/osal/linux/MessageQueue.cpp @@ -1,14 +1,16 @@ -#include "../../serviceinterface/ServiceInterfaceStream.h" #include "MessageQueue.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../objectmanager/ObjectManagerIF.h" #include - #include /* For O_* constants */ #include /* For mode constants */ #include #include + + MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize): id(MessageQueueIF::NO_QUEUE),lastPartner(MessageQueueIF::NO_QUEUE), defaultDestination(MessageQueueIF::NO_QUEUE) { From f73f798a4d606e2fe66d592494ad52e0ba4e50a3 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 17:28:37 +0200 Subject: [PATCH 394/653] lines removed --- osal/linux/MessageQueue.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/osal/linux/MessageQueue.cpp b/osal/linux/MessageQueue.cpp index f2e5a5ec..cb5ffd04 100644 --- a/osal/linux/MessageQueue.cpp +++ b/osal/linux/MessageQueue.cpp @@ -9,8 +9,6 @@ #include - - MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize): id(MessageQueueIF::NO_QUEUE),lastPartner(MessageQueueIF::NO_QUEUE), defaultDestination(MessageQueueIF::NO_QUEUE) { From 303fcec9f656308ef4b50fb1da9f1dcbc2f13192 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 29 Sep 2020 17:49:04 +0200 Subject: [PATCH 395/653] Added a missing include --- osal/linux/MessageQueue.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/osal/linux/MessageQueue.cpp b/osal/linux/MessageQueue.cpp index e5c61cae..76f66170 100644 --- a/osal/linux/MessageQueue.cpp +++ b/osal/linux/MessageQueue.cpp @@ -1,5 +1,6 @@ #include "../../serviceinterface/ServiceInterfaceStream.h" #include "MessageQueue.h" +#include "../../objectmanager/ObjectManagerIF.h" #include From 6c0bb23ed6f24e84a52a2b37c3bf082a39b0c43d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 17:51:16 +0200 Subject: [PATCH 396/653] non member bool operator --- container/ArrayList.h | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/container/ArrayList.h b/container/ArrayList.h index 426e02b3..6bd5c1d5 100644 --- a/container/ArrayList.h +++ b/container/ArrayList.h @@ -131,21 +131,18 @@ public: const T *operator->() const { return value; } - - - //SHOULDDO this should be implemented as non-member - bool operator==(const typename - ArrayList::Iterator& other) const { - return (value == other.value); - } - - //SHOULDDO this should be implemented as non-member - bool operator!=(const typename - ArrayList::Iterator& other) const { - return !(*this == other); - } }; + friend bool operator==(const ArrayList::Iterator& lhs, + const ArrayList::Iterator& rhs) { + return (lhs.value == rhs.value); + } + + friend bool operator!=(const ArrayList::Iterator& lhs, + const ArrayList::Iterator& rhs) { + return not (lhs.value == rhs.value); + } + /** * Iterator pointing to the first stored elmement * @@ -251,4 +248,6 @@ protected: bool allocated; }; + + #endif /* FSFW_CONTAINER_ARRAYLIST_H_ */ From 5fc583117d1291976281ec40e448376257a94ba8 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 30 Sep 2020 10:55:34 +0200 Subject: [PATCH 397/653] Typo in FixedOrderedMultimap --- container/FixedOrderedMultimap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index c5fd2184..717575d7 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -98,7 +98,7 @@ public: } ReturnValue_t insert(std::pair pair) { - return insert(pair.fist, pair.second); + return insert(pair.first, pair.second); } ReturnValue_t exists(key_t key) const { From ecc4bdf11a2144f37e20631c17f3d58132499398 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 30 Sep 2020 12:50:52 +0200 Subject: [PATCH 398/653] Added a compile time check for MAX_SIZE Compiler may warn if MAX_SIZE value overflows by itself but this checks gives a more verbose warning --- container/FixedArrayList.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/container/FixedArrayList.h b/container/FixedArrayList.h index 42b59177..505097c9 100644 --- a/container/FixedArrayList.h +++ b/container/FixedArrayList.h @@ -2,11 +2,13 @@ #define FIXEDARRAYLIST_H_ #include "ArrayList.h" +#include /** * \ingroup container */ -template +template class FixedArrayList: public ArrayList { + static_assert(MAX_SIZE <= (pow(2,sizeof(count_t)*8)-1), "count_t is not large enough to hold MAX_SIZE"); private: T data[MAX_SIZE]; public: From 8d8e918aeb299ceb1b1279a93a289c37419cf325 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 30 Sep 2020 13:05:55 +0200 Subject: [PATCH 399/653] Fixed copying of FixedArrayList --- container/FixedArrayList.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/container/FixedArrayList.h b/container/FixedArrayList.h index 505097c9..e9e127cf 100644 --- a/container/FixedArrayList.h +++ b/container/FixedArrayList.h @@ -20,11 +20,13 @@ public: ArrayList(data, MAX_SIZE) { memcpy(this->data, other.data, sizeof(this->data)); this->entries = data; + this->size = other.size; } FixedArrayList& operator=(FixedArrayList other) { memcpy(this->data, other.data, sizeof(this->data)); this->entries = data; + this->size = other.size; return *this; } From aeeef53508627aa802d14ed9b45a93689171cac6 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 30 Sep 2020 14:34:02 +0200 Subject: [PATCH 400/653] Added Documentation to placement factory --- container/PlacementFactory.h | 42 +++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/container/PlacementFactory.h b/container/PlacementFactory.h index 05538478..529c7804 100644 --- a/container/PlacementFactory.h +++ b/container/PlacementFactory.h @@ -3,26 +3,62 @@ #include "../storagemanager/StorageManagerIF.h" #include - +/** + * The Placement Factory is used to create objects at runtime in a specific pool. + * In general this should be avoided and is should only be used if you know what you are doing. + * You are not allowed to use this container with a type that allocates memory internally like ArrayList. + * + * You have to check the returned pointer against nullptr! + * + * A backend of Type StorageManagerIF must be given as a place to store the new objects. + * Objects must be destroyed by the user with "destroy"! Otherwise the pool will not be cleared. + * + * + * + * The concept is based on the placement new operator. + * + * @warning Do not use with any Type that allocates memory internally! + * @ingroup container + */ class PlacementFactory { public: PlacementFactory(StorageManagerIF* backend) : dataBackend(backend) { } + + /*** + * Generates an object of type T in the backend storage. + * + * @warning Do not use with any Type that allocates memory internally! + * + * @tparam T Type of Object + * @param args Constructor Arguments to be passed + * @return A pointer to the new object or a nullptr in case of failure + */ template T* generate(Args&&... args) { store_address_t tempId; - uint8_t* pData = NULL; + uint8_t* pData = nullptr; ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T), &pData); if (result != HasReturnvaluesIF::RETURN_OK) { - return NULL; + return nullptr; } T* temp = new (pData) T(std::forward(args)...); return temp; } + /*** + * Function to destroy the object allocated with generate and free space in backend. + * This must be called by the user. + * + * @param thisElement Element to be destroyed + * @return RETURN_OK if the element was destroyed, different errors on failure + */ template ReturnValue_t destroy(T* thisElement) { + if (thisElement == nullptr){ + return HasReturnvaluesIF::RETURN_FAILED; + } //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); From 2f61bd0a0f5ac7f9252e9d18b60253fbf39e53f5 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 30 Sep 2020 14:38:46 +0200 Subject: [PATCH 401/653] A few typos and more docu --- container/PlacementFactory.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/container/PlacementFactory.h b/container/PlacementFactory.h index 529c7804..a0aebb7d 100644 --- a/container/PlacementFactory.h +++ b/container/PlacementFactory.h @@ -5,16 +5,16 @@ #include /** * The Placement Factory is used to create objects at runtime in a specific pool. - * In general this should be avoided and is should only be used if you know what you are doing. + * In general, this should be avoided and it should only be used if you know what you are doing. * You are not allowed to use this container with a type that allocates memory internally like ArrayList. * - * You have to check the returned pointer against nullptr! + * Also, you have to check the returned pointer in generate against nullptr! * * A backend of Type StorageManagerIF must be given as a place to store the new objects. + * Therefore ThreadSafety is only provided by your StorageManager Implementation. + * * Objects must be destroyed by the user with "destroy"! Otherwise the pool will not be cleared. * - * - * * The concept is based on the placement new operator. * * @warning Do not use with any Type that allocates memory internally! From 823bae1a2a993af3ff700c0d7eb4709c8176d87d Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 30 Sep 2020 16:06:17 +0200 Subject: [PATCH 402/653] Added null pointer checks for FIFO Base --- container/FIFOBase.tpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/container/FIFOBase.tpp b/container/FIFOBase.tpp index d54b3f8f..763004b6 100644 --- a/container/FIFOBase.tpp +++ b/container/FIFOBase.tpp @@ -26,6 +26,9 @@ inline ReturnValue_t FIFOBase::retrieve(T* value) { if (empty()) { return EMPTY; } else { + if (value == nullptr){ + return HasReturnvaluesIF::RETURN_FAILED; + } *value = values[readIndex]; readIndex = next(readIndex); --currentSize; @@ -38,6 +41,9 @@ inline ReturnValue_t FIFOBase::peek(T* value) { if(empty()) { return EMPTY; } else { + if (value == nullptr){ + return HasReturnvaluesIF::RETURN_FAILED; + } *value = values[readIndex]; return HasReturnvaluesIF::RETURN_OK; } From ab9858b0c78fa6283b7218e7c9339444b91a5c39 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 30 Sep 2020 16:15:48 +0200 Subject: [PATCH 403/653] Added comments --- container/FIFOBase.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/container/FIFOBase.h b/container/FIFOBase.h index b744706d..201d488d 100644 --- a/container/FIFOBase.h +++ b/container/FIFOBase.h @@ -19,24 +19,24 @@ public: /** * Insert value into FIFO * @param value - * @return + * @return RETURN_OK on success, FULL if full */ ReturnValue_t insert(T value); /** * Retrieve item from FIFO. This removes the item from the FIFO. - * @param value - * @return + * @param value Must point to a valid T + * @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed */ ReturnValue_t retrieve(T *value); /** * Retrieve item from FIFO without removing it from FIFO. - * @param value - * @return + * @param value Must point to a valid T + * @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed */ ReturnValue_t peek(T * value); /** * Remove item from FIFO. - * @return + * @return RETURN_OK on success, EMPTY if empty */ ReturnValue_t pop(); From fcabf93af33c61d989bf06555bf3a005e985ff7a Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 30 Sep 2020 16:27:18 +0200 Subject: [PATCH 404/653] Added a few comments --- container/FIFOBase.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/container/FIFOBase.h b/container/FIFOBase.h index 201d488d..edd66d37 100644 --- a/container/FIFOBase.h +++ b/container/FIFOBase.h @@ -40,11 +40,25 @@ public: */ ReturnValue_t pop(); + /*** + * Check if FIFO is empty + * @return True if empty, False if not + */ bool empty(); + /*** + * Check if FIFO is Full + * @return True if full, False if not + */ bool full(); + /*** + * Current used size (elements) used + * @return size_t in elements + */ size_t size(); - - + /*** + * Get maximal capacity of fifo + * @return size_t with max capacity of this fifo + */ size_t getMaxCapacity() const; protected: From a0098e8b17e42d43e64d7d9ef7a78f8cc66b137b Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 30 Sep 2020 18:57:30 +0200 Subject: [PATCH 405/653] non member comp operator for iterators --- container/FixedMap.h | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/container/FixedMap.h b/container/FixedMap.h index d1cc31ff..7a5220fa 100644 --- a/container/FixedMap.h +++ b/container/FixedMap.h @@ -7,14 +7,21 @@ #include /** + * @brief Map implementation for maps with a pre-defined size. + * @details + * Can be initialized with desired maximum size. + * Iterator is used to access pair and iterate through map entries. + * Complexity O(n). * @warning Iterators return a non-const key_t in the pair. * @warning A User is not allowed to change the key, otherwise the map is corrupted. * @ingroup container */ template class FixedMap: public SerializeIF { - static_assert (std::is_trivially_copyable::value or std::is_base_of::value, - "Types used in FixedMap must either be trivial copy-able or a derived Class from SerializeIF to be serialize-able"); + static_assert (std::is_trivially_copyable::value or + std::is_base_of::value, + "Types used in FixedMap must either be trivial copy-able or a " + "derived class from SerializeIF to be serialize-able"); public: static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP; static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01); @@ -54,6 +61,16 @@ public: } }; + friend bool operator==(const typename FixedMap::Iterator& lhs, + const typename FixedMap::Iterator& rhs) { + return (lhs.value == rhs.value); + } + + friend bool operator!=(const typename FixedMap::Iterator& lhs, + const typename FixedMap::Iterator& rhs) { + return not (lhs.value == rhs.value); + } + Iterator begin() const { return Iterator(&theMap[0]); } @@ -136,6 +153,24 @@ public: return HasReturnvaluesIF::RETURN_OK; } + bool empty() { + if(_size == 0) { + return true; + } + else { + return false; + } + } + + bool full() { + if(_size >= theMap.maxSize()) { + return true; + } + else { + return false; + } + } + void clear() { _size = 0; } From a14558ef1fd308ba23757916590af1376a663791 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 30 Sep 2020 20:25:02 +0200 Subject: [PATCH 406/653] Removed old test files --- container/RingBufferTest.cpp.ignore | 79 ------ container/listTest.cpp.ignore | 365 ---------------------------- 2 files changed, 444 deletions(-) delete mode 100644 container/RingBufferTest.cpp.ignore delete mode 100644 container/listTest.cpp.ignore diff --git a/container/RingBufferTest.cpp.ignore b/container/RingBufferTest.cpp.ignore deleted file mode 100644 index d660e29c..00000000 --- a/container/RingBufferTest.cpp.ignore +++ /dev/null @@ -1,79 +0,0 @@ - -#include -#include "SimpleRingBuffer.h" - - -int main() { - using namespace std; - SimpleRingBuffer buffer(64, false); - uint8_t data[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}; - ReturnValue_t result = buffer.writeData(data, 8); - if (result != HasReturnvaluesIF::RETURN_OK) { - cout << "writeData failed." << endl; - } - result = buffer.writeData(data, 8); - if (result != HasReturnvaluesIF::RETURN_OK) { - cout << "writeData failed." << endl; - } - uint8_t buffer2[47] = {0}; - for (uint8_t count = 0; count - -/* - -class Packet: public SinglyLinkedList { -public: - SinglyLinkedList::Element element1; - SinglyLinkedList::Element element2; - - Packet() { - this->start = &element1; - element1.next = &element2; - } -}; - -class Packet2: public SinglyLinkedList { -public: - SinglyLinkedList::Element element1; - SinglyLinkedList::Element, 2>> element2; - SinglyLinkedList::Element element3; - - Packet2() { - this->start = &element1; - element1.next = &element2; - element2.next = &element3; - } -}; - -class Packet3: public SinglyLinkedList { -public: - SinglyLinkedList::TypedElement element1; - SinglyLinkedList::TypedElement element2; - - Packet3() { - this->start = &element1; - element1.next = &element2; - } -}; - -void arrayList() { - puts("** Array List **"); - FixedArrayList list; - FixedArrayList list2; - - list.size = 2; - - list[0] = 0xcafecafe; - - list[1] = 0x12345678; - - uint8_t buffer[100]; - uint8_t *pointer = buffer; - uint32_t size = 0; - uint32_t maxSize = 100; - uint32_t i; - int32_t size2; - - printf("printsize: %i\n", list.getPrintSize()); - - list.print(&pointer, &size, 100, true); - - printf("buffer(%i):", size); - for (i = 0; i < size; ++i) { - printf("%02x", buffer[i]); - } - printf("\n"); - - pointer = buffer; - - size2 = size; - - printf("list2 read: %x\n", list2.read(&pointer, &size2, true)); - - printf("list2(%i):", list2.size); - for (ArrayList::Iterator iter = list2.begin(); - iter != list2.end(); iter++) { - printf("0x%04x ", *iter); - } - printf("\n"); - - HybridIterator hiter(list.begin(),list.end()); - - printf("hybrid1: 0x%04x\n", *(hiter++)); - printf("hybrid2: 0x%04x\n", *hiter); - -} - -void allocatingList() { - puts("** Allocating List **"); - ArrayList myList(3), myList2(2); - myList[0] = 0xab; - myList[1] = 0xcd; - myList.size = 2; - - uint8_t buffer[100]; - uint8_t *pointer = buffer; - uint32_t size = 0; - uint32_t maxSize = 100; - uint32_t i; - int32_t size2; - - myList.print(&pointer, &size, 100, true); - - pointer = buffer; - size2 = size; - - printf("Read %x\n", myList2.read(&pointer, &size2, true)); - - printf("%x,%x\n", myList2[0], myList2[1]); - -} - -void linkedList() { - puts("** Linked List **"); - uint8_t buffer[100]; - uint8_t *pointer = buffer; - uint32_t size = 0; - uint32_t maxSize = 100; - uint32_t i; - int32_t size2; - - Packet myPacket; - myPacket.element1.entry = 0x12345678; - myPacket.element2.entry = 0x9abcdef0; - - pointer = buffer; - size = 0; - ReturnValue_t result = myPacket.print(&pointer, &size, 100, true); - - printf("result %02x\n", result); - - printf("printsize: %i\n", myPacket.getPrintSize()); - - printf("buffer(%i):", size); - for (i = 0; i < size; ++i) { - printf("%02x", buffer[i]); - } - printf("\n"); - - Packet3 myPacket3; - - myPacket3.element1.entry = 0x12345678; - myPacket3.element2.entry = 0xabcdeff; - - SinglyLinkedList::TypedIterator titer(&myPacket3.element1); - - printf("0x%04x\n", *titer); - - HybridIterator hiter(&myPacket3.element1); - - printf("hybrid1: 0x%04x\n", *hiter); - hiter++; - printf("hybrid2: 0x%04x\n", *hiter); -} - -void complex() { - puts("** complex **"); - uint8_t buffer[100]; - uint8_t *pointer = buffer; - uint32_t size = 0; - uint32_t maxSize = 100; - uint32_t i; - int32_t size2 = size; - - Packet myPacket2; - - size2 = size; - pointer = buffer; - - myPacket2.read(&pointer, &size2, true); - - printf("packet: 0x%04x, 0x%04x\n", myPacket2.element1.entry, - myPacket2.element2.entry); - - buffer[0] = 0x12; - buffer[1] = 0x34; - buffer[2] = 0x56; - buffer[3] = 0x78; - buffer[4] = 0x2; - buffer[5] = 0x3; - buffer[6] = 0xab; - buffer[7] = 0xcd; - buffer[8] = 0xef; - buffer[9] = 0x2; - buffer[10] = 0x11; - buffer[11] = 0x22; - buffer[12] = 0xca; - buffer[13] = 0xfe; - buffer[14] = 0x5a; - buffer[15] = 0xfe; - - pointer = buffer; - size2 = 23; - - Packet2 p2; - - ReturnValue_t result = p2.read(&pointer, &size2, true); - printf("result is %02x\n", result); - - printf("%04x; %i: %i: %x %x %x; %i: %x %x;; %04x\n", p2.element1.entry, - p2.element2.entry.size, p2.element2.entry[0].size, - p2.element2.entry[0][0], p2.element2.entry[0][1], - p2.element2.entry[0][2], p2.element2.entry[1].size, - p2.element2.entry[1][0], p2.element2.entry[1][1], - p2.element3.entry); - -} -*/ -struct Test { - uint32_t a; - uint32_t b; -}; - -template -void printMap(FixedMap *map) { - typename FixedMap::Iterator iter; - printf("Map (%i): ", map->getSize()); - for (iter = map->begin(); iter != map->end(); ++iter) { - printf("%x:%08x,%08x ", iter.value->first, (*iter).a, (*iter).b); - } - printf("\n"); -} - -template -void map() { - puts("** Map **"); - typename FixedMap::Iterator iter; - ReturnValue_t result; - FixedMap myMap(5); - - printMap(&myMap); - - Test a; - a.a = 0x01234567; - a.b = 0xabcdef89; - - myMap.insert(1, a); - printMap(&myMap); - - a.a = 0; - - myMap.insert(2, a); - printMap(&myMap); - - printf("2 exists: %x\n", myMap.exists(0x02)); - - printf("ff exists: %x\n", myMap.exists(0xff)); - - a.a = 1; - printf("insert 0x2: %x\n", myMap.insert(2, a)); - - result = myMap.insert(0xff, a); - a.a = 0x44; - result = myMap.insert(0xab, a); - result = myMap.insert(0xa, a); - - printMap(&myMap); - - printf("insert 0x5: %x\n", myMap.insert(5, a)); - - printf("erase 0xfe: %x\n", myMap.erase(0xfe)); - - printf("erase 0x2: %x\n", myMap.erase(0x2)); - - printMap(&myMap); - - printf("erase 0xab: %x\n", myMap.erase(0xab)); - printMap(&myMap); - - printf("insert 0x5: %x\n", myMap.insert(5, a)); - printMap(&myMap); - - iter = myMap.begin(); - ++iter; - ++iter; - ++iter; - - printf("iter: %i: %x,%x\n",iter.value->first, iter->a, iter->b); - - myMap.erase(&iter); - - printf("iter: %i: %x,%x\n",iter.value->first, iter->a, iter->b); - printMap(&myMap); - -} - -/* -void mapPrint() { - puts("** Map Print **"); - FixedMap myMap(5); - Packet2 myPacket; - myPacket.element1.entry = 0x12345678; - - myPacket.element2.entry[0][0] = 0xab; - myPacket.element2.entry[0][1] = 0xcd; - myPacket.element2.entry[0].size = 2; - myPacket.element2.entry.size = 1; - - myPacket.element3.entry = 0xabcdef90; - - myMap.insert(0x1234, myPacket); - - uint8_t buffer[100]; - uint32_t size = 0, i; - uint8_t *pointer = buffer; - - printf("printsize: %i\n", myMap.getPrintSize()); - - SerializeAdapter>::print(&myMap, &pointer, - &size, 100, false); - - printf("buffer(%i):", size); - for (i = 0; i < size; ++i) { - printf("%02x", buffer[i]); - } - printf("\n"); - - int32_t size2 = size; - pointer = buffer; - - FixedMap myMap2(5); - - ReturnValue_t result = SerializeAdapter>::read( - &myMap2, &pointer, &size2, false); - - Packet2 *myPacket2 = myMap2.find(0x1234); - - printf("Map (%i): Packet2: %x, Array (%i): Array (%i): %x, %x; %x\n", - myMap2.getSize(), myPacket2->element1.entry, - myPacket2->element2.entry.size, myPacket2->element2.entry[0].size, - myPacket2->element2.entry[0][0], myPacket2->element2.entry[0][1], - myPacket2->element3.entry); - -} - -void empty() { - puts("** Empty **"); - ArrayList list(0); - printf("%p %p\n", list.front(), list.back()); -} -*/ - -int main(void) { - -// arrayList(); -// linkedList(); -// allocatingList(); -// complex(); - - map(); -// -// mapPrint(); - -// empty(); - - - - return 0; -} From adf528fce91412c43daf349c02cee9710bf54363 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 1 Oct 2020 11:01:52 +0200 Subject: [PATCH 407/653] DH IF and DH message form improved --- devicehandlers/DeviceHandlerIF.h | 20 +++++-- devicehandlers/DeviceHandlerMessage.cpp | 19 +----- devicehandlers/DeviceHandlerMessage.h | 78 ++++++++++--------------- 3 files changed, 48 insertions(+), 69 deletions(-) diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index 52a3be4d..9c8eb098 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -1,12 +1,19 @@ -#ifndef DEVICEHANDLERIF_H_ -#define DEVICEHANDLERIF_H_ +#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ +#define FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ + +#include "DeviceHandlerMessage.h" #include "../action/HasActionsIF.h" -#include "DeviceHandlerMessage.h" #include "../events/Event.h" #include "../modes/HasModesIF.h" #include "../ipc/MessageQueueSenderIF.h" +/** + * This is used to uniquely identify commands that are sent to a device + * The values are defined in the device-specific implementations + */ +using DeviceCommandId_t = uint32_t; + /** * @brief This is the Interface used to communicate with a device handler. * @details Includes all expected return values, events and modes. @@ -15,6 +22,7 @@ class DeviceHandlerIF { public: + static const uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20; static const uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10; @@ -47,6 +55,8 @@ public: //! 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. + //! It is possible to set the mode to _MODE_SHUT_DOWN to use the to off + //! transition if available. static const Mode_t _MODE_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6; //! It is possible to set the mode to _MODE_TO_ON to use the to on //! transition if available. @@ -96,7 +106,7 @@ public: static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF; // Standard codes used when building commands. - static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If the command size is 0. Checked in DHB + static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If no command data was given when expected. static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1); //!< Command ID not in commandMap. Checked in DHB static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA2); //!< Command was already executed. Checked in DHB static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3); @@ -150,4 +160,4 @@ public: }; -#endif /* DEVICEHANDLERIF_H_ */ +#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ */ diff --git a/devicehandlers/DeviceHandlerMessage.cpp b/devicehandlers/DeviceHandlerMessage.cpp index 564fae21..cb9043db 100644 --- a/devicehandlers/DeviceHandlerMessage.cpp +++ b/devicehandlers/DeviceHandlerMessage.cpp @@ -1,10 +1,6 @@ -#include "../objectmanager/ObjectManagerIF.h" #include "DeviceHandlerMessage.h" #include "../objectmanager/ObjectManagerIF.h" -DeviceHandlerMessage::DeviceHandlerMessage() { -} - store_address_t DeviceHandlerMessage::getStoreAddress( const CommandMessage* message) { return store_address_t(message->getParameter2()); @@ -25,14 +21,6 @@ uint8_t DeviceHandlerMessage::getWiretappingMode( return message->getParameter(); } -//void DeviceHandlerMessage::setDeviceHandlerDirectCommandMessage( -// CommandMessage* message, DeviceCommandId_t deviceCommand, -// store_address_t commandParametersStoreId) { -// message->setCommand(CMD_DIRECT); -// message->setParameter(deviceCommand); -// message->setParameter2(commandParametersStoreId.raw); -//} - void DeviceHandlerMessage::setDeviceHandlerRawCommandMessage( CommandMessage* message, store_address_t rawPacketStoreId) { message->setCommand(CMD_RAW); @@ -47,7 +35,7 @@ void DeviceHandlerMessage::setDeviceHandlerWiretappingMessage( void DeviceHandlerMessage::setDeviceHandlerSwitchIoBoardMessage( CommandMessage* message, uint32_t ioBoardIdentifier) { - message->setCommand(CMD_SWITCH_IOBOARD); + message->setCommand(CMD_SWITCH_ADDRESS); message->setParameter(ioBoardIdentifier); } @@ -79,18 +67,17 @@ void DeviceHandlerMessage::setDeviceHandlerDirectCommandReply( void DeviceHandlerMessage::clear(CommandMessage* message) { switch (message->getCommand()) { case CMD_RAW: -// case CMD_DIRECT: case REPLY_RAW_COMMAND: case REPLY_RAW_REPLY: case REPLY_DIRECT_COMMAND_DATA: { StorageManagerIF *ipcStore = objectManager->get( objects::IPC_STORE); - if (ipcStore != NULL) { + if (ipcStore != nullptr) { ipcStore->deleteData(getStoreAddress(message)); } } /* NO BREAK falls through*/ - case CMD_SWITCH_IOBOARD: + case CMD_SWITCH_ADDRESS: case CMD_WIRETAPPING: message->setCommand(CommandMessage::CMD_NONE); message->setParameter(0); diff --git a/devicehandlers/DeviceHandlerMessage.h b/devicehandlers/DeviceHandlerMessage.h index 8d1c94f4..e5da01c8 100644 --- a/devicehandlers/DeviceHandlerMessage.h +++ b/devicehandlers/DeviceHandlerMessage.h @@ -1,69 +1,56 @@ -#ifndef DEVICEHANDLERMESSAGE_H_ -#define DEVICEHANDLERMESSAGE_H_ +#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ +#define FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ #include "../action/ActionMessage.h" #include "../ipc/CommandMessage.h" #include "../objectmanager/SystemObjectIF.h" #include "../storagemanager/StorageManagerIF.h" -//SHOULDDO: 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 - * - * The values are defined in the device-specific implementations - */ -typedef uint32_t DeviceCommandId_t; - -/** - * The DeviceHandlerMessage is used to send Commands to a DeviceHandlerIF + * @brief The DeviceHandlerMessage is used to send commands to classes + * implementing DeviceHandlerIF */ class DeviceHandlerMessage { -private: - DeviceHandlerMessage(); public: + /** + * Instantiation forbidden. Instead, use static functions to operate + * on messages. + */ + DeviceHandlerMessage() = delete; + virtual ~DeviceHandlerMessage() {} /** * These are the commands that can be sent to a DeviceHandlerBase */ static const uint8_t MESSAGE_ID = messagetypes::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 - static const Command_t CMD_WIRETAPPING = MAKE_COMMAND_ID( 4 ); //!< (De)Activates the monitoring of all raw traffic in DeviceHandlers, setParameter is 0 to deactivate, 1 to activate + //! Sends a raw command, setParameter is a storeId containing the + //! raw packet to send + static const Command_t CMD_RAW = MAKE_COMMAND_ID(1); + //! Requests a IO-Board switch, setParameter() is the IO-Board identifier + static const Command_t CMD_SWITCH_ADDRESS = MAKE_COMMAND_ID(3); + //! (De)Activates the monitoring of all raw traffic in DeviceHandlers, + //! setParameter is 0 to deactivate, 1 to activate + static const Command_t CMD_WIRETAPPING = MAKE_COMMAND_ID(4); - /*static const Command_t REPLY_SWITCHED_IOBOARD = MAKE_COMMAND_ID(1 );//!< Reply to a @c CMD_SWITCH_IOBOARD, indicates switch was successful, getParameter() contains the board switched to (0: nominal, 1: redundant) - static const Command_t REPLY_CANT_SWITCH_IOBOARD = MAKE_COMMAND_ID( 2); //!< Reply to a @c CMD_SWITCH_IOBOARD, indicating the switch could not be performed, getParameter() contains the error message - static const Command_t REPLY_WIRETAPPING = MAKE_COMMAND_ID( 3); //!< Reply to a @c CMD_WIRETAPPING, getParameter() is the current state, 1 enabled, 0 disabled - - static const Command_t REPLY_COMMAND_WAS_SENT = MAKE_COMMAND_ID(4 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates the command was successfully sent to the device, getParameter() contains the ::DeviceCommandId_t - static const Command_t REPLY_COMMAND_NOT_SUPPORTED = MAKE_COMMAND_ID(5 );//!< Reply to a @c CMD_DIRECT, the requested ::DeviceCommand_t is not supported, getParameter() contains the requested ::DeviceCommand_t, getParameter2() contains the ::DeviceCommandId_t - static const Command_t REPLY_COMMAND_WAS_NOT_SENT = MAKE_COMMAND_ID(6 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates the command was not sent, getParameter contains the RMAP Return code (@see rmap.h), getParameter2() contains the ::DeviceCommandId_t - - static const Command_t REPLY_COMMAND_ALREADY_SENT = MAKE_COMMAND_ID(7 );//!< Reply to a @c CMD_DIRECT, the requested ::DeviceCommand_t has already been sent to the device and not ye been answered - static const Command_t REPLY_WRONG_MODE_FOR_CMD = MAKE_COMMAND_ID(8 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates that the requested command can not be sent in the curent mode, getParameter() contains the DeviceHandlerCommand_t - static const Command_t REPLY_NO_DATA = MAKE_COMMAND_ID(9 ); //!< Reply to a CMD_RAW or @c CMD_DIRECT, indicates that the ::store_id_t was invalid, getParameter() contains the ::DeviceCommandId_t, getPrameter2() contains the error code - */ - static const Command_t REPLY_DIRECT_COMMAND_SENT = ActionMessage::STEP_SUCCESS; //!< Signals that a direct command was sent - static const Command_t REPLY_RAW_COMMAND = MAKE_COMMAND_ID(0x11 ); //!< Contains a raw command sent to the Device - static const Command_t REPLY_RAW_REPLY = MAKE_COMMAND_ID( 0x12); //!< Contains a raw reply from the Device, getParameter() is the ObjcetId of the sender, getParameter2() is a ::store_id_t containing the raw packet received + //! Signals that a direct command was sent + static const Command_t REPLY_DIRECT_COMMAND_SENT = ActionMessage::STEP_SUCCESS; + //! Contains a raw command sent to the Device + static const Command_t REPLY_RAW_COMMAND = MAKE_COMMAND_ID(0x11); + //! Contains a raw reply from the Device, getParameter() is the ObjcetId + //! of the sender, getParameter2() is a ::store_id_t containing the + //! raw packet received + static const Command_t REPLY_RAW_REPLY = MAKE_COMMAND_ID(0x12); static const Command_t REPLY_DIRECT_COMMAND_DATA = ActionMessage::DATA_REPLY; - /** - * Default Destructor - */ - virtual ~DeviceHandlerMessage() { - } - static store_address_t getStoreAddress(const CommandMessage* message); static uint32_t getDeviceCommandId(const CommandMessage* message); static object_id_t getDeviceObjectId(const CommandMessage *message); static object_id_t getIoBoardObjectId(const CommandMessage* message); static uint8_t getWiretappingMode(const CommandMessage* message); -// static void setDeviceHandlerDirectCommandMessage(CommandMessage* message, -// DeviceCommandId_t deviceCommand, -// store_address_t commandParametersStoreId); - static void setDeviceHandlerDirectCommandReply(CommandMessage* message, object_id_t deviceObjectid, store_address_t commandParametersStoreId); @@ -75,11 +62,6 @@ public: object_id_t deviceObjectid, store_address_t rawPacketStoreId, bool isCommand); -// static void setDeviceHandlerMessage(CommandMessage* message, -// Command_t command, DeviceCommandId_t deviceCommand, -// store_address_t commandParametersStoreId); -// static void setDeviceHandlerMessage(CommandMessage* message, -// Command_t command, store_address_t rawPacketStoreId); static void setDeviceHandlerWiretappingMessage(CommandMessage* message, uint8_t wiretappingMode); static void setDeviceHandlerSwitchIoBoardMessage(CommandMessage* message, @@ -88,4 +70,4 @@ public: static void clear(CommandMessage* message); }; -#endif /* DEVICEHANDLERMESSAGE_H_ */ +#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ */ From 7c3f99ed2d4beba650722e596a48abb9edb837c4 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 1 Oct 2020 11:06:46 +0200 Subject: [PATCH 408/653] Revert "DH IF and DH message form improved" This reverts commit adf528fce91412c43daf349c02cee9710bf54363. --- devicehandlers/DeviceHandlerIF.h | 20 ++----- devicehandlers/DeviceHandlerMessage.cpp | 19 +++++- devicehandlers/DeviceHandlerMessage.h | 78 +++++++++++++++---------- 3 files changed, 69 insertions(+), 48 deletions(-) diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index 9c8eb098..52a3be4d 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -1,19 +1,12 @@ -#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ -#define FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ - -#include "DeviceHandlerMessage.h" +#ifndef DEVICEHANDLERIF_H_ +#define DEVICEHANDLERIF_H_ #include "../action/HasActionsIF.h" +#include "DeviceHandlerMessage.h" #include "../events/Event.h" #include "../modes/HasModesIF.h" #include "../ipc/MessageQueueSenderIF.h" -/** - * This is used to uniquely identify commands that are sent to a device - * The values are defined in the device-specific implementations - */ -using DeviceCommandId_t = uint32_t; - /** * @brief This is the Interface used to communicate with a device handler. * @details Includes all expected return values, events and modes. @@ -22,7 +15,6 @@ using DeviceCommandId_t = uint32_t; class DeviceHandlerIF { public: - static const uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20; static const uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10; @@ -55,8 +47,6 @@ public: //! 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. - //! It is possible to set the mode to _MODE_SHUT_DOWN to use the to off - //! transition if available. static const Mode_t _MODE_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6; //! It is possible to set the mode to _MODE_TO_ON to use the to on //! transition if available. @@ -106,7 +96,7 @@ public: static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF; // Standard codes used when building commands. - static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If no command data was given when expected. + static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If the command size is 0. Checked in DHB static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1); //!< Command ID not in commandMap. Checked in DHB static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA2); //!< Command was already executed. Checked in DHB static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3); @@ -160,4 +150,4 @@ public: }; -#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ */ +#endif /* DEVICEHANDLERIF_H_ */ diff --git a/devicehandlers/DeviceHandlerMessage.cpp b/devicehandlers/DeviceHandlerMessage.cpp index cb9043db..564fae21 100644 --- a/devicehandlers/DeviceHandlerMessage.cpp +++ b/devicehandlers/DeviceHandlerMessage.cpp @@ -1,6 +1,10 @@ +#include "../objectmanager/ObjectManagerIF.h" #include "DeviceHandlerMessage.h" #include "../objectmanager/ObjectManagerIF.h" +DeviceHandlerMessage::DeviceHandlerMessage() { +} + store_address_t DeviceHandlerMessage::getStoreAddress( const CommandMessage* message) { return store_address_t(message->getParameter2()); @@ -21,6 +25,14 @@ uint8_t DeviceHandlerMessage::getWiretappingMode( return message->getParameter(); } +//void DeviceHandlerMessage::setDeviceHandlerDirectCommandMessage( +// CommandMessage* message, DeviceCommandId_t deviceCommand, +// store_address_t commandParametersStoreId) { +// message->setCommand(CMD_DIRECT); +// message->setParameter(deviceCommand); +// message->setParameter2(commandParametersStoreId.raw); +//} + void DeviceHandlerMessage::setDeviceHandlerRawCommandMessage( CommandMessage* message, store_address_t rawPacketStoreId) { message->setCommand(CMD_RAW); @@ -35,7 +47,7 @@ void DeviceHandlerMessage::setDeviceHandlerWiretappingMessage( void DeviceHandlerMessage::setDeviceHandlerSwitchIoBoardMessage( CommandMessage* message, uint32_t ioBoardIdentifier) { - message->setCommand(CMD_SWITCH_ADDRESS); + message->setCommand(CMD_SWITCH_IOBOARD); message->setParameter(ioBoardIdentifier); } @@ -67,17 +79,18 @@ void DeviceHandlerMessage::setDeviceHandlerDirectCommandReply( void DeviceHandlerMessage::clear(CommandMessage* message) { switch (message->getCommand()) { case CMD_RAW: +// case CMD_DIRECT: case REPLY_RAW_COMMAND: case REPLY_RAW_REPLY: case REPLY_DIRECT_COMMAND_DATA: { StorageManagerIF *ipcStore = objectManager->get( objects::IPC_STORE); - if (ipcStore != nullptr) { + if (ipcStore != NULL) { ipcStore->deleteData(getStoreAddress(message)); } } /* NO BREAK falls through*/ - case CMD_SWITCH_ADDRESS: + case CMD_SWITCH_IOBOARD: case CMD_WIRETAPPING: message->setCommand(CommandMessage::CMD_NONE); message->setParameter(0); diff --git a/devicehandlers/DeviceHandlerMessage.h b/devicehandlers/DeviceHandlerMessage.h index e5da01c8..8d1c94f4 100644 --- a/devicehandlers/DeviceHandlerMessage.h +++ b/devicehandlers/DeviceHandlerMessage.h @@ -1,56 +1,69 @@ -#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ -#define FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ +#ifndef DEVICEHANDLERMESSAGE_H_ +#define DEVICEHANDLERMESSAGE_H_ #include "../action/ActionMessage.h" #include "../ipc/CommandMessage.h" #include "../objectmanager/SystemObjectIF.h" #include "../storagemanager/StorageManagerIF.h" -// SHOULDDO: 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. /** - * @brief The DeviceHandlerMessage is used to send commands to classes - * implementing DeviceHandlerIF + * This is used to uniquely identify commands that are sent to a device + * + * The values are defined in the device-specific implementations + */ +typedef uint32_t DeviceCommandId_t; + +/** + * The DeviceHandlerMessage is used to send Commands to a DeviceHandlerIF */ class DeviceHandlerMessage { +private: + DeviceHandlerMessage(); public: - /** - * Instantiation forbidden. Instead, use static functions to operate - * on messages. - */ - DeviceHandlerMessage() = delete; - virtual ~DeviceHandlerMessage() {} /** * These are the commands that can be sent to a DeviceHandlerBase */ static const uint8_t MESSAGE_ID = messagetypes::DEVICE_HANDLER_COMMAND; - //! Sends a raw command, setParameter is a storeId containing the - //! raw packet to send - static const Command_t CMD_RAW = MAKE_COMMAND_ID(1); - //! Requests a IO-Board switch, setParameter() is the IO-Board identifier - static const Command_t CMD_SWITCH_ADDRESS = MAKE_COMMAND_ID(3); - //! (De)Activates the monitoring of all raw traffic in DeviceHandlers, - //! setParameter is 0 to deactivate, 1 to activate - static const Command_t CMD_WIRETAPPING = MAKE_COMMAND_ID(4); + 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 + static const Command_t CMD_WIRETAPPING = MAKE_COMMAND_ID( 4 ); //!< (De)Activates the monitoring of all raw traffic in DeviceHandlers, setParameter is 0 to deactivate, 1 to activate - //! Signals that a direct command was sent - static const Command_t REPLY_DIRECT_COMMAND_SENT = ActionMessage::STEP_SUCCESS; - //! Contains a raw command sent to the Device - static const Command_t REPLY_RAW_COMMAND = MAKE_COMMAND_ID(0x11); - //! Contains a raw reply from the Device, getParameter() is the ObjcetId - //! of the sender, getParameter2() is a ::store_id_t containing the - //! raw packet received - static const Command_t REPLY_RAW_REPLY = MAKE_COMMAND_ID(0x12); + /*static const Command_t REPLY_SWITCHED_IOBOARD = MAKE_COMMAND_ID(1 );//!< Reply to a @c CMD_SWITCH_IOBOARD, indicates switch was successful, getParameter() contains the board switched to (0: nominal, 1: redundant) + static const Command_t REPLY_CANT_SWITCH_IOBOARD = MAKE_COMMAND_ID( 2); //!< Reply to a @c CMD_SWITCH_IOBOARD, indicating the switch could not be performed, getParameter() contains the error message + static const Command_t REPLY_WIRETAPPING = MAKE_COMMAND_ID( 3); //!< Reply to a @c CMD_WIRETAPPING, getParameter() is the current state, 1 enabled, 0 disabled + + static const Command_t REPLY_COMMAND_WAS_SENT = MAKE_COMMAND_ID(4 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates the command was successfully sent to the device, getParameter() contains the ::DeviceCommandId_t + static const Command_t REPLY_COMMAND_NOT_SUPPORTED = MAKE_COMMAND_ID(5 );//!< Reply to a @c CMD_DIRECT, the requested ::DeviceCommand_t is not supported, getParameter() contains the requested ::DeviceCommand_t, getParameter2() contains the ::DeviceCommandId_t + static const Command_t REPLY_COMMAND_WAS_NOT_SENT = MAKE_COMMAND_ID(6 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates the command was not sent, getParameter contains the RMAP Return code (@see rmap.h), getParameter2() contains the ::DeviceCommandId_t + + static const Command_t REPLY_COMMAND_ALREADY_SENT = MAKE_COMMAND_ID(7 );//!< Reply to a @c CMD_DIRECT, the requested ::DeviceCommand_t has already been sent to the device and not ye been answered + static const Command_t REPLY_WRONG_MODE_FOR_CMD = MAKE_COMMAND_ID(8 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates that the requested command can not be sent in the curent mode, getParameter() contains the DeviceHandlerCommand_t + static const Command_t REPLY_NO_DATA = MAKE_COMMAND_ID(9 ); //!< Reply to a CMD_RAW or @c CMD_DIRECT, indicates that the ::store_id_t was invalid, getParameter() contains the ::DeviceCommandId_t, getPrameter2() contains the error code + */ + static const Command_t REPLY_DIRECT_COMMAND_SENT = ActionMessage::STEP_SUCCESS; //!< Signals that a direct command was sent + static const Command_t REPLY_RAW_COMMAND = MAKE_COMMAND_ID(0x11 ); //!< Contains a raw command sent to the Device + static const Command_t REPLY_RAW_REPLY = MAKE_COMMAND_ID( 0x12); //!< Contains a raw reply from the Device, getParameter() is the ObjcetId of the sender, getParameter2() is a ::store_id_t containing the raw packet received static const Command_t REPLY_DIRECT_COMMAND_DATA = ActionMessage::DATA_REPLY; + /** + * Default Destructor + */ + virtual ~DeviceHandlerMessage() { + } + static store_address_t getStoreAddress(const CommandMessage* message); static uint32_t getDeviceCommandId(const CommandMessage* message); static object_id_t getDeviceObjectId(const CommandMessage *message); static object_id_t getIoBoardObjectId(const CommandMessage* message); static uint8_t getWiretappingMode(const CommandMessage* message); +// static void setDeviceHandlerDirectCommandMessage(CommandMessage* message, +// DeviceCommandId_t deviceCommand, +// store_address_t commandParametersStoreId); + static void setDeviceHandlerDirectCommandReply(CommandMessage* message, object_id_t deviceObjectid, store_address_t commandParametersStoreId); @@ -62,6 +75,11 @@ public: object_id_t deviceObjectid, store_address_t rawPacketStoreId, bool isCommand); +// static void setDeviceHandlerMessage(CommandMessage* message, +// Command_t command, DeviceCommandId_t deviceCommand, +// store_address_t commandParametersStoreId); +// static void setDeviceHandlerMessage(CommandMessage* message, +// Command_t command, store_address_t rawPacketStoreId); static void setDeviceHandlerWiretappingMessage(CommandMessage* message, uint8_t wiretappingMode); static void setDeviceHandlerSwitchIoBoardMessage(CommandMessage* message, @@ -70,4 +88,4 @@ public: static void clear(CommandMessage* message); }; -#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ */ +#endif /* DEVICEHANDLERMESSAGE_H_ */ From b313043e4312af0f54a24a2b8e560ba22ce287c5 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 1 Oct 2020 12:05:24 +0200 Subject: [PATCH 409/653] added new local data pool files --- datapoollocal/HasLocalDataPoolIF.h | 95 +++++ datapoollocal/LocalDataPoolManager.cpp | 427 ++++++++++++++++++++ datapoollocal/LocalDataPoolManager.h | 291 +++++++++++++ datapoollocal/LocalDataSet.cpp | 22 + datapoollocal/LocalDataSet.h | 21 + datapoollocal/LocalPoolDataSetBase.cpp | 259 ++++++++++++ datapoollocal/LocalPoolDataSetBase.h | 190 +++++++++ datapoollocal/LocalPoolVariable.h | 177 ++++++++ datapoollocal/LocalPoolVariable.tpp | 169 ++++++++ datapoollocal/LocalPoolVector.h | 202 +++++++++ datapoollocal/LocalPoolVector.tpp | 209 ++++++++++ datapoollocal/SharedLocalDataSet.cpp | 16 + datapoollocal/SharedLocalDataSet.h | 24 ++ datapoollocal/StaticLocalDataSet.h | 50 +++ housekeeping/AcceptsHkPacketsIF.h | 11 + housekeeping/HousekeepingMessage.cpp | 162 ++++++++ housekeeping/HousekeepingMessage.h | 157 +++++++ housekeeping/HousekeepingPacketDownlink.h | 34 ++ housekeeping/HousekeepingPacketUpdate.h | 73 ++++ housekeeping/HousekeepingSetPacket.h | 59 +++ housekeeping/PeriodicHousekeepingHelper.cpp | 48 +++ housekeeping/PeriodicHousekeepingHelper.h | 32 ++ 22 files changed, 2728 insertions(+) create mode 100644 datapoollocal/HasLocalDataPoolIF.h create mode 100644 datapoollocal/LocalDataPoolManager.cpp create mode 100644 datapoollocal/LocalDataPoolManager.h create mode 100644 datapoollocal/LocalDataSet.cpp create mode 100644 datapoollocal/LocalDataSet.h create mode 100644 datapoollocal/LocalPoolDataSetBase.cpp create mode 100644 datapoollocal/LocalPoolDataSetBase.h create mode 100644 datapoollocal/LocalPoolVariable.h create mode 100644 datapoollocal/LocalPoolVariable.tpp create mode 100644 datapoollocal/LocalPoolVector.h create mode 100644 datapoollocal/LocalPoolVector.tpp create mode 100644 datapoollocal/SharedLocalDataSet.cpp create mode 100644 datapoollocal/SharedLocalDataSet.h create mode 100644 datapoollocal/StaticLocalDataSet.h create mode 100644 housekeeping/AcceptsHkPacketsIF.h create mode 100644 housekeeping/HousekeepingMessage.cpp create mode 100644 housekeeping/HousekeepingMessage.h create mode 100644 housekeeping/HousekeepingPacketDownlink.h create mode 100644 housekeeping/HousekeepingPacketUpdate.h create mode 100644 housekeeping/HousekeepingSetPacket.h create mode 100644 housekeeping/PeriodicHousekeepingHelper.cpp create mode 100644 housekeeping/PeriodicHousekeepingHelper.h diff --git a/datapoollocal/HasLocalDataPoolIF.h b/datapoollocal/HasLocalDataPoolIF.h new file mode 100644 index 00000000..f8f4ef4c --- /dev/null +++ b/datapoollocal/HasLocalDataPoolIF.h @@ -0,0 +1,95 @@ +#ifndef FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_ +#define FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_ + +#include "../datapool/PoolEntryIF.h" +#include "../ipc/MessageQueueSenderIF.h" +#include "../housekeeping/HousekeepingMessage.h" + +#include + +class LocalDataPoolManager; +class LocalPoolDataSetBase; + +/** + * @brief Type definition for local pool entries. + */ +using lp_id_t = uint32_t; +using LocalDataPool = std::map; +using LocalDataPoolMapIter = LocalDataPool::iterator; + +/** + * @brief This interface is implemented by classes which posses a local + * data pool (not the managing class). It defines the relationship + * between the local data pool owner and the LocalDataPoolManager. + * @details + * Any class implementing this interface shall also have a LocalDataPoolManager + * member class which contains the actual pool data structure + * and exposes the public interface for it. + * This is required because the pool entries are templates, which makes + * specifying an interface rather difficult. The local data pool can be + * accessed by using the LocalPoolVariable, LocalPoolVector or LocalDataSet + * classes. + * + * Architectural Note: + * This could be circumvented by using a wrapper/accessor function or + * implementing the templated function in this interface.. + * The first solution sounds better than the second but + * the LocalPoolVariable classes are templates as well, so this just shifts + * the problem somewhere else. Interfaces are nice, but the most + * pragmatic solution I found was to offer the client the full interface + * of the LocalDataPoolManager. + */ +class HasLocalDataPoolIF { +public: + virtual~ HasLocalDataPoolIF() {}; + + static constexpr uint8_t INTERFACE_ID = CLASS_ID::LOCAL_POOL_OWNER_IF; + static constexpr lp_id_t NO_POOL_ID = 0xffffffff; + + virtual object_id_t getObjectId() const = 0; + + /** Command queue for housekeeping messages. */ + virtual MessageQueueId_t getCommandQueue() const = 0; + + /** + * Is used by pool owner to initialize the pool map once + * The manager instance shall also be passed to this function. + * It can be used to subscribe for periodic packets for for updates. + */ + virtual ReturnValue_t initializeLocalDataPool( + LocalDataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) = 0; + + /** Can be used to get a handle to the local data pool manager. */ + virtual LocalDataPoolManager* getHkManagerHandle() = 0; + + /** + * Returns the minimum sampling frequency in milliseconds, which will + * usually be the period the pool owner performs its periodic operation. + * @return + */ + virtual uint32_t getPeriodicOperationFrequency() const = 0; + + /** + * This function is used by the pool manager to get a valid dataset + * from a SID + * @param sid Corresponding structure ID + * @return + */ + virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) = 0; + + /* These function can be implemented by pool owner, as they are required + * by the housekeeping message interface */ + virtual ReturnValue_t addDataSet(sid_t sid) { + return HasReturnvaluesIF::RETURN_FAILED; + }; + virtual ReturnValue_t removeDataSet(sid_t sid) { + return HasReturnvaluesIF::RETURN_FAILED; + }; + virtual ReturnValue_t changeCollectionInterval(sid_t sid, + float newIntervalSeconds) { + return HasReturnvaluesIF::RETURN_FAILED; + }; +}; + +#endif /* FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_ */ diff --git a/datapoollocal/LocalDataPoolManager.cpp b/datapoollocal/LocalDataPoolManager.cpp new file mode 100644 index 00000000..c23f183b --- /dev/null +++ b/datapoollocal/LocalDataPoolManager.cpp @@ -0,0 +1,427 @@ +#include "LocalDataPoolManager.h" +#include "LocalPoolDataSetBase.h" + +#include "../housekeeping/HousekeepingSetPacket.h" +#include "../housekeeping/AcceptsHkPacketsIF.h" +#include "../ipc/MutexFactory.h" +#include "../ipc/MutexHelper.h" +#include "../ipc/QueueFactory.h" +#include "../objectmanager/frameworkObjects.h" + +#include +#include + +object_id_t LocalDataPoolManager::defaultHkDestination = + objects::PUS_SERVICE_3_HOUSEKEEPING; + +LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner, + MessageQueueIF* queueToUse, bool appendValidityBuffer): + appendValidityBuffer(appendValidityBuffer) { + if(owner == nullptr) { + sif::error << "LocalDataPoolManager::LocalDataPoolManager: " + << "Invalid supplied owner!" << std::endl; + return; + } + this->owner = owner; + mutex = MutexFactory::instance()->createMutex(); + if(mutex == nullptr) { + sif::error << "LocalDataPoolManager::LocalDataPoolManager: " + << "Could not create mutex." << std::endl; + } + + hkQueue = queueToUse; +} + +LocalDataPoolManager::~LocalDataPoolManager() {} + +ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) { + if(queueToUse == nullptr) { + sif::error << "LocalDataPoolManager::initialize: " + << std::hex << "0x" << owner->getObjectId() << ". Supplied " + << "queue invalid!" << std::dec << std::endl; + } + hkQueue = queueToUse; + + ipcStore = objectManager->get(objects::IPC_STORE); + if(ipcStore == nullptr) { + sif::error << "LocalDataPoolManager::initialize: " + << std::hex << "0x" << owner->getObjectId() << ": Could not " + << "set IPC store." <get(defaultHkDestination); + if(hkPacketReceiver != nullptr) { + hkDestinationId = hkPacketReceiver->getHkQueue(); + } + else { + sif::error << "LocalDataPoolManager::LocalDataPoolManager: " + << "Default HK destination object is invalid!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + } + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation( + uint8_t nonDiagInvlFactor) { + setNonDiagnosticIntervalFactor(nonDiagInvlFactor); + return initializeHousekeepingPoolEntriesOnce(); +} + +ReturnValue_t LocalDataPoolManager::initializeHousekeepingPoolEntriesOnce() { + if(not mapInitialized) { + ReturnValue_t result = owner->initializeLocalDataPool(localPoolMap, + *this); + if(result == HasReturnvaluesIF::RETURN_OK) { + mapInitialized = true; + } + return result; + } + sif::warning << "HousekeepingManager: The map should only be initialized " + << "once!" << std::endl; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t LocalDataPoolManager::performHkOperation() { + for(auto& receiver: hkReceiversMap) { + //HkReceiver* receiver = &hkReceiversIter.second; + + switch(receiver.reportingType) { + case(ReportingType::PERIODIC): { + if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) { + // Periodic packets shall only be generated from datasets. + continue; + } + performPeriodicHkGeneration(receiver); + break; + } + case(ReportingType::UPDATE_SNAPSHOT): { + // check whether data has changed and send messages in case it has. + break; + } + default: + // This should never happen. + return HasReturnvaluesIF::RETURN_FAILED; + } + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid, + bool enableReporting, float collectionInterval, bool isDiagnostics, + object_id_t packetDestination) { + AcceptsHkPacketsIF* hkReceiverObject = + objectManager->get(packetDestination); + if(hkReceiverObject == nullptr) { + sif::error << "LocalDataPoolManager::subscribeForPeriodicPacket:" + << " Invalid receiver!"<< std::endl; + return HasReturnvaluesIF::RETURN_OK; + } + + struct HkReceiver hkReceiver; + hkReceiver.dataId.sid = sid; + hkReceiver.reportingType = ReportingType::PERIODIC; + hkReceiver.destinationQueue = hkReceiverObject->getHkQueue(); + + LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid); + if(dataSet != nullptr) { + dataSet->setReportingEnabled(enableReporting); + dataSet->setDiagnostic(isDiagnostics); + dataSet->initializePeriodicHelper(collectionInterval, + owner->getPeriodicOperationFrequency(), isDiagnostics); + } + + hkReceiversMap.push_back(hkReceiver); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage( + CommandMessage* message) { + Command_t command = message->getCommand(); + sid_t sid = HousekeepingMessage::getSid(message); + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + switch(command) { + case(HousekeepingMessage::ENABLE_PERIODIC_DIAGNOSTICS_GENERATION): { + result = togglePeriodicGeneration(sid, true, true); + break; + } + + case(HousekeepingMessage::DISABLE_PERIODIC_DIAGNOSTICS_GENERATION): { + result = togglePeriodicGeneration(sid, false, true); + break; + } + + case(HousekeepingMessage::ENABLE_PERIODIC_HK_REPORT_GENERATION): { + result = togglePeriodicGeneration(sid, true, false); + break; + } + + case(HousekeepingMessage::DISABLE_PERIODIC_HK_REPORT_GENERATION): { + result = togglePeriodicGeneration(sid, false, false); + break; + } + + case(HousekeepingMessage::REPORT_DIAGNOSTICS_REPORT_STRUCTURES): + return generateSetStructurePacket(sid, true); + case(HousekeepingMessage::REPORT_HK_REPORT_STRUCTURES): + return generateSetStructurePacket(sid, false); + case(HousekeepingMessage::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL): + case(HousekeepingMessage::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL): { + float newCollIntvl = 0; + HousekeepingMessage::getCollectionIntervalModificationCommand(message, + &newCollIntvl); + if(command == HousekeepingMessage:: + MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL) { + result = changeCollectionInterval(sid, newCollIntvl, true); + } + else { + result = changeCollectionInterval(sid, newCollIntvl, false); + } + break; + } + + case(HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT): + case(HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT): { + LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid); + if(command == HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT + and dataSet->isDiagnostics()) { + return WRONG_HK_PACKET_TYPE; + } + else if(command == HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT + and not dataSet->isDiagnostics()) { + return WRONG_HK_PACKET_TYPE; + } + return generateHousekeepingPacket(HousekeepingMessage::getSid(message), + dataSet, true); + } + + default: + return CommandMessageIF::UNKNOWN_COMMAND; + } + + CommandMessage reply; + if(result != HasReturnvaluesIF::RETURN_OK) { + HousekeepingMessage::setHkRequestFailureReply(&reply, sid, result); + } + else { + HousekeepingMessage::setHkRequestSuccessReply(&reply, sid); + } + hkQueue->sendMessage(hkDestinationId, &reply); + return result; +} + +ReturnValue_t LocalDataPoolManager::printPoolEntry( + lp_id_t localPoolId) { + auto poolIter = localPoolMap.find(localPoolId); + if (poolIter == localPoolMap.end()) { + sif::debug << "HousekeepingManager::fechPoolEntry:" + << " Pool entry not found." << std::endl; + return POOL_ENTRY_NOT_FOUND; + } + poolIter->second->print(); + return HasReturnvaluesIF::RETURN_OK; +} + +MutexIF* LocalDataPoolManager::getMutexHandle() { + return mutex; +} + +HasLocalDataPoolIF* LocalDataPoolManager::getOwner() { + return owner; +} + +ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid, + LocalPoolDataSetBase* dataSet, bool forDownlink, + MessageQueueId_t destination) { + if(dataSet == nullptr) { + // Configuration error. + sif::warning << "HousekeepingManager::generateHousekeepingPacket:" + << " Set ID not found or dataset not assigned!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + store_address_t storeId; + HousekeepingPacketDownlink hkPacket(sid, dataSet); + size_t serializedSize = 0; + ReturnValue_t result = serializeHkPacketIntoStore(hkPacket, storeId, + forDownlink, &serializedSize); + if(result != HasReturnvaluesIF::RETURN_OK or serializedSize == 0) { + return result; + } + + // and now we set a HK message and send it the HK packet destination. + CommandMessage hkMessage; + if(dataSet->isDiagnostics()) { + HousekeepingMessage::setHkDiagnosticsReply(&hkMessage, sid, storeId); + } + else { + HousekeepingMessage::setHkReportReply(&hkMessage, sid, storeId); + } + + if(hkQueue == nullptr) { + return QUEUE_OR_DESTINATION_NOT_SET; + } + if(destination == MessageQueueIF::NO_QUEUE) { + if(hkDestinationId == MessageQueueIF::NO_QUEUE) { + // error, all destinations invalid + return HasReturnvaluesIF::RETURN_FAILED; + } + destination = hkDestinationId; + } + + return hkQueue->sendMessage(destination, &hkMessage); +} + +ReturnValue_t LocalDataPoolManager::serializeHkPacketIntoStore( + HousekeepingPacketDownlink& hkPacket, + store_address_t& storeId, bool forDownlink, + size_t* serializedSize) { + uint8_t* dataPtr = nullptr; + const size_t maxSize = hkPacket.getSerializedSize(); + ReturnValue_t result = ipcStore->getFreeElement(&storeId, + maxSize, &dataPtr); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + if(forDownlink) { + return hkPacket.serialize(&dataPtr, serializedSize, maxSize, + SerializeIF::Endianness::BIG); + } + return hkPacket.serialize(&dataPtr, serializedSize, maxSize, + SerializeIF::Endianness::MACHINE); +} + +void LocalDataPoolManager::setNonDiagnosticIntervalFactor( + uint8_t nonDiagInvlFactor) { + this->nonDiagnosticIntervalFactor = nonDiagInvlFactor; +} + +void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) { + sid_t sid = receiver.dataId.sid; + LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid); + if(not dataSet->getReportingEnabled()) { + return; + } + + if(dataSet->periodicHelper == nullptr) { + // Configuration error. + return; + } + + if(not dataSet->periodicHelper->checkOpNecessary()) { + return; + } + + ReturnValue_t result = generateHousekeepingPacket( + sid, dataSet, true); + if(result != HasReturnvaluesIF::RETURN_OK) { + // configuration error + sif::debug << "LocalDataPoolManager::performHkOperation:" + << "0x" << std::hex << std::setfill('0') << std::setw(8) + << owner->getObjectId() << " Error generating " + << "HK packet" << std::setfill(' ') << std::dec << std::endl; + } +} + + +ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, + bool enable, bool isDiagnostics) { + LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid); + if((dataSet->isDiagnostics() and not isDiagnostics) or + (not dataSet->isDiagnostics() and isDiagnostics)) { + return WRONG_HK_PACKET_TYPE; + } + + if((dataSet->getReportingEnabled() and enable) or + (not dataSet->getReportingEnabled() and not enable)) { + return REPORTING_STATUS_UNCHANGED; + } + + dataSet->setReportingEnabled(enable); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, + float newCollectionInterval, bool isDiagnostics) { + LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid); + bool targetIsDiagnostics = dataSet->isDiagnostics(); + if((targetIsDiagnostics and not isDiagnostics) or + (not targetIsDiagnostics and isDiagnostics)) { + return WRONG_HK_PACKET_TYPE; + } + + if(dataSet->periodicHelper == nullptr) { + // config error + return PERIODIC_HELPER_INVALID; + } + + dataSet->periodicHelper->changeCollectionInterval(newCollectionInterval); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, + bool isDiagnostics) { + // Get and check dataset first. + LocalPoolDataSetBase* dataSet = dynamic_cast( + owner->getDataSetHandle(sid)); + if(dataSet == nullptr) { + sif::warning << "HousekeepingManager::generateHousekeepingPacket:" + << " Set ID not found" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + + bool targetIsDiagnostics = dataSet->isDiagnostics(); + if((targetIsDiagnostics and not isDiagnostics) or + (not targetIsDiagnostics and isDiagnostics)) { + return WRONG_HK_PACKET_TYPE; + } + + bool valid = dataSet->isValid(); + bool reportingEnabled = dataSet->getReportingEnabled(); + float collectionInterval = + dataSet->periodicHelper->getCollectionIntervalInSeconds(); + + // Generate set packet which can be serialized. + HousekeepingSetPacket setPacket = HousekeepingSetPacket(sid, + reportingEnabled, valid, collectionInterval, dataSet); + size_t expectedSize = setPacket.getSerializedSize(); + uint8_t* storePtr = nullptr; + store_address_t storeId; + ReturnValue_t result = ipcStore->getFreeElement(&storeId, + expectedSize,&storePtr); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "HousekeepingManager::generateHousekeepingPacket: " + << "Could not get free element from IPC store." << std::endl; + return result; + } + + // Serialize set packet into store. + size_t size = 0; + result = setPacket.serialize(&storePtr, &size, expectedSize, + SerializeIF::Endianness::BIG); + if(expectedSize != size) { + sif::error << "HousekeepingManager::generateSetStructurePacket: " + << "Expected size is not equal to serialized size" << std::endl; + } + + // Send structure reporting reply. + CommandMessage reply; + if(isDiagnostics) { + HousekeepingMessage::setDiagnosticsStuctureReportReply(&reply, + sid, storeId); + } + else { + HousekeepingMessage::setHkStuctureReportReply(&reply, + sid, storeId); + } + + hkQueue->reply(&reply); + return result; +} diff --git a/datapoollocal/LocalDataPoolManager.h b/datapoollocal/LocalDataPoolManager.h new file mode 100644 index 00000000..779e3050 --- /dev/null +++ b/datapoollocal/LocalDataPoolManager.h @@ -0,0 +1,291 @@ +#ifndef FSFW_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_ +#define FSFW_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_ + +#include "HasLocalDataPoolIF.h" + +#include "../housekeeping/HousekeepingPacketDownlink.h" +#include "../housekeeping/HousekeepingMessage.h" +#include "../housekeeping/PeriodicHousekeepingHelper.h" +#include "../datapool/DataSetIF.h" +#include "../datapool/PoolEntry.h" +#include "../objectmanager/SystemObjectIF.h" +#include "../ipc/MutexIF.h" +#include "../ipc/CommandMessage.h" +#include "../ipc/MessageQueueIF.h" +#include "../ipc/MutexHelper.h" + +#include + +namespace Factory { +void setStaticFrameworkObjectIds(); +} + +class LocalDataSetBase; + + +/** + * @brief This class is the managing instance for the local data pool. + * @details + * The actual data pool structure is a member of this class. Any class which + * has a local data pool shall have this class as a member and implement + * the HasLocalDataPoolIF. + * + * Users of the data pool use the helper classes LocalDataSet, + * LocalPoolVariable and LocalPoolVector to access pool entries in + * a thread-safe and efficient way. + * + * The local data pools employ a blackboard logic: Only the most recent + * value is stored. The helper classes offer a read() and commit() interface + * through the PoolVariableIF which is used to read and update values. + * Each pool entry has a valid state too. + * @author R. Mueller + */ +class LocalDataPoolManager { + template + friend class LocalPoolVar; + template + friend class LocalPoolVector; + friend class LocalPoolDataSetBase; + friend void (Factory::setStaticFrameworkObjectIds)(); +public: + static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER; + + static constexpr ReturnValue_t POOL_ENTRY_NOT_FOUND = MAKE_RETURN_CODE(0x00); + static constexpr ReturnValue_t POOL_ENTRY_TYPE_CONFLICT = MAKE_RETURN_CODE(0x01); + + static constexpr ReturnValue_t QUEUE_OR_DESTINATION_NOT_SET = MAKE_RETURN_CODE(0x02); + + static constexpr ReturnValue_t WRONG_HK_PACKET_TYPE = MAKE_RETURN_CODE(0x03); + static constexpr ReturnValue_t REPORTING_STATUS_UNCHANGED = MAKE_RETURN_CODE(0x04); + static constexpr ReturnValue_t PERIODIC_HELPER_INVALID = MAKE_RETURN_CODE(0x05); + + /** + * This constructor is used by a class which wants to implement + * a personal local data pool. The queueToUse can be supplied if it + * is already known. + * + * initialize() has to be called in any case before using the object! + * @param owner + * @param queueToUse + * @param appendValidityBuffer + */ + LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse, + bool appendValidityBuffer = true); + virtual~ LocalDataPoolManager(); + + /** + * Assigns the queue to use. + * @param queueToUse + * @param nonDiagInvlFactor See #setNonDiagnosticIntervalFactor doc + * @return + */ + ReturnValue_t initialize(MessageQueueIF* queueToUse); + + /** + * Initializes the map by calling the map initialization function and + * setting the periodic factor for non-diagnostic packets. + * Don't forget to call this, otherwise the map will be invalid! + * @param nonDiagInvlFactor + * @return + */ + ReturnValue_t initializeAfterTaskCreation(uint8_t nonDiagInvlFactor = 5); + + /** + * This should be called in the periodic handler of the owner. + * It performs all the periodic functionalities of the data pool manager, + * for example generating periodic HK packets. + * @return + */ + ReturnValue_t performHkOperation(); + + /** + * @return + */ + ReturnValue_t subscribeForPeriodicPacket(sid_t sid, bool enableReporting, + float collectionInterval, bool isDiagnostics, + object_id_t packetDestination = defaultHkDestination); + + /** + * Non-Diagnostics packets usually have a lower minimum sampling frequency + * than diagnostic packets. + * A factor can be specified to determine the minimum sampling frequency + * for non-diagnostic packets. The minimum sampling frequency of the + * diagnostics packets,which is usually jusst the period of the + * performOperation calls, is multiplied with that factor. + * @param factor + */ + void setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor); + + + /** + * Generate a housekeeping packet with a given SID. + * @param sid + * @return + */ + ReturnValue_t generateHousekeepingPacket(sid_t sid, + LocalPoolDataSetBase* dataSet, bool forDownlink, + MessageQueueId_t destination = MessageQueueIF::NO_QUEUE); + + ReturnValue_t handleHousekeepingMessage(CommandMessage* message); + + /** + * This function is used to fill the local data pool map with pool + * entries. It should only be called once by the pool owner. + * @param localDataPoolMap + * @return + */ + ReturnValue_t initializeHousekeepingPoolEntriesOnce(); + + HasLocalDataPoolIF* getOwner(); + + ReturnValue_t printPoolEntry(lp_id_t localPoolId); + + /** + * Different types of housekeeping reporting are possible. + * 1. PERIODIC: + * HK packets are generated in fixed intervals and sent to + * destination. Fromat will be raw. + * 2. UPDATE_NOTIFICATION: + * Notification will be sent out if HK data has changed. + * 3. UPDATE_SNAPSHOT: + * HK packets are only generated if explicitely requested. + * Propably not necessary, just use multiple local data sets or + * shared datasets. + */ + enum class ReportingType: uint8_t { + //! Periodic generation of HK packets. + PERIODIC, + //! Housekeeping packet will be generated if values have changed. + UPDATE_HK, + //! Update notification will be sent out as message. + UPDATE_NOTIFICATION, + //! Notification will be sent out as message and a snapshot of the + //! current data will be generated. + UPDATE_SNAPSHOT, + }; + + /** + * Different data types are possible in the HK receiver map. + * For example, updates can be requested for full datasets or + * for single pool variables. Periodic reporting is only possible for + * data sets. + */ + enum class DataType: uint8_t { + LOCAL_POOL_VARIABLE, + DATA_SET + }; + + /* Copying forbidden */ + LocalDataPoolManager(const LocalDataPoolManager &) = delete; + LocalDataPoolManager operator=(const LocalDataPoolManager&) = delete; + +private: + LocalDataPool localPoolMap; + //! Every housekeeping data manager has a mutex to protect access + //! to it's data pool. + MutexIF* mutex = nullptr; + + /** The class which actually owns the manager (and its datapool). */ + HasLocalDataPoolIF* owner = nullptr; + + uint8_t nonDiagnosticIntervalFactor = 0; + + /** Default receiver for periodic HK packets */ + static object_id_t defaultHkDestination; + MessageQueueId_t hkDestinationId = MessageQueueIF::NO_QUEUE; + + /** The data pool manager will keep an internal map of HK receivers. */ + struct HkReceiver { + /** Object ID of receiver */ + object_id_t objectId = objects::NO_OBJECT; + + DataType dataType = DataType::DATA_SET; + union DataId { + DataId(): sid() {}; + sid_t sid; + lp_id_t localPoolId; + }; + DataId dataId; + + ReportingType reportingType = ReportingType::PERIODIC; + MessageQueueId_t destinationQueue = MessageQueueIF::NO_QUEUE; + }; + + /** This vector will contain the list of HK receivers. */ + using HkReceivers = std::vector; + + HkReceivers hkReceiversMap; + + /** This is the map holding the actual data. Should only be initialized + * once ! */ + bool mapInitialized = false; + /** This specifies whether a validity buffer is appended at the end + * of generated housekeeping packets. */ + bool appendValidityBuffer = true; + + /** + * @brief Queue used for communication, for example commands. + * Is also used to send messages. Can be set either in the constructor + * or in the initialize() function. + */ + MessageQueueIF* hkQueue = nullptr; + + /** Global IPC store is used to store all packets. */ + StorageManagerIF* ipcStore = nullptr; + /** + * Get the pointer to the mutex. Can be used to lock the data pool + * eternally. Use with care and don't forget to unlock locked mutexes! + * For now, only friend classes can accss this function. + * @return + */ + MutexIF* getMutexHandle(); + + /** + * Read a variable by supplying its local pool ID and assign the pool + * entry to the supplied PoolEntry pointer. The type of the pool entry + * is deduced automatically. This call is not thread-safe! + * For now, only friend classes like LocalPoolVar may access this + * function. + * @tparam T Type of the pool entry + * @param localPoolId Pool ID of the variable to read + * @param poolVar [out] Corresponding pool entry will be assigned to the + * supplied pointer. + * @return + */ + template ReturnValue_t fetchPoolEntry(lp_id_t localPoolId, + PoolEntry **poolEntry); + + ReturnValue_t serializeHkPacketIntoStore( + HousekeepingPacketDownlink& hkPacket, + store_address_t& storeId, bool forDownlink, size_t* serializedSize); + + void performPeriodicHkGeneration(HkReceiver& hkReceiver); + ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable, + bool isDiagnostics); + ReturnValue_t changeCollectionInterval(sid_t sid, + float newCollectionInterval, bool isDiagnostics); + ReturnValue_t generateSetStructurePacket(sid_t sid, bool isDiagnostics); +}; + + +template inline +ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId, + PoolEntry **poolEntry) { + auto poolIter = localPoolMap.find(localPoolId); + if (poolIter == localPoolMap.end()) { + sif::warning << "HousekeepingManager::fechPoolEntry: Pool entry " + "not found." << std::endl; + return POOL_ENTRY_NOT_FOUND; + } + + *poolEntry = dynamic_cast< PoolEntry* >(poolIter->second); + if(*poolEntry == nullptr) { + sif::debug << "HousekeepingManager::fetchPoolEntry:" + " Pool entry not found." << std::endl; + return POOL_ENTRY_TYPE_CONFLICT; + } + return HasReturnvaluesIF::RETURN_OK; +} + + +#endif /* FSFW_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_ */ diff --git a/datapoollocal/LocalDataSet.cpp b/datapoollocal/LocalDataSet.cpp new file mode 100644 index 00000000..394a9abe --- /dev/null +++ b/datapoollocal/LocalDataSet.cpp @@ -0,0 +1,22 @@ +#include "LocalDataSet.h" +#include "../datapoollocal/LocalDataPoolManager.h" +#include "../serialize/SerializeAdapter.h" + +#include +#include + +LocalDataSet::LocalDataSet(HasLocalDataPoolIF *hkOwner, uint32_t setId, + const size_t maxNumberOfVariables): + LocalPoolDataSetBase(hkOwner, setId, nullptr, maxNumberOfVariables), + poolVarList(maxNumberOfVariables) { + this->setContainer(poolVarList.data()); +} + +LocalDataSet::LocalDataSet(sid_t sid, const size_t maxNumberOfVariables): + LocalPoolDataSetBase(sid, nullptr, maxNumberOfVariables), + poolVarList(maxNumberOfVariables) { + this->setContainer(poolVarList.data()); +} + +LocalDataSet::~LocalDataSet() {} + diff --git a/datapoollocal/LocalDataSet.h b/datapoollocal/LocalDataSet.h new file mode 100644 index 00000000..0368f26d --- /dev/null +++ b/datapoollocal/LocalDataSet.h @@ -0,0 +1,21 @@ +#ifndef FSFW_DATAPOOLLOCAL_LOCALDATASET_H_ +#define FSFW_DATAPOOLLOCAL_LOCALDATASET_H_ + +#include "LocalPoolDataSetBase.h" +#include + +class LocalDataSet: public LocalPoolDataSetBase { +public: + LocalDataSet(HasLocalDataPoolIF* hkOwner, uint32_t setId, + const size_t maxSize); + LocalDataSet(sid_t sid, const size_t maxSize); + virtual~ LocalDataSet(); + + //! Copying forbidden for now. + LocalDataSet(const LocalDataSet&) = delete; + LocalDataSet& operator=(const LocalDataSet&) = delete; +private: + std::vector poolVarList; +}; + +#endif /* FSFW_DATAPOOLLOCAL_LOCALDATASET_H_ */ diff --git a/datapoollocal/LocalPoolDataSetBase.cpp b/datapoollocal/LocalPoolDataSetBase.cpp new file mode 100644 index 00000000..da0a86b2 --- /dev/null +++ b/datapoollocal/LocalPoolDataSetBase.cpp @@ -0,0 +1,259 @@ +#include "LocalPoolDataSetBase.h" +#include "../datapoollocal/LocalDataPoolManager.h" +#include "../housekeeping/PeriodicHousekeepingHelper.h" +#include "../serialize/SerializeAdapter.h" + +#include +#include + +LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner, + uint32_t setId, PoolVariableIF** registeredVariablesArray, + const size_t maxNumberOfVariables, bool noPeriodicHandling): + PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) { + if(hkOwner == nullptr) { + // Configuration error. + sif::error << "LocalPoolDataSetBase::LocalPoolDataSetBase: Owner " + << "invalid!" << std::endl; + return; + } + hkManager = hkOwner->getHkManagerHandle(); + this->sid.objectId = hkOwner->getObjectId(); + this->sid.ownerSetId = setId; + + // Data creators get a periodic helper for periodic HK data generation. + if(not noPeriodicHandling) { + periodicHelper = new PeriodicHousekeepingHelper(this); + } +} + +LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid, + PoolVariableIF** registeredVariablesArray, + const size_t maxNumberOfVariables): + PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) { + HasLocalDataPoolIF* hkOwner = objectManager->get( + sid.objectId); + if(hkOwner == nullptr) { + // Configuration error. + sif::error << "LocalPoolDataSetBase::LocalPoolDataSetBase: Owner " + << "invalid!" << std::endl; + return; + } + hkManager = hkOwner->getHkManagerHandle(); + this->sid = sid; +} + +LocalPoolDataSetBase::~LocalPoolDataSetBase() { +} + +ReturnValue_t LocalPoolDataSetBase::lockDataPool(uint32_t timeoutMs) { + MutexIF* mutex = hkManager->getMutexHandle(); + return mutex->lockMutex(MutexIF::TimeoutType::WAITING, timeoutMs); +} + +ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer(uint8_t **buffer, + size_t *size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + uint8_t validityMaskSize = std::ceil(static_cast(fillCount)/8.0); + uint8_t validityMask[validityMaskSize]; + uint8_t validBufferIndex = 0; + uint8_t validBufferIndexBit = 0; + for (uint16_t count = 0; count < fillCount; count++) { + if(registeredVariables[count]->isValid()) { + // set validity buffer here. + this->bitSetter(validityMask + validBufferIndex, + validBufferIndexBit); + if(validBufferIndexBit == 7) { + validBufferIndex ++; + validBufferIndexBit = 0; + } + else { + validBufferIndexBit ++; + } + } + result = registeredVariables[count]->serialize(buffer, size, maxSize, + streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + // copy validity buffer to end + std::memcpy(*buffer, validityMask, validityMaskSize); + *size += validityMaskSize; + return result; +} + +ReturnValue_t LocalPoolDataSetBase::deSerializeWithValidityBuffer( + const uint8_t **buffer, size_t *size, + SerializeIF::Endianness streamEndianness) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + for (uint16_t count = 0; count < fillCount; count++) { + result = registeredVariables[count]->deSerialize(buffer, size, + streamEndianness); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + uint8_t validBufferIndex = 0; + uint8_t validBufferIndexBit = 0; + // could be made more efficient but make it work first + for (uint16_t count = 0; count < fillCount; count++) { + // set validity buffer here. + bool nextVarValid = this->bitGetter(*buffer + + validBufferIndex, validBufferIndexBit); + registeredVariables[count]->setValid(nextVarValid); + + if(validBufferIndexBit == 7) { + validBufferIndex ++; + validBufferIndexBit = 0; + } + else { + validBufferIndexBit ++; + } + } + return result; +} +ReturnValue_t LocalPoolDataSetBase::unlockDataPool() { + MutexIF* mutex = hkManager->getMutexHandle(); + return mutex->unlockMutex(); +} + +ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t** buffer, + size_t* size, size_t maxSize,SerializeIF::Endianness streamEndianness, + bool serializeFillCount) const { + // Serialize as uint8_t + uint8_t fillCount = this->fillCount; + if(serializeFillCount) { + SerializeAdapter::serialize(&fillCount, buffer, size, maxSize, + streamEndianness); + } + for (uint16_t count = 0; count < fillCount; count++) { + lp_id_t currentPoolId = registeredVariables[count]->getDataPoolId(); + auto result = SerializeAdapter::serialize(¤tPoolId, buffer, + size, maxSize, streamEndianness); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "LocalDataSet::serializeLocalPoolIds: Serialization" + " error!" << std::endl; + return result; + } + } + return HasReturnvaluesIF::RETURN_OK; +} + + +uint8_t LocalPoolDataSetBase::getLocalPoolIdsSerializedSize( + bool serializeFillCount) const { + if(serializeFillCount) { + return fillCount * sizeof(lp_id_t) + sizeof(uint8_t); + } + else { + return fillCount * sizeof(lp_id_t); + } +} + +size_t LocalPoolDataSetBase::getSerializedSize() const { + if(withValidityBuffer) { + uint8_t validityMaskSize = std::ceil(static_cast(fillCount)/8.0); + return validityMaskSize + PoolDataSetBase::getSerializedSize(); + } + else { + return PoolDataSetBase::getSerializedSize(); + } +} + +void LocalPoolDataSetBase::setValidityBufferGeneration( + bool withValidityBuffer) { + this->withValidityBuffer = withValidityBuffer; +} + +ReturnValue_t LocalPoolDataSetBase::deSerialize(const uint8_t **buffer, + size_t *size, SerializeIF::Endianness streamEndianness) { + if(withValidityBuffer) { + return this->deSerializeWithValidityBuffer(buffer, size, + streamEndianness); + } + else { + return PoolDataSetBase::deSerialize(buffer, size, streamEndianness); + } +} + +ReturnValue_t LocalPoolDataSetBase::serialize(uint8_t **buffer, size_t *size, + size_t maxSize, SerializeIF::Endianness streamEndianness) const { + if(withValidityBuffer) { + return this->serializeWithValidityBuffer(buffer, size, + maxSize, streamEndianness); + } + else { + return PoolDataSetBase::serialize(buffer, size, maxSize, + streamEndianness); + } +} + +void LocalPoolDataSetBase::bitSetter(uint8_t* byte, uint8_t position) const { + if(position > 7) { + sif::debug << "Pool Raw Access: Bit setting invalid position" + << std::endl; + return; + } + uint8_t shiftNumber = position + (7 - 2 * position); + *byte |= 1 << shiftNumber; +} + +void LocalPoolDataSetBase::setDiagnostic(bool isDiagnostics) { + this->diagnostic = isDiagnostics; +} + +bool LocalPoolDataSetBase::isDiagnostics() const { + return diagnostic; +} + +void LocalPoolDataSetBase::setReportingEnabled(bool reportingEnabled) { + this->reportingEnabled = reportingEnabled; +} + +bool LocalPoolDataSetBase::getReportingEnabled() const { + return reportingEnabled; +} + +void LocalPoolDataSetBase::initializePeriodicHelper( + float collectionInterval, dur_millis_t minimumPeriodicInterval, + bool isDiagnostics, uint8_t nonDiagIntervalFactor) { + periodicHelper->initialize(collectionInterval, minimumPeriodicInterval, + isDiagnostics, nonDiagIntervalFactor); +} + +void LocalPoolDataSetBase::setChanged(bool changed) { + this->changed = changed; +} + +bool LocalPoolDataSetBase::isChanged() const { + return changed; +} + +sid_t LocalPoolDataSetBase::getSid() const { + return sid; +} + +bool LocalPoolDataSetBase::bitGetter(const uint8_t* byte, + uint8_t position) const { + if(position > 7) { + sif::debug << "Pool Raw Access: Bit setting invalid position" + << std::endl; + return false; + } + uint8_t shiftNumber = position + (7 - 2 * position); + return *byte & (1 << shiftNumber); +} + +bool LocalPoolDataSetBase::isValid() const { + return this->valid; +} + +void LocalPoolDataSetBase::setValidity(bool valid, bool setEntriesRecursively) { + if(setEntriesRecursively) { + for(size_t idx = 0; idx < this->getFillCount(); idx++) { + registeredVariables[idx] -> setValid(valid); + } + } + this->valid = valid; +} diff --git a/datapoollocal/LocalPoolDataSetBase.h b/datapoollocal/LocalPoolDataSetBase.h new file mode 100644 index 00000000..d00af992 --- /dev/null +++ b/datapoollocal/LocalPoolDataSetBase.h @@ -0,0 +1,190 @@ +#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_ +#define FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_ + +#include "HasLocalDataPoolIF.h" +#include "../datapool/DataSetIF.h" +#include "../datapool/PoolDataSetBase.h" +#include "../serialize/SerializeIF.h" + +#include + +class LocalDataPoolManager; +class PeriodicHousekeepingHelper; + +/** + * @brief The LocalDataSet class manages a set of locally checked out + * variables for local data pools + * @details + * Extends the PoolDataSetBase class for local data pools by introducing + * a validity state, a flag to mark the set as changed, and various other + * functions to make it usable by the LocalDataPoolManager class. + * + * This class manages a list, where a set of local variables (or pool variables) + * are registered. They are checked-out (i.e. their values are looked + * up and copied) with the read call. After the user finishes working with the + * pool variables, he can write back all variable values to the pool with + * the commit call. The data set manages locking and freeing the local data + * pools, to ensure thread-safety. + * + * Pool variables can be added to the dataset by using the constructor + * argument of the pool variable or using the #registerVariable member function. + * + * An internal state manages usage of this class. Variables may only be + * registered before any read call is made, and the commit call can only happen + * after the read call. + * + * If pool variables are writable and not committed until destruction + * of the set, the DataSet class automatically sets the valid flag in the + * data pool to invalid (without) changing the variable's value. + * + * @ingroup data_pool + */ +class LocalPoolDataSetBase: public PoolDataSetBase { + friend class LocalDataPoolManager; + friend class PeriodicHousekeepingHelper; +public: + /** + * @brief Constructor for the creator of local pool data. + * @details + * This constructor also initializes the components required for + * periodic handling. + */ + LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner, + uint32_t setId, PoolVariableIF** registeredVariablesArray, + const size_t maxNumberOfVariables, bool noPeriodicHandling = false); + + /** + * @brief Constructor for users of local pool data. + * @details + * @param sid Unique identifier of dataset consisting of object ID and + * set ID. + * @param registeredVariablesArray + * @param maxNumberOfVariables + */ + LocalPoolDataSetBase(sid_t sid, PoolVariableIF** registeredVariablesArray, + const size_t maxNumberOfVariables); + + /** + * @brief The destructor automatically manages writing the valid + * information of variables. + * @details + * In case the data set was read out, but not committed(indicated by state), + * the destructor parses all variables that are still registered to the set. + * For each, the valid flag in the data pool is set to "invalid". + */ + ~LocalPoolDataSetBase(); + + void setValidityBufferGeneration(bool withValidityBuffer); + + sid_t getSid() const; + + /** SerializeIF overrides */ + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const override; + ReturnValue_t deSerialize(const uint8_t** buffer, size_t *size, + SerializeIF::Endianness streamEndianness) override; + size_t getSerializedSize() const override; + + /** + * Special version of the serilization function which appends a + * validity buffer at the end. Each bit of this validity buffer + * denotes whether the container data set entries are valid from left + * to right, MSB first. (length = ceil(N/8), N = number of pool variables) + * @param buffer + * @param size + * @param maxSize + * @param bigEndian + * @param withValidityBuffer + * @return + */ + ReturnValue_t serializeWithValidityBuffer(uint8_t** buffer, + size_t* size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const; + ReturnValue_t deSerializeWithValidityBuffer(const uint8_t** buffer, + size_t *size, SerializeIF::Endianness streamEndianness); + ReturnValue_t serializeLocalPoolIds(uint8_t** buffer, + size_t* size, size_t maxSize, + SerializeIF::Endianness streamEndianness, + bool serializeFillCount = true) const; + uint8_t getLocalPoolIdsSerializedSize(bool serializeFillCount = true) const; + + /** + * Set the dataset valid or invalid + * @param setEntriesRecursively + * If this is true, all contained datasets will also be set recursively. + */ + void setValidity(bool valid, bool setEntriesRecursively); + bool isValid() const override; + + void setChanged(bool changed); + bool isChanged() const; + +protected: + sid_t sid; + + bool diagnostic = false; + void setDiagnostic(bool diagnostics); + bool isDiagnostics() const; + + /** + * Used for periodic generation. + */ + bool reportingEnabled = false; + void setReportingEnabled(bool enabled); + bool getReportingEnabled() const; + + void initializePeriodicHelper(float collectionInterval, + dur_millis_t minimumPeriodicInterval, + bool isDiagnostics, uint8_t nonDiagIntervalFactor = 5); + + /** + * If the valid state of a dataset is always relevant to the whole + * data set we can use this flag. + */ + bool valid = false; + + /** + * Can be used to mark the dataset as changed, which is used + * by the LocalDataPoolManager to send out update messages. + */ + bool changed = false; + + /** + * Specify whether the validity buffer is serialized too when serializing + * or deserializing the packet. Each bit of the validity buffer will + * contain the validity state of the pool variables from left to right. + * The size of validity buffer thus will be ceil(N / 8) with N = number of + * pool variables. + */ + bool withValidityBuffer = true; + + /** + * @brief This is a small helper function to facilitate locking + * the global data pool. + * @details + * It makes use of the lockDataPool method offered by the DataPool class. + */ + ReturnValue_t lockDataPool(uint32_t timeoutMs) override; + /** + * @brief This is a small helper function to facilitate + * unlocking the global data pool + * @details + * It makes use of the freeDataPoolLock method offered by the DataPool class. + */ + ReturnValue_t unlockDataPool() override; + + LocalDataPoolManager* hkManager; + + /** + * Set n-th bit of a byte, with n being the position from 0 + * (most significant bit) to 7 (least significant bit) + */ + void bitSetter(uint8_t* byte, uint8_t position) const; + bool bitGetter(const uint8_t* byte, uint8_t position) const; + + PeriodicHousekeepingHelper* periodicHelper = nullptr; + +}; + + +#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_ */ diff --git a/datapoollocal/LocalPoolVariable.h b/datapoollocal/LocalPoolVariable.h new file mode 100644 index 00000000..ec5c8cd1 --- /dev/null +++ b/datapoollocal/LocalPoolVariable.h @@ -0,0 +1,177 @@ +#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_ +#define FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_ + +#include "HasLocalDataPoolIF.h" +#include "LocalDataPoolManager.h" + +#include "../datapool/PoolVariableIF.h" +#include "../datapool/DataSetIF.h" +#include "../objectmanager/ObjectManagerIF.h" +#include "../serialize/SerializeAdapter.h" + +/** + * @brief Local Pool Variable class which is used to access the local pools. + * @details + * This class is not stored in the map. Instead, it is used to access + * the pool entries by using a pointer to the map storing the pool + * entries. It can also be used to organize these pool entries into data sets. + * + * @tparam T The template parameter sets the type of the variable. Currently, + * all plain data types are supported, but in principle any type is possible. + * @ingroup data_pool + */ +template +class LocalPoolVar: public PoolVariableIF, HasReturnvaluesIF { +public: + //! Default ctor is forbidden. + LocalPoolVar() = delete; + + /** + * This constructor is used by the data creators to have pool variable + * instances which can also be stored in datasets. + * + * It does not fetch the current value from the data pool, which + * has to be done by calling the read() operation. + * Datasets can be used to access multiple local pool entries in an + * efficient way. A pointer to a dataset can be passed to register + * the pool variable in that dataset directly. + * @param poolId ID of the local pool entry. + * @param hkOwner Pointer of the owner. This will generally be the calling + * class itself which passes "this". + * @param dataSet The data set in which the variable shall register itself. + * If nullptr, the variable is not registered. + * @param setReadWriteMode Specify the read-write mode of the pool variable. + */ + LocalPoolVar(lp_id_t poolId, HasLocalDataPoolIF* hkOwner, + DataSetIF* dataSet = nullptr, + pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE); + + /** + * This constructor is used by data users like controllers to have + * access to the local pool variables of data creators by supplying + * the respective creator object ID. + * + * It does not fetch the current value from the data pool, which + * has to be done by calling the read() operation. + * Datasets can be used to access multiple local pool entries in an + * efficient way. A pointer to a dataset can be passed to register + * the pool variable in that dataset directly. + * @param poolId ID of the local pool entry. + * @param hkOwner object ID of the pool owner. + * @param dataSet The data set in which the variable shall register itself. + * If nullptr, the variable is not registered. + * @param setReadWriteMode Specify the read-write mode of the pool variable. + * + */ + LocalPoolVar(lp_id_t poolId, object_id_t poolOwner, + DataSetIF* dataSet = nullptr, + pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE); + + virtual~ LocalPoolVar() {}; + + /** + * @brief This is the local copy of the data pool entry. + * @details The user can work on this attribute + * just like he would on a simple local variable. + */ + T value = 0; + + pool_rwm_t getReadWriteMode() const override; + + lp_id_t getDataPoolId() const override; + void setDataPoolId(lp_id_t poolId); + + bool isValid() const override; + void setValid(bool validity) override; + uint8_t getValid() const; + + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const override; + virtual size_t getSerializedSize() const override; + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) override; + + /** + * @brief This is a call to read the array's values + * from the global data pool. + * @details + * When executed, this operation tries to fetch the pool entry with matching + * data pool id from the data pool and copies all array values and the valid + * information to its local attributes. + * In case of a failure (wrong type, size or pool id not found), the + * variable is set to zero and invalid. + * The read call is protected with a lock. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. + * + */ + ReturnValue_t read(dur_millis_t lockTimeout = MutexIF::BLOCKING) override; + /** + * @brief The commit call copies the array values back to the data pool. + * @details + * It checks type and size, as well as if the variable is writable. If so, + * the value is copied and the local valid flag is written back as well. + * The read call is protected with a lock. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. + */ + ReturnValue_t commit(dur_millis_t lockTimeout = MutexIF::BLOCKING) override; + + + LocalPoolVar &operator=(T newValue); +protected: + /** + * @brief Like #read, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t readWithoutLock() override; + /** + * @brief Like #commit, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t commitWithoutLock() override; + + // std::ostream is the type for object std::cout + template + friend std::ostream& operator<< (std::ostream &out, + const LocalPoolVar &var); + +private: + //! @brief Pool ID of pool entry inside the used local pool. + lp_id_t localPoolId = PoolVariableIF::NO_PARAMETER; + //! @brief Read-write mode of the pool variable + pool_rwm_t readWriteMode = pool_rwm_t::VAR_READ_WRITE; + //! @brief Specifies whether the entry is valid or invalid. + bool valid = false; + + //! Pointer to the class which manages the HK pool. + LocalDataPoolManager* hkManager; +}; + +#include "LocalPoolVariable.tpp" + +template +using lp_var_t = LocalPoolVar; + +using lp_bool_t = LocalPoolVar; +using lp_uint8_t = LocalPoolVar; +using lp_uint16_t = LocalPoolVar; +using lp_uint32_t = LocalPoolVar; +using lp_uint64_t = LocalPoolVar; +using lp_int8_t = LocalPoolVar; +using lp_int16_t = LocalPoolVar; +using lp_int32_t = LocalPoolVar; +using lp_int64_t = LocalPoolVar; +using lp_float_t = LocalPoolVar; +using lp_double_t = LocalPoolVar; + + +#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_ */ diff --git a/datapoollocal/LocalPoolVariable.tpp b/datapoollocal/LocalPoolVariable.tpp new file mode 100644 index 00000000..b0bdd7b9 --- /dev/null +++ b/datapoollocal/LocalPoolVariable.tpp @@ -0,0 +1,169 @@ +#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_ +#define FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_ + +#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_ +#error Include LocalPoolVariable.h before LocalPoolVariable.tpp! +#endif + +template +inline LocalPoolVar::LocalPoolVar(lp_id_t poolId, + HasLocalDataPoolIF* hkOwner, DataSetIF* dataSet, + pool_rwm_t setReadWriteMode): + localPoolId(poolId), readWriteMode(setReadWriteMode) { + if(poolId == PoolVariableIF::NO_PARAMETER) { + sif::warning << "LocalPoolVar::LocalPoolVar: 0 passed as pool ID, " + << "which is the NO_PARAMETER value!" << std::endl; + } + if(hkOwner == nullptr) { + sif::error << "LocalPoolVar::LocalPoolVar: The supplied pool " + << "owner is a invalid!" << std::endl; + return; + } + hkManager = hkOwner->getHkManagerHandle(); + if(dataSet != nullptr) { + dataSet->registerVariable(this); + } +} + +template +inline LocalPoolVar::LocalPoolVar(lp_id_t poolId, object_id_t poolOwner, + DataSetIF *dataSet, pool_rwm_t setReadWriteMode): + localPoolId(poolId), readWriteMode(setReadWriteMode) { + if(poolId == PoolVariableIF::NO_PARAMETER) { + sif::warning << "LocalPoolVar::LocalPoolVar: 0 passed as pool ID, " + << "which is the NO_PARAMETER value!" << std::endl; + } + HasLocalDataPoolIF* hkOwner = + objectManager->get(poolOwner); + if(hkOwner == nullptr) { + sif::error << "LocalPoolVariable: The supplied pool owner did not " + << "implement the correct interface " + << "HasLocalDataPoolIF!" << std::endl; + return; + } + hkManager = hkOwner->getHkManagerHandle(); + if(dataSet != nullptr) { + dataSet->registerVariable(this); + } +} + +template +inline ReturnValue_t LocalPoolVar::read(dur_millis_t lockTimeout) { + MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, + lockTimeout); + return readWithoutLock(); +} + +template +inline ReturnValue_t LocalPoolVar::readWithoutLock() { + if(readWriteMode == pool_rwm_t::VAR_WRITE) { + sif::debug << "LocalPoolVar: Invalid read write " + "mode for read() call." << std::endl; + return PoolVariableIF::INVALID_READ_WRITE_MODE; + } + + PoolEntry* poolEntry = nullptr; + ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); + if(result != RETURN_OK and poolEntry != nullptr) { + sif::error << "PoolVector: Read of local pool variable of object " + "0x" << std::hex << std::setw(8) << std::setfill('0') << + hkManager->getOwner() << " and lp ID 0x" << localPoolId << + std::dec << " failed.\n" << std::flush; + return result; + } + this->value = *(poolEntry->address); + this->valid = poolEntry->valid; + return RETURN_OK; +} + +template +inline ReturnValue_t LocalPoolVar::commit(dur_millis_t lockTimeout) { + MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, + lockTimeout); + return commitWithoutLock(); +} + +template +inline ReturnValue_t LocalPoolVar::commitWithoutLock() { + if(readWriteMode == pool_rwm_t::VAR_READ) { + sif::debug << "LocalPoolVar: Invalid read write " + "mode for commit() call." << std::endl; + return PoolVariableIF::INVALID_READ_WRITE_MODE; + } + PoolEntry* poolEntry = nullptr; + ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); + if(result != RETURN_OK) { + sif::error << "PoolVector: Read of local pool variable of object " + "0x" << std::hex << std::setw(8) << std::setfill('0') << + hkManager->getOwner() << " and lp ID 0x" << localPoolId << + std::dec << " failed.\n" << std::flush; + return result; + } + *(poolEntry->address) = this->value; + poolEntry->valid = this->valid; + return RETURN_OK; +} + +template +inline LocalPoolVar & LocalPoolVar::operator =(T newValue) { + value = newValue; + return *this; +} + + +template +inline pool_rwm_t LocalPoolVar::getReadWriteMode() const { + return readWriteMode; +} + +template +inline lp_id_t LocalPoolVar::getDataPoolId() const { + return localPoolId; +} + +template +inline void LocalPoolVar::setDataPoolId(lp_id_t poolId) { + this->localPoolId = poolId; +} + +template +inline bool LocalPoolVar::isValid() const { + return valid; +} + +template +inline void LocalPoolVar::setValid(bool validity) { + this->valid = validity; +} + +template +inline uint8_t LocalPoolVar::getValid() const { + return valid; +} + +template +inline ReturnValue_t LocalPoolVar::serialize(uint8_t** buffer, size_t* size, + const size_t max_size, SerializeIF::Endianness streamEndianness) const { + return SerializeAdapter::serialize(&value, + buffer, size ,max_size, streamEndianness); +} + +template +inline size_t LocalPoolVar::getSerializedSize() const { + return SerializeAdapter::getSerializedSize(&value); +} + +template +inline ReturnValue_t LocalPoolVar::deSerialize(const uint8_t** buffer, + size_t* size, SerializeIF::Endianness streamEndianness) { + return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness); +} + +template +inline std::ostream& operator<< (std::ostream &out, + const LocalPoolVar &var) { + out << var.value; + return out; +} + +#endif diff --git a/datapoollocal/LocalPoolVector.h b/datapoollocal/LocalPoolVector.h new file mode 100644 index 00000000..57c4b90b --- /dev/null +++ b/datapoollocal/LocalPoolVector.h @@ -0,0 +1,202 @@ +#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_ +#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_ + +#include "../datapool/DataSetIF.h" +#include "../datapool/PoolEntry.h" +#include "../datapool/PoolVariableIF.h" +#include "../datapoollocal/LocalDataPoolManager.h" +#include "../serialize/SerializeAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" + + +/** + * @brief This is the access class for array-type data pool entries. + * @details + * To ensure safe usage of the data pool, operation is not done directly on the + * data pool entries, but on local copies. This class provides simple type- + * and length-safe access to vector-style data pool entries (i.e. entries with + * length > 1). The class can be instantiated as read-write and read only. + * + * It provides a commit-and-roll-back semantic, which means that no array + * entry in the data pool is changed until the commit call is executed. + * There are two template parameters: + * @tparam T + * This template parameter specifies the data type of an array entry. Currently, + * all plain data types are supported, but in principle any type is possible. + * @tparam vector_size + * This template parameter specifies the vector size of this entry. Using a + * template parameter for this is not perfect, but avoids + * dynamic memory allocation. + * @ingroup data_pool + */ +template +class LocalPoolVector: public PoolVariableIF, public HasReturnvaluesIF { +public: + LocalPoolVector() = delete; + /** + * This constructor is used by the data creators to have pool variable + * instances which can also be stored in datasets. + * It does not fetch the current value from the data pool. This is performed + * by the read() operation (which is not thread-safe). + * Datasets can be used to access local pool entires in a thread-safe way. + * @param poolId ID of the local pool entry. + * @param hkOwner Pointer of the owner. This will generally be the calling + * class itself which passes "this". + * @param setReadWriteMode Specify the read-write mode of the pool variable. + * @param dataSet The data set in which the variable shall register itself. + * If nullptr, the variable is not registered. + */ + LocalPoolVector(lp_id_t poolId, HasLocalDataPoolIF* hkOwner, + DataSetIF* dataSet = nullptr, + pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE + ); + + /** + * This constructor is used by data users like controllers to have + * access to the local pool variables of data creators by supplying + * the respective creator object ID. + * It does not fetch the current value from the data pool. This is performed + * by the read() operation (which is not thread-safe). + * Datasets can be used to access local pool entires in a thread-safe way. + * @param poolId ID of the local pool entry. + * @param hkOwner Pointer of the owner. This will generally be the calling + * class itself which passes "this". + * @param setReadWriteMode Specify the read-write mode of the pool variable. + * @param dataSet The data set in which the variable shall register itself. + * If nullptr, the variable is not registered. + */ + LocalPoolVector(lp_id_t poolId, object_id_t poolOwner, + DataSetIF* dataSet = nullptr, + pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE + ); + + /** + * @brief This is the local copy of the data pool entry. + * @details + * The user can work on this attribute just like he would on a local + * array of this type. + */ + T value[vectorSize]; + /** + * @brief The classes destructor is empty. + * @details If commit() was not called, the local value is + * discarded and not written back to the data pool. + */ + ~LocalPoolVector() {}; + /** + * @brief The operation returns the number of array entries + * in this variable. + */ + uint8_t getSize() { + return vectorSize; + } + + uint32_t getDataPoolId() const override; + /** + * @brief This operation sets the data pool ID of the variable. + * @details + * The method is necessary to set id's of data pool member variables + * with bad initialization. + */ + void setDataPoolId(uint32_t poolId); + + /** + * This method returns if the variable is write-only, read-write or read-only. + */ + pool_rwm_t getReadWriteMode() const; + + /** + * @brief With this call, the valid information of the variable is returned. + */ + bool isValid() const override; + void setValid(bool valid) override; + uint8_t getValid() const; + + T& operator [](int i); + const T &operator [](int i) const; + + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + const size_t maxSize, + SerializeIF::Endianness streamEndiannes) const override; + virtual size_t getSerializedSize() const override; + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) override; + + /** + * @brief This is a call to read the array's values + * from the global data pool. + * @details + * When executed, this operation tries to fetch the pool entry with matching + * data pool id from the data pool and copies all array values and the valid + * information to its local attributes. + * In case of a failure (wrong type, size or pool id not found), the + * variable is set to zero and invalid. + * The read call is protected with a lock. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. + */ + ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override; + /** + * @brief The commit call copies the array values back to the data pool. + * @details + * It checks type and size, as well as if the variable is writable. If so, + * the value is copied and the local valid flag is written back as well. + * The read call is protected with a lock. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. + */ + ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; + +protected: + /** + * @brief Like #read, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t readWithoutLock() override; + /** + * @brief Like #commit, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t commitWithoutLock() override; + +private: + /** + * @brief To access the correct data pool entry on read and commit calls, + * the data pool id is stored. + */ + uint32_t localPoolId; + /** + * @brief The valid information as it was stored in the data pool + * is copied to this attribute. + */ + bool valid; + /** + * @brief The information whether the class is read-write or + * read-only is stored here. + */ + ReadWriteMode_t readWriteMode; + //! @brief Pointer to the class which manages the HK pool. + LocalDataPoolManager* hkManager; + + // std::ostream is the type for object std::cout + template + friend std::ostream& operator<< (std::ostream &out, + const LocalPoolVector &var); + + +}; + +#include "LocalPoolVector.tpp" + +template +using lp_vec_t = LocalPoolVector; + +#endif /* FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_ */ diff --git a/datapoollocal/LocalPoolVector.tpp b/datapoollocal/LocalPoolVector.tpp new file mode 100644 index 00000000..2aa6fbb5 --- /dev/null +++ b/datapoollocal/LocalPoolVector.tpp @@ -0,0 +1,209 @@ +#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_TPP_ +#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_TPP_ + +#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_ +#error Include LocalPoolVector.h before LocalPoolVector.tpp! +#endif + +template +inline LocalPoolVector::LocalPoolVector(lp_id_t poolId, + HasLocalDataPoolIF* hkOwner, DataSetIF* dataSet, + pool_rwm_t setReadWriteMode): + localPoolId(poolId), valid(false), readWriteMode(setReadWriteMode) { + if(poolId == PoolVariableIF::NO_PARAMETER) { + sif::warning << "LocalPoolVector: PoolVariableIF::NO_PARAMETER passed " + << "as pool ID, which is the NO_PARAMETER value!" << std::endl; + } + std::memset(this->value, 0, vectorSize * sizeof(T)); + hkManager = hkOwner->getHkManagerHandle(); + if (dataSet != nullptr) { + dataSet->registerVariable(this); + } +} + +template +inline LocalPoolVector::LocalPoolVector(lp_id_t poolId, + object_id_t poolOwner, DataSetIF *dataSet, pool_rwm_t setReadWriteMode): + readWriteMode(setReadWriteMode) { + if(poolId == PoolVariableIF::NO_PARAMETER) { + sif::warning << "LocalPoolVector: PoolVariableIF::NO_PARAMETER passed " + << "as pool ID, which is the NO_PARAMETER value!" << std::endl; + } + HasLocalDataPoolIF* hkOwner = + objectManager->get(poolOwner); + if(hkOwner == nullptr) { + sif::error << "LocalPoolVariable: The supplied pool owner did not " + << "implement the correct interface HasHkPoolParametersIF!" + << std::endl; + return; + } + hkManager = hkOwner->getHkManagerHandle(); + if(dataSet != nullptr) { + dataSet->registerVariable(this); + } +} + +template +inline ReturnValue_t LocalPoolVector::read(uint32_t lockTimeout) { + MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, + lockTimeout); + return readWithoutLock(); +} +template +inline ReturnValue_t LocalPoolVector::readWithoutLock() { + if(readWriteMode == pool_rwm_t::VAR_WRITE) { + sif::debug << "LocalPoolVar: Invalid read write " + "mode for read() call." << std::endl; + return PoolVariableIF::INVALID_READ_WRITE_MODE; + } + + PoolEntry* poolEntry = nullptr; + ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); + memset(this->value, 0, vectorSize * sizeof(T)); + + if(result != RETURN_OK) { + sif::error << "PoolVector: Read of local pool variable of object " + "0x" << std::hex << std::setw(8) << std::setfill('0') << + hkManager->getOwner() << "and lp ID 0x" << localPoolId << + std::dec << " failed." << std::endl; + return result; + } + std::memcpy(this->value, poolEntry->address, poolEntry->getByteSize()); + this->valid = poolEntry->valid; + return RETURN_OK; +} + +template +inline ReturnValue_t LocalPoolVector::commit( + uint32_t lockTimeout) { + MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, + lockTimeout); + return commitWithoutLock(); +} + +template +inline ReturnValue_t LocalPoolVector::commitWithoutLock() { + if(readWriteMode == pool_rwm_t::VAR_READ) { + sif::debug << "LocalPoolVar: Invalid read write " + "mode for commit() call." << std::endl; + return PoolVariableIF::INVALID_READ_WRITE_MODE; + } + PoolEntry* poolEntry = nullptr; + ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); + if(result != RETURN_OK) { + sif::error << "PoolVector: Read of local pool variable of object " + "0x" << std::hex << std::setw(8) << std::setfill('0') << + hkManager->getOwner() << " and lp ID 0x" << localPoolId << + std::dec << " failed.\n" << std::flush; + return result; + } + std::memcpy(poolEntry->address, this->value, poolEntry->getByteSize()); + poolEntry->valid = this->valid; + return RETURN_OK; +} + +template +inline T& LocalPoolVector::operator [](int i) { + if(i <= vectorSize) { + return value[i]; + } + // If this happens, I have to set some value. I consider this + // a configuration error, but I wont exit here. + sif::error << "LocalPoolVector: Invalid index. Setting or returning" + " last value!" << std::endl; + return value[i]; +} + +template +inline const T& LocalPoolVector::operator [](int i) const { + if(i <= vectorSize) { + return value[i]; + } + // If this happens, I have to set some value. I consider this + // a configuration error, but I wont exit here. + sif::error << "LocalPoolVector: Invalid index. Setting or returning" + " last value!" << std::endl; + return value[i]; +} + +template +inline ReturnValue_t LocalPoolVector::serialize(uint8_t** buffer, + size_t* size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + for (uint16_t i = 0; i < vectorSize; i++) { + result = SerializeAdapter::serialize(&(value[i]), buffer, size, + maxSize, streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + break; + } + } + return result; +} + +template +inline size_t LocalPoolVector::getSerializedSize() const { + return vectorSize * SerializeAdapter::getSerializedSize(value); +} + +template +inline ReturnValue_t LocalPoolVector::deSerialize( + const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + for (uint16_t i = 0; i < vectorSize; i++) { + result = SerializeAdapter::deSerialize(&(value[i]), buffer, size, + streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + break; + } + } + return result; +} + +template +inline pool_rwm_t LocalPoolVector::getReadWriteMode() const { + return this->readWriteMode; +} + + +template +inline uint32_t LocalPoolVector::getDataPoolId() const { + return localPoolId; +} + +template +inline void LocalPoolVector::setDataPoolId(uint32_t poolId) { + this->localPoolId = poolId; +} + +template +inline void LocalPoolVector::setValid(bool valid) { + this->valid = valid; +} + +template +inline uint8_t LocalPoolVector::getValid() const { + return valid; +} + +template +inline bool LocalPoolVector::isValid() const { + return valid; +} + +template +inline std::ostream& operator<< (std::ostream &out, + const LocalPoolVector &var) { + out << "Vector: ["; + for(int i = 0;i < vectorSize; i++) { + out << var.value[i]; + if(i < vectorSize - 1) { + out << ", "; + } + } + out << "]"; + return out; +} + +#endif diff --git a/datapoollocal/SharedLocalDataSet.cpp b/datapoollocal/SharedLocalDataSet.cpp new file mode 100644 index 00000000..dd1bdcc4 --- /dev/null +++ b/datapoollocal/SharedLocalDataSet.cpp @@ -0,0 +1,16 @@ +#include "SharedLocalDataSet.h" + +SharedLocalDataSet::SharedLocalDataSet(object_id_t objectId, sid_t sid, + const size_t maxSize): SystemObject(objectId), + LocalPoolDataSetBase(sid, nullptr, maxSize) { + this->setContainer(poolVarVector.data()); + datasetLock = MutexFactory::instance()->createMutex(); +} + +ReturnValue_t SharedLocalDataSet::lockDataset(dur_millis_t mutexTimeout) { + return datasetLock->lockMutex(MutexIF::TimeoutType::WAITING, mutexTimeout); +} + +ReturnValue_t SharedLocalDataSet::unlockDataset() { + return datasetLock->unlockMutex(); +} diff --git a/datapoollocal/SharedLocalDataSet.h b/datapoollocal/SharedLocalDataSet.h new file mode 100644 index 00000000..2e5a76fa --- /dev/null +++ b/datapoollocal/SharedLocalDataSet.h @@ -0,0 +1,24 @@ +#ifndef FSFW_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_ +#define FSFW_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_ + +#include "LocalPoolDataSetBase.h" +#include "../datapool/SharedDataSetIF.h" +#include "../objectmanager/SystemObject.h" +#include + +class SharedLocalDataSet: public SystemObject, + public LocalPoolDataSetBase, + public SharedDataSetIF { +public: + SharedLocalDataSet(object_id_t objectId, sid_t sid, + const size_t maxSize); + ReturnValue_t lockDataset(dur_millis_t mutexTimeout) override; + ReturnValue_t unlockDataset() override; +private: + + MutexIF* datasetLock = nullptr; + std::vector poolVarVector; +}; + + +#endif /* FSFW_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_ */ diff --git a/datapoollocal/StaticLocalDataSet.h b/datapoollocal/StaticLocalDataSet.h new file mode 100644 index 00000000..a637e360 --- /dev/null +++ b/datapoollocal/StaticLocalDataSet.h @@ -0,0 +1,50 @@ +#ifndef FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_ +#define FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_ + +#include "LocalPoolDataSetBase.h" +#include "../objectmanager/SystemObjectIF.h" +#include + +/** + * @brief This local dataset type is created on the stack. + * @details + * This will is the primary data structure to organize pool variables into + * sets which can be accessed via the housekeeping service interface or + * which can be sent to other software objects. + * + * It is recommended to read the documentation of the LocalPoolDataSetBase + * class for more information on how this class works and how to use it. + * @tparam capacity Capacity of the static dataset, which is usually known + * beforehand. + */ +template +class StaticLocalDataSet: public LocalPoolDataSetBase { +public: + /** + * Constructor used by data owner and creator like device handlers. + * This constructor also initialized the components required for + * periodic handling. + * @param hkOwner + * @param setId + */ + StaticLocalDataSet(HasLocalDataPoolIF* hkOwner, + uint32_t setId): LocalPoolDataSetBase(hkOwner, setId, nullptr, + NUM_VARIABLES) { + this->setContainer(poolVarList.data()); + } + + /** + * Constructor used by data users like controllers. + * @param hkOwner + * @param setId + */ + StaticLocalDataSet(sid_t sid): LocalPoolDataSetBase(sid, nullptr, + NUM_VARIABLES) { + this->setContainer(poolVarList.data()); + } + +private: + std::array poolVarList; +}; + +#endif /* FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_ */ diff --git a/housekeeping/AcceptsHkPacketsIF.h b/housekeeping/AcceptsHkPacketsIF.h new file mode 100644 index 00000000..b3ba6e7c --- /dev/null +++ b/housekeeping/AcceptsHkPacketsIF.h @@ -0,0 +1,11 @@ +#ifndef FRAMEWORK_HOUSEKEEPING_ACCEPTSHKPACKETSIF_H_ +#define FRAMEWORK_HOUSEKEEPING_ACCEPTSHKPACKETSIF_H_ +#include "../ipc/MessageQueueMessageIF.h" + +class AcceptsHkPacketsIF { +public: + virtual~ AcceptsHkPacketsIF() {}; + virtual MessageQueueId_t getHkQueue() const = 0; +}; + +#endif /* FRAMEWORK_HOUSEKEEPING_ACCEPTSHKPACKETSIF_H_ */ diff --git a/housekeeping/HousekeepingMessage.cpp b/housekeeping/HousekeepingMessage.cpp new file mode 100644 index 00000000..d2ab546b --- /dev/null +++ b/housekeeping/HousekeepingMessage.cpp @@ -0,0 +1,162 @@ +#include +#include "HousekeepingMessage.h" +#include + +HousekeepingMessage::~HousekeepingMessage() {} + +void HousekeepingMessage::setHkReportReply(CommandMessage* message, sid_t sid, + store_address_t storeId) { + message->setCommand(HK_REPORT); + message->setMessageSize(HK_MESSAGE_SIZE); + setSid(message, sid); + message->setParameter3(storeId.raw); +} + +void HousekeepingMessage::setHkDiagnosticsReply(CommandMessage* message, + sid_t sid, store_address_t storeId) { + message->setCommand(DIAGNOSTICS_REPORT); + message->setMessageSize(HK_MESSAGE_SIZE); + setSid(message, sid); + message->setParameter3(storeId.raw); +} + +sid_t HousekeepingMessage::getHkDataReply(const CommandMessage *message, + store_address_t *storeIdToSet) { + if(storeIdToSet != nullptr) { + *storeIdToSet = message->getParameter3(); + } + return getSid(message); +} + +void HousekeepingMessage::setToggleReportingCommand(CommandMessage *message, + sid_t sid, bool enableReporting, bool isDiagnostics) { + if(isDiagnostics) { + if(enableReporting) { + message->setCommand(ENABLE_PERIODIC_DIAGNOSTICS_GENERATION); + } + else { + message->setCommand(DISABLE_PERIODIC_DIAGNOSTICS_GENERATION); + } + } + else { + if(enableReporting) { + message->setCommand(ENABLE_PERIODIC_HK_REPORT_GENERATION); + } + else { + message->setCommand(DISABLE_PERIODIC_HK_REPORT_GENERATION); + } + } + + setSid(message, sid); +} + +void HousekeepingMessage::setStructureReportingCommand(CommandMessage *command, + sid_t sid, bool isDiagnostics) { + if(isDiagnostics) { + command->setCommand(REPORT_DIAGNOSTICS_REPORT_STRUCTURES); + } + else { + command->setCommand(REPORT_HK_REPORT_STRUCTURES); + } + + setSid(command, sid); +} + +void HousekeepingMessage::setOneShotReportCommand(CommandMessage *command, + sid_t sid, bool isDiagnostics) { + if(isDiagnostics) { + command->setCommand(GENERATE_ONE_DIAGNOSTICS_REPORT); + } + else { + command->setCommand(GENERATE_ONE_PARAMETER_REPORT); + } + + setSid(command, sid); +} + +void HousekeepingMessage::setCollectionIntervalModificationCommand( + CommandMessage *command, sid_t sid, float collectionInterval, + bool isDiagnostics) { + if(isDiagnostics) { + command->setCommand(MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL); + } + else { + command->setCommand(MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL); + } + command->setParameter3(collectionInterval); + + setSid(command, sid); +} + +sid_t HousekeepingMessage::getCollectionIntervalModificationCommand( + const CommandMessage* command, float* newCollectionInterval) { + if(newCollectionInterval != nullptr) { + *newCollectionInterval = command->getParameter3(); + } + + return getSid(command); +} + +void HousekeepingMessage::setHkRequestSuccessReply(CommandMessage *reply, + sid_t sid) { + setSid(reply, sid); + reply->setCommand(HK_REQUEST_SUCCESS); +} + +void HousekeepingMessage::setHkRequestFailureReply(CommandMessage *reply, + sid_t sid, ReturnValue_t error) { + setSid(reply, sid); + reply->setCommand(HK_REQUEST_FAILURE); + reply->setParameter3(error); +} + +sid_t HousekeepingMessage::getHkRequestFailureReply(const CommandMessage *reply, + ReturnValue_t *error) { + if(error != nullptr) { + *error = reply->getParameter3(); + } + return getSid(reply); +} + +sid_t HousekeepingMessage::getSid(const CommandMessage* message) { + sid_t sid; + std::memcpy(&sid.raw, message->getData(), sizeof(sid.raw)); + return sid; +} + +void HousekeepingMessage::setSid(CommandMessage *message, sid_t sid) { + std::memcpy(message->getData(), &sid.raw, sizeof(sid.raw)); +} + +void HousekeepingMessage::setHkStuctureReportReply(CommandMessage *reply, + sid_t sid, store_address_t storeId) { + reply->setCommand(HK_DEFINITIONS_REPORT); + setSid(reply, sid); + reply->setParameter3(storeId.raw); +} + +void HousekeepingMessage::setDiagnosticsStuctureReportReply( + CommandMessage *reply, sid_t sid, store_address_t storeId) { + reply->setCommand(DIAGNOSTICS_DEFINITION_REPORT); + setSid(reply, sid); + reply->setParameter3(storeId.raw); +} + +void HousekeepingMessage::clear(CommandMessage* message) { + switch(message->getCommand()) { + case(HK_REPORT): + case(DIAGNOSTICS_REPORT): + case(HK_DEFINITIONS_REPORT): + case(DIAGNOSTICS_DEFINITION_REPORT): + case(UPDATE_SNAPSHOT): { + store_address_t storeId; + getHkDataReply(message, &storeId); + StorageManagerIF *ipcStore = objectManager->get( + objects::IPC_STORE); + if (ipcStore != nullptr) { + ipcStore->deleteData(storeId); + } + } + } + message->setCommand(CommandMessage::CMD_NONE); +} diff --git a/housekeeping/HousekeepingMessage.h b/housekeeping/HousekeepingMessage.h new file mode 100644 index 00000000..6dc95f54 --- /dev/null +++ b/housekeeping/HousekeepingMessage.h @@ -0,0 +1,157 @@ +#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGMESSAGE_H_ +#define FSFW_HOUSEKEEPING_HOUSEKEEPINGMESSAGE_H_ + +#include "../ipc/CommandMessage.h" +#include "../ipc/FwMessageTypes.h" +#include "../objectmanager/frameworkObjects.h" +#include "../objectmanager/SystemObjectIF.h" +#include "../storagemanager/StorageManagerIF.h" + +union sid_t { + static constexpr uint64_t INVALID_SID = -1; + static constexpr uint32_t INVALID_SET_ID = -1; + static constexpr uint32_t INVALID_OBJECT_ID = objects::NO_OBJECT; + sid_t(): raw(INVALID_SID) {} + + sid_t(object_id_t objectId, uint32_t setId): + objectId(objectId), + ownerSetId(setId) {} + + struct { + object_id_t objectId ; + /** + * A generic 32 bit ID to identify unique HK packets for a single + * object. For example, the DeviceCommandId_t is used for + * DeviceHandlers + */ + uint32_t ownerSetId; + }; + /** + * Alternative access to the raw value. This is also the size of the type. + */ + uint64_t raw; + + bool notSet() const { + return raw == INVALID_SID; + } + + bool operator==(const sid_t& other) const { + return raw == other.raw; + } + + bool operator!=(const sid_t& other) const { + return not (raw == other.raw); + } +}; + + +/** + * @brief Special command message type for housekeeping messages + * @details + * This message is slightly larger than regular command messages to accomodate + * the uint64_t structure ID (SID). + */ +class HousekeepingMessage { +public: + + static constexpr size_t HK_MESSAGE_SIZE = CommandMessageIF::HEADER_SIZE + + sizeof(sid_t) + sizeof(uint32_t); + + /** + * Concrete instance is not used, instead this class operates on + * command message instances. + */ + HousekeepingMessage() = delete; + virtual ~HousekeepingMessage(); + + static constexpr uint8_t MESSAGE_ID = messagetypes::HOUSEKEEPING; + + static constexpr Command_t ENABLE_PERIODIC_HK_REPORT_GENERATION = + MAKE_COMMAND_ID(5); + static constexpr Command_t DISABLE_PERIODIC_HK_REPORT_GENERATION = + MAKE_COMMAND_ID(6); + + static constexpr Command_t ENABLE_PERIODIC_DIAGNOSTICS_GENERATION = + MAKE_COMMAND_ID(7); + static constexpr Command_t DISABLE_PERIODIC_DIAGNOSTICS_GENERATION = + MAKE_COMMAND_ID(8); + + static constexpr Command_t REPORT_HK_REPORT_STRUCTURES = MAKE_COMMAND_ID(9); + static constexpr Command_t REPORT_DIAGNOSTICS_REPORT_STRUCTURES = + MAKE_COMMAND_ID(11); + + static constexpr Command_t HK_DEFINITIONS_REPORT = MAKE_COMMAND_ID(10); + static constexpr Command_t DIAGNOSTICS_DEFINITION_REPORT = MAKE_COMMAND_ID(12); + + static constexpr Command_t HK_REPORT = MAKE_COMMAND_ID(25); + static constexpr Command_t DIAGNOSTICS_REPORT = MAKE_COMMAND_ID(26); + + static constexpr Command_t GENERATE_ONE_PARAMETER_REPORT = + MAKE_COMMAND_ID(27); + static constexpr Command_t GENERATE_ONE_DIAGNOSTICS_REPORT = + MAKE_COMMAND_ID(28); + + static constexpr Command_t MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL = + MAKE_COMMAND_ID(31); + static constexpr Command_t MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL = + MAKE_COMMAND_ID(32); + + static constexpr Command_t HK_REQUEST_SUCCESS = + MAKE_COMMAND_ID(128); + static constexpr Command_t HK_REQUEST_FAILURE = + MAKE_COMMAND_ID(129); + + static constexpr Command_t UPDATE_NOTIFICATION = MAKE_COMMAND_ID(130); + static constexpr Command_t UPDATE_SNAPSHOT = MAKE_COMMAND_ID(131); + + static constexpr Command_t UPDATE_HK_REPORT = MAKE_COMMAND_ID(132); + + static sid_t getSid(const CommandMessage* message); + + /** Setter functions */ + static void setToggleReportingCommand(CommandMessage* command, sid_t sid, + bool enableReporting, bool isDiagnostics); + static void setStructureReportingCommand(CommandMessage* command, sid_t sid, + bool isDiagnostics); + static void setOneShotReportCommand(CommandMessage* command, sid_t sid, + bool isDiagnostics); + static void setCollectionIntervalModificationCommand( + CommandMessage* command, sid_t sid, float collectionInterval, + bool isDiagnostics); + + static void setHkReportReply(CommandMessage* reply, sid_t sid, + store_address_t storeId); + static void setHkDiagnosticsReply(CommandMessage* reply, sid_t sid, + store_address_t storeId); + + static void setHkRequestSuccessReply(CommandMessage* reply, sid_t sid); + static void setHkRequestFailureReply(CommandMessage* reply, sid_t sid, + ReturnValue_t error); + + static void setHkStuctureReportReply(CommandMessage* reply, + sid_t sid, store_address_t storeId); + static void setDiagnosticsStuctureReportReply(CommandMessage* reply, + sid_t sid, store_address_t storeId); + + static sid_t getHkRequestFailureReply(const CommandMessage* reply, + ReturnValue_t* error); + + /** + * @brief Generic getter function for housekeeping data replies + * @details + * Command ID can be used beforehand to distinguish between diagnostics and + * regular HK packets. This getter function should be used for the + * command IDs 10, 12, 25 and 26. + */ + static sid_t getHkDataReply(const CommandMessage* message, + store_address_t * storeIdToSet); + static sid_t getCollectionIntervalModificationCommand( + const CommandMessage* command, float* newCollectionInterval); + + static void clear(CommandMessage* message); +private: + static void setSid(CommandMessage* message, sid_t sid); +}; + + +#endif /* FSFW_HOUSEKEEPING_HOUSEKEEPINGMESSAGE_H_ */ diff --git a/housekeeping/HousekeepingPacketDownlink.h b/housekeeping/HousekeepingPacketDownlink.h new file mode 100644 index 00000000..ae0cc988 --- /dev/null +++ b/housekeeping/HousekeepingPacketDownlink.h @@ -0,0 +1,34 @@ +#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETDOWNLINK_H_ +#define FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETDOWNLINK_H_ + +#include "../datapoollocal/LocalPoolDataSetBase.h" +#include "../serialize/SerialLinkedListAdapter.h" +#include "../storagemanager/StorageManagerIF.h" + +/** + * @brief This class will be used to serialize general housekeeping packets + * which are destined to be downlinked into the store. + * @details + * The housekeeping packets are stored into the IPC store and forwarded + * to the designated housekeeping handler. + */ +class HousekeepingPacketDownlink: public SerialLinkedListAdapter { +public: + HousekeepingPacketDownlink(sid_t sid, LocalPoolDataSetBase* dataSetPtr): + sourceId(sid.objectId), setId(sid.ownerSetId), hkData(dataSetPtr) { + setLinks(); + } + +private: + void setLinks() { + setStart(&sourceId); + sourceId.setNext(&setId); + setId.setNext(&hkData); + } + + SerializeElement sourceId; + SerializeElement setId; + LinkedElement hkData; +}; + +#endif /* FRAMEWORK_HOUSEKEEPING_HOUSEKEEPINGPACKETDOWNLINK_H_ */ diff --git a/housekeeping/HousekeepingPacketUpdate.h b/housekeeping/HousekeepingPacketUpdate.h new file mode 100644 index 00000000..eebdc11c --- /dev/null +++ b/housekeeping/HousekeepingPacketUpdate.h @@ -0,0 +1,73 @@ +#ifndef FRAMEWORK_HOUSEKEEPING_HOUSEKEEPINGPACKETUPDATE_H_ +#define FRAMEWORK_HOUSEKEEPING_HOUSEKEEPINGPACKETUPDATE_H_ + +#include "../serialize/SerialBufferAdapter.h" +#include "../serialize/SerialLinkedListAdapter.h" +#include "../datapoollocal/LocalPoolDataSetBase.h" + +/** + * @brief This helper class will be used to serialize and deserialize + * update housekeeping packets into the store. + */ +class HousekeepingPacketUpdate: public SerializeIF { +public: + /** + * @param timeStamp + * @param timeStampSize + * @param hkData + * @param hkDataSize + */ + HousekeepingPacketUpdate(uint8_t* timeStamp, size_t timeStampSize, + LocalPoolDataSetBase* dataSetPtr): + timeStamp(timeStamp), timeStampSize(timeStampSize), + dataSetPtr(dataSetPtr) {}; + + virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, + size_t maxSize, Endianness streamEndianness) const { + if(timeStamp != nullptr) { + /* Endianness will always be MACHINE, so we can simply use memcpy + here. */ + std::memcpy(*buffer, timeStamp, timeStampSize); + *size += timeStampSize; + *buffer += timeStampSize; + } + if(dataSetPtr == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + + return dataSetPtr->serialize(buffer, size, maxSize, streamEndianness); + } + + virtual size_t getSerializedSize() const { + if(dataSetPtr == nullptr) { + return 0; + } + return timeStampSize + dataSetPtr->getSerializedSize(); + } + + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) override { + if(timeStamp != nullptr) { + /* Endianness will always be MACHINE, so we can simply use memcpy + here. */ + std::memcpy(timeStamp, *buffer, timeStampSize); + *size += timeStampSize; + *buffer += timeStampSize; + } + + if(dataSetPtr == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + return dataSetPtr->deSerialize(buffer, size, streamEndianness); + } + +private: + uint8_t* timeStamp; + size_t timeStampSize; + + LocalPoolDataSetBase* dataSetPtr = nullptr; +}; + + + +#endif /* FRAMEWORK_HOUSEKEEPING_HOUSEKEEPINGPACKETUPDATE_H_ */ diff --git a/housekeeping/HousekeepingSetPacket.h b/housekeeping/HousekeepingSetPacket.h new file mode 100644 index 00000000..f94720d4 --- /dev/null +++ b/housekeeping/HousekeepingSetPacket.h @@ -0,0 +1,59 @@ +#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGSETPACKET_H_ +#define FSFW_HOUSEKEEPING_HOUSEKEEPINGSETPACKET_H_ + +#include "../housekeeping/HousekeepingMessage.h" +#include "../serialize/SerialLinkedListAdapter.h" +#include "../datapoollocal/LocalPoolDataSetBase.h" + +class HousekeepingSetPacket: public SerialLinkedListAdapter { +public: + HousekeepingSetPacket(sid_t sid, bool reportingEnabled, bool valid, + float collectionInterval, LocalPoolDataSetBase* dataSetPtr): + objectId(sid.objectId), setId(sid.ownerSetId), + reportingEnabled(reportingEnabled), valid(valid), + collectionIntervalSeconds(collectionInterval), dataSet(dataSetPtr) { + setLinks(); + } + + ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const override { + ReturnValue_t result = SerialLinkedListAdapter::serialize(buffer, size, + maxSize, streamEndianness); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return dataSet->serializeLocalPoolIds(buffer, size ,maxSize, + streamEndianness); + } + + size_t getSerializedSize() const override { + size_t linkedSize = SerialLinkedListAdapter::getSerializedSize(); + linkedSize += dataSet->getLocalPoolIdsSerializedSize(); + return linkedSize; + } + + ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override { + return HasReturnvaluesIF::RETURN_OK; + } + +private: + + void setLinks() { + setStart(&objectId); + objectId.setNext(&setId); + setId.setNext(&reportingEnabled); + reportingEnabled.setNext(&valid); + valid.setNext(&collectionIntervalSeconds); + collectionIntervalSeconds.setEnd(); + } + + SerializeElement objectId; + SerializeElement setId; + SerializeElement reportingEnabled; + SerializeElement valid; + SerializeElement collectionIntervalSeconds; + LocalPoolDataSetBase* dataSet; +}; + +#endif /* FSFW_HOUSEKEEPING_HOUSEKEEPINGSETPACKET_H_ */ diff --git a/housekeeping/PeriodicHousekeepingHelper.cpp b/housekeeping/PeriodicHousekeepingHelper.cpp new file mode 100644 index 00000000..37349f81 --- /dev/null +++ b/housekeeping/PeriodicHousekeepingHelper.cpp @@ -0,0 +1,48 @@ +#include "../datapoollocal/LocalPoolDataSetBase.h" +#include "PeriodicHousekeepingHelper.h" +#include + +PeriodicHousekeepingHelper::PeriodicHousekeepingHelper( + LocalPoolDataSetBase* owner): owner(owner) {} + + +void PeriodicHousekeepingHelper::initialize(float collectionInterval, + dur_millis_t minimumPeriodicInterval, bool isDiagnostics, + uint8_t nonDiagIntervalFactor) { + this->minimumPeriodicInterval = minimumPeriodicInterval; + if(not isDiagnostics) { + this->minimumPeriodicInterval = this->minimumPeriodicInterval * + nonDiagIntervalFactor; + } + collectionIntervalTicks = intervalSecondsToInterval(collectionInterval); +} + +float PeriodicHousekeepingHelper::getCollectionIntervalInSeconds() { + return intervalToIntervalSeconds(collectionIntervalTicks); +} + +bool PeriodicHousekeepingHelper::checkOpNecessary() { + if(internalTickCounter >= collectionIntervalTicks) { + internalTickCounter = 1; + return true; + } + internalTickCounter++; + return false; +} + +uint32_t PeriodicHousekeepingHelper::intervalSecondsToInterval( + float collectionIntervalSeconds) { + return std::ceil(collectionIntervalSeconds * 1000 + / minimumPeriodicInterval); +} + +float PeriodicHousekeepingHelper::intervalToIntervalSeconds( + uint32_t collectionInterval) { + return static_cast(collectionInterval * + minimumPeriodicInterval); +} + +void PeriodicHousekeepingHelper::changeCollectionInterval( + float newIntervalSeconds) { + collectionIntervalTicks = intervalSecondsToInterval(newIntervalSeconds); +} diff --git a/housekeeping/PeriodicHousekeepingHelper.h b/housekeeping/PeriodicHousekeepingHelper.h new file mode 100644 index 00000000..d96eae1d --- /dev/null +++ b/housekeeping/PeriodicHousekeepingHelper.h @@ -0,0 +1,32 @@ +#ifndef FSFW_HOUSEKEEPING_PERIODICHOUSEKEEPINGHELPER_H_ +#define FSFW_HOUSEKEEPING_PERIODICHOUSEKEEPINGHELPER_H_ + +#include "../timemanager/Clock.h" +#include + +class LocalPoolDataSetBase; + +class PeriodicHousekeepingHelper { +public: + PeriodicHousekeepingHelper(LocalPoolDataSetBase* owner); + + void initialize(float collectionInterval, + dur_millis_t minimumPeriodicInterval, bool isDiagnostics, + uint8_t nonDiagIntervalFactor); + + void changeCollectionInterval(float newInterval); + float getCollectionIntervalInSeconds(); + bool checkOpNecessary(); +private: + LocalPoolDataSetBase* owner = nullptr; + + uint32_t intervalSecondsToInterval(float collectionIntervalSeconds); + float intervalToIntervalSeconds(uint32_t collectionInterval); + + dur_millis_t minimumPeriodicInterval = 0; + uint32_t internalTickCounter = 1; + uint32_t collectionIntervalTicks = 0; + +}; + +#endif /* FSFW_HOUSEKEEPING_PERIODICHOUSEKEEPINGHELPER_H_ */ From a43e8ea60333627ca085b54c127f0b0acdddd601 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 1 Oct 2020 12:27:28 +0200 Subject: [PATCH 410/653] added srv3 object ID --- objectmanager/frameworkObjects.h | 1 + 1 file changed, 1 insertion(+) diff --git a/objectmanager/frameworkObjects.h b/objectmanager/frameworkObjects.h index 4d08f084..57783286 100644 --- a/objectmanager/frameworkObjects.h +++ b/objectmanager/frameworkObjects.h @@ -6,6 +6,7 @@ enum framework_objects { // Default verification reporter. PUS_SERVICE_1_VERIFICATION = 0x53000001, PUS_SERVICE_2_DEVICE_ACCESS = 0x53000002, + PUS_SERVICE_3_HOUSEKEEPING = 0x53000003, PUS_SERVICE_5_EVENT_REPORTING = 0x53000005, PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008, PUS_SERVICE_9_TIME_MGMT = 0x53000009, From 322ff54f58d1ce3c214e1b240f418d543e93a320 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 1 Oct 2020 12:28:25 +0200 Subject: [PATCH 411/653] added new message types --- ipc/FwMessageTypes.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ipc/FwMessageTypes.h b/ipc/FwMessageTypes.h index e820b1df..8b49c122 100644 --- a/ipc/FwMessageTypes.h +++ b/ipc/FwMessageTypes.h @@ -3,7 +3,7 @@ namespace messagetypes { //Remember to add new Message Types to the clearCommandMessage function! -enum FW_MESSAGE_TYPE { +enum FsfwMessageTypes { COMMAND = 0, MODE_COMMAND, HEALTH_COMMAND, @@ -14,7 +14,10 @@ enum FW_MESSAGE_TYPE { MONITORING, MEMORY, PARAMETER, - FW_MESSAGES_COUNT + FILE_SYSTEM_MESSAGE, + HOUSEKEEPING, + + FW_MESSAGES_COUNT, }; } From 196cde4075e92bd1053c136720acb3a3c6cd62f2 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 1 Oct 2020 12:30:53 +0200 Subject: [PATCH 412/653] DHB update --- devicehandlers/DeviceHandlerBase.cpp | 171 +++++++++++++++++++-------- devicehandlers/DeviceHandlerBase.h | 170 ++++++++++++++------------ 2 files changed, 214 insertions(+), 127 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 6fcba64b..227d5b6d 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -2,15 +2,17 @@ #include "AcceptsDeviceResponsesIF.h" #include "DeviceTmReportingWrapper.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../datapoolglob/GlobalDataSet.h" +#include "../datapoolglob/GlobalPoolVariable.h" #include "../objectmanager/ObjectManager.h" #include "../storagemanager/StorageManagerIF.h" #include "../thermal/ThermalComponentIF.h" -#include "../datapoolglob/GlobalDataSet.h" -#include "../datapoolglob/GlobalPoolVariable.h" #include "../globalfunctions/CRC.h" -#include "../subsystem/SubsystemBase.h" +#include "../housekeeping/HousekeepingMessage.h" +#include "../ipc/MessageQueueMessage.h" #include "../ipc/QueueFactory.h" -#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../subsystem/SubsystemBase.h" #include @@ -25,10 +27,11 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, wiretappingMode(OFF), storedRawData(StorageManagerIF::INVALID_ADDRESS), deviceCommunicationId(deviceCommunication), comCookie(comCookie), healthHelper(this,setObjectId), modeHelper(this), parameterHelper(this), - actionHelper(this, nullptr), childTransitionFailure(RETURN_OK), - fdirInstance(fdirInstance), hkSwitcher(this), - defaultFDIRUsed(fdirInstance == nullptr), switchOffWasReported(false), - childTransitionDelay(5000), transitionSourceMode(_MODE_POWER_DOWN), + actionHelper(this, nullptr), hkManager(this, nullptr), + childTransitionFailure(RETURN_OK), fdirInstance(fdirInstance), + hkSwitcher(this), defaultFDIRUsed(fdirInstance == nullptr), + switchOffWasReported(false), childTransitionDelay(5000), + transitionSourceMode(_MODE_POWER_DOWN), transitionSourceSubMode(SUBMODE_NONE) { commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE); @@ -48,6 +51,10 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, } } +void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) { + this->hkDestination = hkDestination; +} + void DeviceHandlerBase::setThermalStateRequestPoolIds( uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId) { this->deviceThermalRequestPoolId = thermalStatePoolId; @@ -74,6 +81,7 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { decrementDeviceReplyMap(); fdirInstance->checkForFailures(); hkSwitcher.performOperation(); + hkManager.performHkOperation(); performOperationHook(); } if (mode == MODE_OFF) { @@ -120,7 +128,9 @@ ReturnValue_t DeviceHandlerBase::initialize() { result = communicationInterface->initializeInterface(comCookie); if (result != RETURN_OK) { - return result; + sif::error << "DeviceHandlerBase::initialize: Initializing " + "communication interface failed!" << std::endl; + return result; } IPCStore = objectManager->get(objects::IPC_STORE); @@ -183,11 +193,16 @@ ReturnValue_t DeviceHandlerBase::initialize() { return result; } + result = hkManager.initialize(commandQueue); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + fillCommandAndReplyMap(); //Set temperature target state to NON_OP. GlobDataSet mySet; - gp_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, + gp_uint8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_WRITE); mySet.read(); thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; @@ -245,10 +260,10 @@ void DeviceHandlerBase::readCommandQueue() { return; } -// result = hkManager.handleHousekeepingMessage(&command); -// if (result == RETURN_OK) { -// return; -// } + result = hkManager.handleHousekeepingMessage(&command); + if (result == RETURN_OK) { + return; + } result = handleDeviceHandlerMessage(&command); if (result == RETURN_OK) { @@ -376,24 +391,28 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode, ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap( DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, - size_t replyLen, bool periodic, bool hasDifferentReplyId, - DeviceCommandId_t replyId) { + LocalPoolDataSetBase* replyDataSet, size_t replyLen, bool periodic, + bool hasDifferentReplyId, DeviceCommandId_t replyId) { //No need to check, as we may try to insert multiple times. insertInCommandMap(deviceCommand); if (hasDifferentReplyId) { - return insertInReplyMap(replyId, maxDelayCycles, replyLen, periodic); + return insertInReplyMap(replyId, maxDelayCycles, + replyDataSet, replyLen, periodic); } else { - return insertInReplyMap(deviceCommand, maxDelayCycles, replyLen, periodic); + return insertInReplyMap(deviceCommand, maxDelayCycles, + replyDataSet, replyLen, periodic); } } ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId, - uint16_t maxDelayCycles, size_t replyLen, bool periodic) { + uint16_t maxDelayCycles, LocalPoolDataSetBase* dataSet, + size_t replyLen, bool periodic) { DeviceReplyInfo info; info.maxDelayCycles = maxDelayCycles; info.periodic = periodic; info.delayCycles = 0; info.replyLen = replyLen; + info.dataSet = dataSet; info.command = deviceCommandMap.end(); auto resultPair = deviceReplyMap.emplace(replyId, info); if (resultPair.second) { @@ -419,13 +438,12 @@ ReturnValue_t DeviceHandlerBase::insertInCommandMap( ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply, uint16_t delayCycles, uint16_t maxDelayCycles, bool periodic) { - std::map::iterator iter = - deviceReplyMap.find(deviceReply); - if (iter == deviceReplyMap.end()) { + auto replyIter = deviceReplyMap.find(deviceReply); + if (replyIter == deviceReplyMap.end()) { triggerEvent(INVALID_DEVICE_COMMAND, deviceReply); return RETURN_FAILED; } else { - DeviceReplyInfo *info = &(iter->second); + DeviceReplyInfo *info = &(replyIter->second); if (maxDelayCycles != 0) { info->maxDelayCycles = maxDelayCycles; } @@ -435,6 +453,17 @@ ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceRep } } + +ReturnValue_t DeviceHandlerBase::setReplyDataset(DeviceCommandId_t replyId, + LocalPoolDataSetBase *dataSet) { + auto replyIter = deviceReplyMap.find(replyId); + if(replyIter == deviceReplyMap.end()) { + return HasReturnvaluesIF::RETURN_FAILED; + } + replyIter->second.dataSet = dataSet; + return HasReturnvaluesIF::RETURN_OK; +} + void DeviceHandlerBase::callChildStatemachine() { if (mode == _MODE_START_UP) { doStartUp(); @@ -470,7 +499,7 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) { if (mode == MODE_OFF) { GlobDataSet mySet; - gp_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, + gp_uint8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { @@ -649,7 +678,7 @@ void DeviceHandlerBase::doGetRead() { void DeviceHandlerBase::parseReply(const uint8_t* receivedData, size_t receivedDataLen) { ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; - DeviceCommandId_t foundId = 0xFFFFFFFF; + DeviceCommandId_t foundId = 0xffffffff; size_t foundLen = 0; // The loop may not execute more often than the number of received bytes // (worst case). This approach avoids infinite loops due to buggy @@ -661,18 +690,26 @@ void DeviceHandlerBase::parseReply(const uint8_t* receivedData, switch (result) { case RETURN_OK: handleReply(receivedData, foundId, foundLen); + if(foundLen == 0) { + sif::warning << "DeviceHandlerBase::parseReply: foundLen is 0!" + " Packet parsing will be stuck." << std::endl; + } break; case APERIODIC_REPLY: { result = interpretDeviceReply(foundId, receivedData); if (result != RETURN_OK) { - replyRawReplyIfnotWiretapped(receivedData, foundLen); - triggerEvent(DEVICE_INTERPRETING_REPLY_FAILED, result, - foundId); + replyRawReplyIfnotWiretapped(receivedData, foundLen); + triggerEvent(DEVICE_INTERPRETING_REPLY_FAILED, result, + foundId); + } + if(foundLen == 0) { + sif::warning << "DeviceHandlerBase::parseReply: foundLen is 0!" + " Packet parsing will be stuck." << std::endl; } - } - break; - case IGNORE_REPLY_DATA: break; + } + case IGNORE_REPLY_DATA: + continue; case IGNORE_FULL_PACKET: return; default: @@ -704,16 +741,19 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, DeviceReplyInfo *info = &(iter->second); if (info->delayCycles != 0) { + result = interpretDeviceReply(foundId, receivedData); - if (info->periodic != false) { + if(result == IGNORE_REPLY_DATA) { + return; + } + + if (info->periodic) { info->delayCycles = info->maxDelayCycles; } else { info->delayCycles = 0; } - result = interpretDeviceReply(foundId, receivedData); - if (result != RETURN_OK) { // Report failed interpretation to FDIR. replyRawReplyIfnotWiretapped(receivedData, foundLen); @@ -927,9 +967,9 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, if ((commandedMode == MODE_ON) && (mode == MODE_OFF) && (deviceThermalStatePoolId != PoolVariableIF::NO_PARAMETER)) { GlobDataSet mySet; - gp_int8_t thermalState(deviceThermalStatePoolId, &mySet, + gp_uint8_t thermalState(deviceThermalStatePoolId, &mySet, PoolVariableIF::VAR_READ); - gp_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, + gp_uint8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_READ); mySet.read(); if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { @@ -1089,19 +1129,6 @@ ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage( } replyReturnvalueToCommand(RETURN_OK); return RETURN_OK; -// case DeviceHandlerMessage::CMD_SWITCH_IOBOARD: -// if (mode != MODE_OFF) { -// replyReturnvalueToCommand(WRONG_MODE_FOR_COMMAND); -// } else { -// result = switchCookieChannel( -// DeviceHandlerMessage::getIoBoardObjectId(message)); -// if (result == RETURN_OK) { -// replyReturnvalueToCommand(RETURN_OK); -// } else { -// replyReturnvalueToCommand(CANT_SWITCH_IO_ADDRESS); -// } -// } -// return RETURN_OK; case DeviceHandlerMessage::CMD_RAW: if ((mode != MODE_RAW)) { DeviceHandlerMessage::clear(message); @@ -1248,10 +1275,14 @@ void DeviceHandlerBase::buildInternalCommand(void) { if (iter == deviceCommandMap.end()) { result = COMMAND_NOT_SUPPORTED; } else if (iter->second.isExecuting) { + //so we can track misconfigurations sif::debug << std::hex << getObjectId() << ": 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 + << deviceCommandId << " isExecuting" << std::dec + << std::endl; + // 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 + return; } else { iter->second.sendReplyTo = NO_COMMANDER; iter->second.isExecuting = true; @@ -1340,12 +1371,50 @@ void DeviceHandlerBase::debugInterface(uint8_t positionTracker, void DeviceHandlerBase::performOperationHook() { } +ReturnValue_t DeviceHandlerBase::initializeLocalDataPool( + LocalDataPool &localDataPoolMap, + LocalDataPoolManager& poolManager) { + return RETURN_OK; +} + +LocalDataPoolManager* DeviceHandlerBase::getHkManagerHandle() { + return &hkManager; +} + + ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() { // In this function, the task handle should be valid if the task // was implemented correctly. We still check to be 1000 % sure :-) if(executingTask != nullptr) { pstIntervalMs = executingTask->getPeriodMs(); } + this->hkManager.initializeAfterTaskCreation(); + + if(setStartupImmediately) { + startTransition(MODE_ON, SUBMODE_NONE); + } return HasReturnvaluesIF::RETURN_OK; } +LocalPoolDataSetBase* DeviceHandlerBase::getDataSetHandle(sid_t sid) { + auto iter = deviceReplyMap.find(sid.ownerSetId); + if(iter != deviceReplyMap.end()) { + return iter->second.dataSet; + } + else { + return nullptr; + } +} + +object_id_t DeviceHandlerBase::getObjectId() const { + return SystemObject::getObjectId(); +} + +void DeviceHandlerBase::setStartUpImmediately() { + this->setStartupImmediately = true; +} + +dur_millis_t DeviceHandlerBase::getPeriodicOperationFrequency() const { + return pstIntervalMs; +} + diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 5666f35e..eda318cb 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -1,12 +1,11 @@ -#ifndef FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ -#define FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ +#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ +#define FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ #include "DeviceHandlerIF.h" #include "DeviceCommunicationIF.h" #include "DeviceHandlerFailureIsolation.h" #include "../objectmanager/SystemObject.h" -#include "../tasks/PeriodicTaskIF.h" #include "../tasks/ExecutableObjectIF.h" #include "../returnvalues/HasReturnvaluesIF.h" #include "../action/HasActionsIF.h" @@ -14,10 +13,13 @@ #include "../modes/HasModesIF.h" #include "../power/PowerSwitchIF.h" #include "../ipc/MessageQueueIF.h" +#include "../tasks/PeriodicTaskIF.h" #include "../action/ActionHelper.h" #include "../health/HealthHelper.h" #include "../parameters/ParameterHelper.h" #include "../datapool/HkSwitchHelper.h" +#include "../datapoollocal/HasLocalDataPoolIF.h" +#include "../datapoollocal/LocalDataPoolManager.h" #include @@ -38,17 +40,16 @@ class StorageManagerIF; * Documentation: Dissertation Baetz p.138,139, p.141-149 * * It features handling of @link DeviceHandlerIF::Mode_t Modes @endlink, - * communication with physical devices, using the @link DeviceCommunicationIF @endlink, - * and communication with commanding objects. - * It inherits SystemObject and thus can be created by the ObjectManagerIF. + * communication with physical devices, using the + * @link DeviceCommunicationIF @endlink, and communication with commanding + * objects. 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 (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. - * NOTE: RMAP is a standard which is used for FLP. + * This class uses the opcode of ExecutableObjectIF to perform a + * step-wise execution. For each step a different action is selected and + * executed. Currently, the device handler base performs a 4-step + * execution related to 4 communication steps (based on RMAP). + * NOTE: RMAP is a standard which is used for Flying Laptop. * 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. @@ -69,9 +70,6 @@ class StorageManagerIF; * * Other important virtual methods with a default implementation * are the getTransitionDelayMs() function and the getSwitches() function. - * Please ensure that getSwitches() returns DeviceHandlerIF::NO_SWITCHES if - * power switches are not implemented yet. Otherwise, the device handler will - * not transition to MODE_ON, even if setMode(MODE_ON) is called. * If a transition to MODE_ON is desired without commanding, override the * intialize() function and call setMode(_MODE_START_UP) before calling * DeviceHandlerBase::initialize(). @@ -85,20 +83,18 @@ class DeviceHandlerBase: public DeviceHandlerIF, public HasModesIF, public HasHealthIF, public HasActionsIF, - public ReceivesParameterMessagesIF { + public ReceivesParameterMessagesIF, + public HasLocalDataPoolIF { friend void (Factory::setStaticFrameworkObjectIds)(); public: /** * The constructor passes the objectId to the SystemObject(). * * @param setObjectId the ObjectId to pass to the SystemObject() Constructor - * @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() * @param deviceCommuncation Communcation Interface object which is used * to implement communication functions - * @param thermalStatePoolId - * @param thermalRequestPoolId + * @param comCookie This object will be passed to the communication inter- + * face and can contain user-defined information about the communication. * @param fdirInstance * @param cmdQueueSize */ @@ -106,8 +102,21 @@ public: CookieIF * comCookie, FailureIsolationBase* fdirInstance = nullptr, size_t cmdQueueSize = 20); + void setHkDestination(object_id_t hkDestination); void setThermalStateRequestPoolIds(uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId); + /** + * @brief Helper function to ease device handler development. + * This will instruct the transition to MODE_ON immediately + * (leading to doStartUp() being called for the transition to the ON mode), + * so external mode commanding is not necessary anymore. + * + * This has to be called before the task is started! + * (e.g. in the task factory). This is only a helper function for + * development. Regular mode commanding should be performed by commanding + * the AssemblyBase or Subsystem objects resposible for the device handler. + */ + void setStartUpImmediately(); /** * @brief This function is the device handler base core component and is @@ -153,6 +162,14 @@ public: * @return */ virtual ReturnValue_t initialize(); + + /** + * @brief Intialization steps performed after all tasks have been created. + * This function will be called by the executing task. + * @return + */ + virtual ReturnValue_t initializeAfterTaskCreation() override; + /** Destructor. */ virtual ~DeviceHandlerBase(); @@ -320,6 +337,8 @@ protected: * @param packet * @return * - @c RETURN_OK when the reply was interpreted. + * - @c IGNORE_REPLY_DATA Ignore the reply and don't reset reply cycle + * counter. * - @c RETURN_FAILED when the reply could not be interpreted, * e.g. logical errors or range violations occurred */ @@ -347,22 +366,10 @@ protected: * set to the maximum expected number of PST cycles between two replies * (also a tolerance should be added, as an FDIR message will be * generated if it is missed). - * - * (Robin) This part confuses me. "must do as soon as" implies that - * the developer must do something somewhere else in the code. Is - * that really the case? If I understood correctly, DHB performs - * almost everything (e.g. in erirm function) as long as the commands - * are inserted correctly. - * - * As soon as the replies are enabled, DeviceCommandInfo.periodic must - * be set to true, DeviceCommandInfo.delayCycles to - * DeviceCommandInfo.maxDelayCycles. * From then on, the base class handles the reception. * Then, scanForReply returns the id of the reply or the placeholder id * and the base class will take care of checking that all replies are * received and the interval is correct. - * When the replies are disabled, DeviceCommandInfo.periodic must be set - * to 0, DeviceCommandInfo.delayCycles to 0; * * - Aperiodic, unrequested replies. These are replies that are sent * by the device without any preceding command and not in a defined @@ -376,13 +383,17 @@ protected: * @param deviceCommand Identifier of the command to add. * @param maxDelayCycles The maximum number of delay cycles the command * waits until it times out. + * @param replyLen Will be supplied to the requestReceiveMessage call of + * the communication interface. * @param periodic Indicates if the command is periodic (i.e. it is sent * by the device repeatedly without request) or not. Default is aperiodic (0) * @return - @c RETURN_OK when the command was successfully inserted, * - @c RETURN_FAILED else. */ ReturnValue_t insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, - uint16_t maxDelayCycles, size_t replyLen = 0, bool periodic = false, + uint16_t maxDelayCycles, + LocalPoolDataSetBase* replyDataSet = nullptr, + size_t replyLen = 0, bool periodic = false, bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0); /** @@ -396,7 +407,8 @@ protected: * - @c RETURN_FAILED else. */ ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, - uint16_t maxDelayCycles, size_t replyLen = 0, bool periodic = false); + uint16_t maxDelayCycles, LocalPoolDataSetBase* dataSet = nullptr, + size_t replyLen = 0, bool periodic = false); /** * @brief A simple command to add a command to the commandList. @@ -424,6 +436,9 @@ protected: uint16_t delayCycles, uint16_t maxDelayCycles, bool periodic = false); + ReturnValue_t setReplyDataset(DeviceCommandId_t replyId, + LocalPoolDataSetBase* dataset); + /** * @brief Can be implemented by child handler to * perform debugging @@ -477,18 +492,22 @@ protected: * @param localDataPoolMap * @return */ - //virtual ReturnValue_t initializePoolEntries( - // LocalDataPool& localDataPoolMap) override; + virtual ReturnValue_t initializeLocalDataPool(LocalDataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override; /** Get the HK manager object handle */ - //virtual LocalDataPoolManager* getHkManagerHandle() override; + virtual LocalDataPoolManager* getHkManagerHandle() override; /** * @brief Hook function for child handlers which is called once per * performOperation(). Default implementation is empty. */ virtual void performOperationHook(); + public: + /** Explicit interface implementation of getObjectId */ + virtual object_id_t getObjectId() const override; + /** * @param parentQueueId */ @@ -608,7 +627,7 @@ protected: /** Action helper for HasActionsIF */ ActionHelper actionHelper; /** Housekeeping Manager */ - //LocalDataPoolManager hkManager; + LocalDataPoolManager hkManager; /** * @brief Information about commands @@ -647,7 +666,7 @@ protected: //! The dataset used to access housekeeping data related to the //! respective device reply. Will point to a dataset held by //! the child handler (if one is specified) - // DataSetIF* dataSet = nullptr; + LocalPoolDataSetBase* dataSet; //! The command that expects this reply. DeviceCommandMap::iterator command; }; @@ -689,14 +708,18 @@ protected: uint32_t deviceThermalRequestPoolId = PoolVariableIF::NO_PARAMETER; /** - * Optional Error code - * Can be set in doStartUp(), doShutDown() and doTransition() to signal cause for Transition failure. + * Optional Error code. Can be set in doStartUp(), doShutDown() and + * doTransition() to signal cause for Transition failure. */ ReturnValue_t childTransitionFailure; - uint32_t ignoreMissedRepliesCount = 0; //!< Counts if communication channel lost a reply, so some missed replys can be ignored. + /** Counts if communication channel lost a reply, so some missed + * replys can be ignored. */ + uint32_t ignoreMissedRepliesCount = 0; - FailureIsolationBase* fdirInstance; //!< Pointer to the used FDIR instance. If not provided by child, default class is instantiated. + /** Pointer to the used FDIR instance. If not provided by child, + * default class is instantiated. */ + FailureIsolationBase* fdirInstance; HkSwitchHelper hkSwitcher; @@ -944,14 +967,17 @@ protected: virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode); - virtual void startTransition(Mode_t mode, Submode_t submode); - virtual void setToExternalControl(); - virtual void announceMode(bool recursive); + + /* HasModesIF overrides */ + virtual void startTransition(Mode_t mode, Submode_t submode) override; + virtual void setToExternalControl() override; + virtual void announceMode(bool recursive) override; virtual ReturnValue_t letChildHandleMessage(CommandMessage *message); /** - * Overwrites SystemObject::triggerEvent in order to inform FDIR"Helper" faster about executed events. + * Overwrites SystemObject::triggerEvent in order to inform FDIR"Helper" + * faster about executed events. * This is a bit sneaky, but improves responsiveness of the device FDIR. * @param event The event to be thrown * @param parameter1 Optional parameter 1 @@ -1034,12 +1060,17 @@ private: /** the object used to set power switches */ PowerSwitchIF *powerSwitcher = nullptr; + /** HK destination can also be set individually */ + object_id_t hkDestination = objects::NO_OBJECT; + /** * @brief Used for timing out mode transitions. * Set when setMode() is called. */ uint32_t timeoutStart = 0; + bool setStartupImmediately = false; + /** * Delay for the current mode transition, used for time out */ @@ -1080,11 +1111,6 @@ private: void buildRawDeviceCommand(CommandMessage* message); void buildInternalCommand(void); -// /** -// * Send a reply with the current mode and submode. -// */ -// void announceMode(void); - /** * Decrement the counter for the timout of replies. * @@ -1111,10 +1137,14 @@ private: /** * Build and send a command to the device. * - * This routine checks whether a raw or direct command has been received, checks the content of the received command and - * calls buildCommandFromCommand() for direct commands or sets #rawpacket to the received raw packet. - * If no external command is received or the received command is invalid and the current mode is @c MODE_NORMAL or a transitional mode, - * it asks the child class to build a command (via getNormalDeviceCommand() or getTransitionalDeviceCommand() and buildCommand()) and + * This routine checks whether a raw or direct command has been received, + * checks the content of the received command and calls + * buildCommandFromCommand() for direct commands or sets #rawpacket + * to the received raw packet. + * If no external command is received or the received command is invalid and + * the current mode is @c MODE_NORMAL or a transitional mode, it asks the + * child class to build a command (via getNormalDeviceCommand() or + * getTransitionalDeviceCommand() and buildCommand()) and * sends the command via RMAP. */ void doSendWrite(void); @@ -1159,7 +1189,6 @@ private: ReturnValue_t getStorageData(store_address_t storageAddress, uint8_t **data, uint32_t *len); - /** * @param modeTo either @c MODE_ON, MODE_NORMAL or MODE_RAW NOTHING ELSE!!! */ @@ -1170,25 +1199,14 @@ private: */ void callChildStatemachine(); - /** - * Switches the channel of the cookie used for the communication - * - * - * @param newChannel the object Id of the channel to switch to - * @return - * - @c RETURN_OK when cookie was changed - * - @c RETURN_FAILED when cookies could not be changed, eg because the newChannel is not enabled - * - @c returnvalues of RMAPChannelIF::isActive() - */ - ReturnValue_t switchCookieChannel(object_id_t newChannelId); - ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message); - virtual ReturnValue_t initializeAfterTaskCreation() override; + virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; - void parseReply(const uint8_t* receivedData, - size_t receivedDataLen); + virtual dur_millis_t getPeriodicOperationFrequency() const override; + + void parseReply(const uint8_t* receivedData, + size_t receivedDataLen); }; -#endif /* FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */ - +#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */ From 89c4370d91859eed6e4f5513b9aa03c3864d77e7 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 1 Oct 2020 13:23:06 +0200 Subject: [PATCH 413/653] tc distribution improvements --- tcdistribution/CCSDSDistributor.cpp | 59 +++++++----- tcdistribution/CCSDSDistributor.h | 99 +++++++++++--------- tcdistribution/CCSDSDistributorIF.h | 36 ++++---- tcdistribution/PUSDistributor.cpp | 118 +++++++++++++----------- tcdistribution/PUSDistributor.h | 60 +++++++----- tcdistribution/PUSDistributorIF.h | 13 +-- tcdistribution/TcDistributor.cpp | 28 +++--- tcdistribution/TcDistributor.h | 136 +++++++++++++++------------- tcdistribution/TcPacketCheck.cpp | 24 ++--- tcdistribution/TcPacketCheck.h | 25 ++--- 10 files changed, 331 insertions(+), 267 deletions(-) diff --git a/tcdistribution/CCSDSDistributor.cpp b/tcdistribution/CCSDSDistributor.cpp index 1ebb3185..ddd63308 100644 --- a/tcdistribution/CCSDSDistributor.cpp +++ b/tcdistribution/CCSDSDistributor.cpp @@ -1,31 +1,39 @@ -#include "../serviceinterface/ServiceInterfaceStream.h" #include "CCSDSDistributor.h" + +#include "../serviceinterface/ServiceInterfaceStream.h" #include "../tmtcpacket/SpacePacketBase.h" -CCSDSDistributor::CCSDSDistributor( uint16_t setDefaultApid, object_id_t setObjectId ) : - TcDistributor( setObjectId ), default_apid( setDefaultApid ), tcStore(NULL) { +CCSDSDistributor::CCSDSDistributor(uint16_t setDefaultApid, + object_id_t setObjectId): + TcDistributor(setObjectId), defaultApid( setDefaultApid ) { } -CCSDSDistributor::~CCSDSDistributor() { +CCSDSDistributor::~CCSDSDistributor() {} -} - -iterator_t CCSDSDistributor::selectDestination() { -// debug << "CCSDSDistributor::selectDestination received: " << this->currentMessage.getStorageId().pool_index << ", " << this->currentMessage.getStorageId().packet_index << std::endl; - const uint8_t* p_packet = NULL; +TcDistributor::TcMqMapIter CCSDSDistributor::selectDestination() { +// sif::debug << "CCSDSDistributor::selectDestination received: " << +// this->currentMessage.getStorageId().pool_index << ", " << +// this->currentMessage.getStorageId().packet_index << std::endl; + const uint8_t* packet = nullptr; size_t size = 0; - //TODO check returncode? - this->tcStore->getData( this->currentMessage.getStorageId(), &p_packet, &size ); - SpacePacketBase current_packet( p_packet ); -// info << "CCSDSDistributor::selectDestination has packet with APID " << std::hex << current_packet.getAPID() << std::dec << std::endl; - iterator_t position = this->queueMap.find( current_packet.getAPID() ); + ReturnValue_t result = this->tcStore->getData(currentMessage.getStorageId(), + &packet, &size ); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "CCSDSDistributor::selectDestination: Getting data from" + " store failed!" << std::endl; + } + SpacePacketBase currentPacket(packet); + +// sif:: info << "CCSDSDistributor::selectDestination has packet with APID " +// << std::hex << currentPacket.getAPID() << std::dec << std::endl; + TcMqMapIter position = this->queueMap.find(currentPacket.getAPID()); if ( position != this->queueMap.end() ) { return position; } else { - //The APID was not found. Forward packet to main SW-APID anyway to create acceptance failure report. - return this->queueMap.find( this->default_apid ); + //The APID was not found. Forward packet to main SW-APID anyway to + // create acceptance failure report. + return this->queueMap.find( this->defaultApid ); } - } MessageQueueId_t CCSDSDistributor::getRequestQueue() { @@ -35,9 +43,9 @@ MessageQueueId_t CCSDSDistributor::getRequestQueue() { ReturnValue_t CCSDSDistributor::registerApplication( AcceptsTelecommandsIF* application) { ReturnValue_t returnValue = RETURN_OK; - bool errorCode = true; - errorCode = this->queueMap.insert( std::pair( application->getIdentifier(), application->getRequestQueue() ) ).second; - if( errorCode == false ) { + auto insertPair = this->queueMap.emplace(application->getIdentifier(), + application->getRequestQueue()); + if(not insertPair.second) { returnValue = RETURN_FAILED; } return returnValue; @@ -46,9 +54,8 @@ ReturnValue_t CCSDSDistributor::registerApplication( ReturnValue_t CCSDSDistributor::registerApplication(uint16_t apid, MessageQueueId_t id) { ReturnValue_t returnValue = RETURN_OK; - bool errorCode = true; - errorCode = this->queueMap.insert( std::pair( apid, id ) ).second; - if( errorCode == false ) { + auto insertPair = this->queueMap.emplace(apid, id); + if(not insertPair.second) { returnValue = RETURN_FAILED; } return returnValue; @@ -62,7 +69,11 @@ uint16_t CCSDSDistributor::getIdentifier() { ReturnValue_t CCSDSDistributor::initialize() { ReturnValue_t status = this->TcDistributor::initialize(); this->tcStore = objectManager->get( objects::TC_STORE ); - if (this->tcStore == NULL) status = RETURN_FAILED; + if (this->tcStore == nullptr) { + sif::error << "CCSDSDistributor::initialize: Could not initialize" + " TC store!" << std::endl; + status = RETURN_FAILED; + } return status; } diff --git a/tcdistribution/CCSDSDistributor.h b/tcdistribution/CCSDSDistributor.h index bff72092..e8d54c9c 100644 --- a/tcdistribution/CCSDSDistributor.h +++ b/tcdistribution/CCSDSDistributor.h @@ -1,58 +1,71 @@ -#ifndef CCSDSDISTRIBUTOR_H_ -#define CCSDSDISTRIBUTOR_H_ +#ifndef FRAMEWORK_TCDISTRIBUTION_CCSDSDISTRIBUTOR_H_ +#define FRAMEWORK_TCDISTRIBUTION_CCSDSDISTRIBUTOR_H_ #include "../objectmanager/ObjectManagerIF.h" #include "../storagemanager/StorageManagerIF.h" -#include "CCSDSDistributorIF.h" -#include "TcDistributor.h" +#include "../tcdistribution/CCSDSDistributorIF.h" +#include "../tcdistribution/TcDistributor.h" #include "../tmtcservices/AcceptsTelecommandsIF.h" + /** - * An instantiation of the CCSDSDistributorIF. - * It receives Space Packets, and selects a destination depending on the APID of the telecommands. + * @brief An instantiation of the CCSDSDistributorIF. + * @details + * It receives Space Packets, and selects a destination depending on the + * APID of the telecommands. * The Secondary Header (with Service/Subservice) is ignored. - * \ingroup tc_distribution + * @ingroup tc_distribution */ -class CCSDSDistributor : public TcDistributor, public CCSDSDistributorIF, public AcceptsTelecommandsIF { -protected: - /** - * This implementation checks if an Application with fitting APID has registered and forwards the - * packet to the according message queue. - * If the packet is not found, it returns the queue to \c default_apid, where a Acceptance Failure - * message should be generated. - * @return Iterator to map entry of found APID or iterator to default APID. - */ - iterator_t selectDestination(); - /** - * The default APID, where packets with unknown APID are sent to. - */ - uint16_t default_apid; - /** - * A reference to the TC storage must be maintained, as this class handles pure Space Packets and there - * exists no SpacePacketStored class. - */ - StorageManagerIF* tcStore; - /** - * The callback here handles the generation of acceptance success/failure messages. - */ - ReturnValue_t callbackAfterSending( ReturnValue_t queueStatus ); +class CCSDSDistributor : public TcDistributor, + public CCSDSDistributorIF, + public AcceptsTelecommandsIF { public: /** - * The constructor sets the default APID and calls the TcDistributor ctor with a certain object id. - * \c tcStore is set in the \c initialize method. - * @param set_default_apid The default APID, where packets with unknown destination are sent to. + * @brief The constructor sets the default APID and calls the + * TcDistributor ctor with a certain object id. + * @details + * @c tcStore is set in the @c initialize method. + * @param setDefaultApid The default APID, where packets with unknown + * destination are sent to. */ - CCSDSDistributor( uint16_t setDefaultApid, object_id_t setObjectId ); + CCSDSDistributor(uint16_t setDefaultApid, object_id_t setObjectId); /** * The destructor is empty. */ - ~CCSDSDistributor(); - MessageQueueId_t getRequestQueue(); - ReturnValue_t registerApplication( uint16_t apid, MessageQueueId_t id ); - ReturnValue_t registerApplication( AcceptsTelecommandsIF* application ); - uint16_t getIdentifier(); - ReturnValue_t initialize(); + virtual ~CCSDSDistributor(); + + MessageQueueId_t getRequestQueue() override; + ReturnValue_t registerApplication( uint16_t apid, + MessageQueueId_t id) override; + ReturnValue_t registerApplication( + AcceptsTelecommandsIF* application) override; + uint16_t getIdentifier() override; + ReturnValue_t initialize() override; + +protected: + /** + * This implementation checks if an application with fitting APID has + * registered and forwards the packet to the according message queue. + * If the packet is not found, it returns the queue to @c defaultApid, + * where a Acceptance Failure message should be generated. + * @return Iterator to map entry of found APID or iterator to default APID. + */ + TcMqMapIter selectDestination() override; + /** + * The callback here handles the generation of acceptance + * success/failure messages. + */ + ReturnValue_t callbackAfterSending( ReturnValue_t queueStatus ) override; + + /** + * The default APID, where packets with unknown APID are sent to. + */ + uint16_t defaultApid; + /** + * A reference to the TC storage must be maintained, as this class handles + * pure Space Packets and there exists no SpacePacketStored class. + */ + StorageManagerIF* tcStore = nullptr; + }; - - -#endif /* CCSDSDISTRIBUTOR_H_ */ +#endif /* FRAMEWORK_TCDISTRIBUTION_CCSDSDISTRIBUTOR_H_ */ diff --git a/tcdistribution/CCSDSDistributorIF.h b/tcdistribution/CCSDSDistributorIF.h index be3c2811..6334a35a 100644 --- a/tcdistribution/CCSDSDistributorIF.h +++ b/tcdistribution/CCSDSDistributorIF.h @@ -1,34 +1,38 @@ -#ifndef CCSDSDISTRIBUTORIF_H_ -#define CCSDSDISTRIBUTORIF_H_ +#ifndef FSFW_TCDISTRIBUTION_CCSDSDISTRIBUTORIF_H_ +#define FSFW_TCDISTRIBUTION_CCSDSDISTRIBUTORIF_H_ #include "../tmtcservices/AcceptsTelecommandsIF.h" #include "../ipc/MessageQueueSenderIF.h" /** * This is the Interface to a CCSDS Distributor. - * On a CCSDS Distributor, Applications (in terms of CCSDS) may register themselves, - * either by passing a pointer to themselves (and implementing the CCSDSApplicationIF, - * or by explicitly passing an APID and a MessageQueueId to route the TC's to. - * \ingroup tc_distribution + * On a CCSDS Distributor, Applications (in terms of CCSDS) may register + * themselves, either by passing a pointer to themselves (and implementing the + * CCSDSApplicationIF), or by explicitly passing an APID and a MessageQueueId + * to route the TC's to. + * @ingroup tc_distribution */ class CCSDSDistributorIF { public: /** - * With this call, a class implementing the CCSDSApplicationIF can register at the - * distributor. + * With this call, a class implementing the CCSDSApplicationIF can register + * at the distributor. * @param application A pointer to the Application to register. - * @return - \c RETURN_OK on success, - * - \c RETURN_FAILED on failure. + * @return - @c RETURN_OK on success, + * - @c RETURN_FAILED on failure. */ - virtual ReturnValue_t registerApplication( AcceptsTelecommandsIF* application ) = 0; + virtual ReturnValue_t registerApplication( + AcceptsTelecommandsIF* application) = 0; /** * With this call, other Applications can register to the CCSDS distributor. * This is done by passing an APID and a MessageQueueId to the method. * @param apid The APID to register. - * @param id The MessageQueueId of the message queue to send the TC Packets to. - * @return - \c RETURN_OK on success, - * - \c RETURN_FAILED on failure. + * @param id The MessageQueueId of the message queue to send the + * TC Packets to. + * @return - @c RETURN_OK on success, + * - @c RETURN_FAILED on failure. */ - virtual ReturnValue_t registerApplication( uint16_t apid, MessageQueueId_t id ) = 0; + virtual ReturnValue_t registerApplication( uint16_t apid, + MessageQueueId_t id) = 0; /** * The empty virtual destructor. */ @@ -37,4 +41,4 @@ public: }; -#endif /* CCSDSDISTRIBUTORIF_H_ */ +#endif /* FSFW_TCDISTRIBUTION_CCSDSDISTRIBUTORIF_H_ */ diff --git a/tcdistribution/PUSDistributor.cpp b/tcdistribution/PUSDistributor.cpp index f77eb99d..3baef7d1 100644 --- a/tcdistribution/PUSDistributor.cpp +++ b/tcdistribution/PUSDistributor.cpp @@ -1,61 +1,68 @@ -#include "../serviceinterface/ServiceInterfaceStream.h" #include "CCSDSDistributorIF.h" #include "PUSDistributor.h" + +#include "../serviceinterface/ServiceInterfaceStream.h" #include "../tmtcpacket/pus/TcPacketStored.h" #include "../tmtcservices/PusVerificationReport.h" -PUSDistributor::PUSDistributor(uint16_t setApid, object_id_t setObjectId, object_id_t setPacketSource) : - TcDistributor(setObjectId), checker(setApid), verifyChannel(), currentPacket(), tcStatus( - RETURN_FAILED), packetSource(setPacketSource) { +PUSDistributor::PUSDistributor(uint16_t setApid, object_id_t setObjectId, + object_id_t setPacketSource) : + TcDistributor(setObjectId), checker(setApid), verifyChannel(), + tcStatus(RETURN_FAILED), packetSource(setPacketSource) {} + +PUSDistributor::~PUSDistributor() {} + +PUSDistributor::TcMqMapIter PUSDistributor::selectDestination() { + // sif:: debug << "PUSDistributor::handlePacket received: " + // << this->current_packet_id.store_index << ", " + // << this->current_packet_id.packet_index << std::endl; + TcMqMapIter queueMapIt = this->queueMap.end(); + this->currentPacket->setStoreAddress(this->currentMessage.getStorageId()); + if (currentPacket->getWholeData() != NULL) { + tcStatus = checker.checkPacket(currentPacket); +#ifdef DEBUG + if(tcStatus != HasReturnvaluesIF::RETURN_OK) { + sif::debug << "PUSDistributor::handlePacket: Packet format " + << "invalid, code "<< static_cast(tcStatus) + << std::endl; + } +#endif + uint32_t queue_id = currentPacket->getService(); + queueMapIt = this->queueMap.find(queue_id); + } + else { + tcStatus = PACKET_LOST; + } + + if (queueMapIt == this->queueMap.end()) { + tcStatus = DESTINATION_NOT_FOUND; +#ifdef DEBUG + sif::debug << "PUSDistributor::handlePacket: Destination not found, " + << "code "<< static_cast(tcStatus) << std::endl; +#endif + } + + if (tcStatus != RETURN_OK) { + return this->queueMap.end(); + } + else { + return queueMapIt; + } } -PUSDistributor::~PUSDistributor() { - -} - -iterator_t PUSDistributor::selectDestination() { -// debug << "PUSDistributor::handlePacket received: " << this->current_packet_id.store_index << ", " << this->current_packet_id.packet_index << std::endl; - iterator_t queueMapIt = this->queueMap.end(); - this->currentPacket.setStoreAddress(this->currentMessage.getStorageId()); - if (currentPacket.getWholeData() != NULL) { - tcStatus = checker.checkPacket(¤tPacket); -// info << "PUSDistributor::handlePacket: packetCheck returned with " << (int)tc_status << std::endl; - uint32_t queue_id = currentPacket.getService(); - queueMapIt = this->queueMap.find(queue_id); - } else { - tcStatus = PACKET_LOST; - } - if (queueMapIt == this->queueMap.end()) { - tcStatus = DESTINATION_NOT_FOUND; - } - - if (tcStatus != RETURN_OK) { - sif::debug << "PUSDistributor::handlePacket: error with " << (int) tcStatus - << std::endl; - return this->queueMap.end(); - } else { - return queueMapIt; - } - -} - -//uint16_t PUSDistributor::createDestination( uint8_t service_id, uint8_t subservice_id ) { -// return ( service_id << 8 ) + subservice_id; -//} ReturnValue_t PUSDistributor::registerService(AcceptsTelecommandsIF* service) { - ReturnValue_t returnValue = RETURN_OK; - bool errorCode = true; uint16_t serviceId = service->getIdentifier(); + // sif::info << "Service ID: " << (int)serviceId << std::endl; MessageQueueId_t queue = service->getRequestQueue(); - errorCode = this->queueMap.insert( - std::pair(serviceId, queue)).second; - if (errorCode == false) { - //TODO Return Code - returnValue = MessageQueueIF::NO_QUEUE; + auto returnPair = queueMap.emplace(serviceId, queue); + if (not returnPair.second) { + sif::error << "PUSDistributor::registerService: Service ID already" + " exists in map." << std::endl; + return SERVICE_ID_ALREADY_EXISTS; } - return returnValue; + return HasReturnvaluesIF::RETURN_OK; } MessageQueueId_t PUSDistributor::getRequestQueue() { @@ -68,13 +75,14 @@ ReturnValue_t PUSDistributor::callbackAfterSending(ReturnValue_t queueStatus) { } if (tcStatus != RETURN_OK) { this->verifyChannel.sendFailureReport(TC_VERIFY::ACCEPTANCE_FAILURE, - ¤tPacket, tcStatus); - //A failed packet is deleted immediately after reporting, otherwise it will block memory. - currentPacket.deletePacket(); + currentPacket, tcStatus); + // A failed packet is deleted immediately after reporting, + // otherwise it will block memory. + currentPacket->deletePacket(); return RETURN_FAILED; } else { this->verifyChannel.sendSuccessReport(TC_VERIFY::ACCEPTANCE_SUCCESS, - ¤tPacket); + currentPacket); return RETURN_OK; } } @@ -86,9 +94,15 @@ uint16_t PUSDistributor::getIdentifier() { ReturnValue_t PUSDistributor::initialize() { CCSDSDistributorIF* ccsdsDistributor = objectManager->get(packetSource); - if (ccsdsDistributor == NULL) { - return RETURN_FAILED; - } else { + if (ccsdsDistributor == nullptr) { + sif::error << "PUSDistributor::initialize: Packet source invalid." + << " Make sure it exists and implements CCSDSDistributorIF!" + << std::endl; + return RETURN_FAILED; + } + else { return ccsdsDistributor->registerApplication(this); } + + currentPacket = new TcPacketStored(); } diff --git a/tcdistribution/PUSDistributor.h b/tcdistribution/PUSDistributor.h index e9d4be8c..be3804ef 100644 --- a/tcdistribution/PUSDistributor.h +++ b/tcdistribution/PUSDistributor.h @@ -1,67 +1,79 @@ -#ifndef PUSDISTRIBUTOR_H_ -#define PUSDISTRIBUTOR_H_ +#ifndef FSFW_TCDISTRIBUTION_PUSDISTRIBUTOR_H_ +#define FSFW_TCDISTRIBUTION_PUSDISTRIBUTOR_H_ -#include "../returnvalues/HasReturnvaluesIF.h" #include "PUSDistributorIF.h" #include "TcDistributor.h" #include "TcPacketCheck.h" + +#include "../returnvalues/HasReturnvaluesIF.h" #include "../tmtcservices/AcceptsTelecommandsIF.h" #include "../tmtcservices/VerificationReporter.h" /** - * This class accepts PUS Telecommands and forwards them to Application services. - * In addition, the class performs a formal packet check and sends acceptance success - * or failure messages. - * \ingroup tc_distribution + * This class accepts PUS Telecommands and forwards them to Application + * services. In addition, the class performs a formal packet check and + * sends acceptance success or failure messages. + * @ingroup tc_distribution */ class PUSDistributor: public TcDistributor, public PUSDistributorIF, public AcceptsTelecommandsIF { public: /** - * The ctor passes \c set_apid to the checker class and calls the TcDistribution ctor with a certain object id. + * The ctor passes @c set_apid to the checker class and calls the + * TcDistribution ctor with a certain object id. * @param setApid The APID of this receiving Application. * @param setObjectId Object ID of the distributor itself - * @param setPacketSource Object ID of the source of TC packets. Must implement CCSDSDistributorIF. + * @param setPacketSource Object ID of the source of TC packets. + * Must implement CCSDSDistributorIF. */ - PUSDistributor(uint16_t setApid, object_id_t setObjectId, object_id_t setPacketSource); + PUSDistributor(uint16_t setApid, object_id_t setObjectId, + object_id_t setPacketSource); /** * The destructor is empty. */ virtual ~PUSDistributor(); - ReturnValue_t registerService(AcceptsTelecommandsIF* service); - MessageQueueId_t getRequestQueue(); - uint16_t getIdentifier(); - ReturnValue_t initialize(); + ReturnValue_t registerService(AcceptsTelecommandsIF* service) override; + MessageQueueId_t getRequestQueue() override; + ReturnValue_t initialize() override; + uint16_t getIdentifier() override; + protected: /** * This attribute contains the class, that performs a formal packet check. */ TcPacketCheck checker; /** - * With this class, verification messages are sent to the TC Verification service. + * With this class, verification messages are sent to the + * TC Verification service. */ VerificationReporter verifyChannel; /** * The currently handled packet is stored here. */ - TcPacketStored currentPacket; + TcPacketStored* currentPacket = nullptr; /** - * With this variable, the current check status is stored to generate acceptance messages later. + * With this variable, the current check status is stored to generate + * acceptance messages later. */ ReturnValue_t tcStatus; const object_id_t packetSource; + /** - * This method reads the packet service, checks if such a service is registered and forwards the packet to the destination. - * It also initiates the formal packet check and sending of verification messages. - * @return Iterator to map entry of found service id or iterator to \c map.end(). + * This method reads the packet service, checks if such a service is + * registered and forwards the packet to the destination. + * It also initiates the formal packet check and sending of verification + * messages. + * @return Iterator to map entry of found service id + * or iterator to @c map.end(). */ - iterator_t selectDestination(); + TcMqMapIter selectDestination() override; /** - * The callback here handles the generation of acceptance success/failure messages. + * The callback here handles the generation of acceptance + * success/failure messages. */ - ReturnValue_t callbackAfterSending(ReturnValue_t queueStatus); + ReturnValue_t callbackAfterSending(ReturnValue_t queueStatus) override; }; -#endif /* PUSDISTRIBUTOR_H_ */ +#endif /* FSFW_TCDISTRIBUTION_PUSDISTRIBUTOR_H_ */ diff --git a/tcdistribution/PUSDistributorIF.h b/tcdistribution/PUSDistributorIF.h index 5e27b35c..0125c08f 100644 --- a/tcdistribution/PUSDistributorIF.h +++ b/tcdistribution/PUSDistributorIF.h @@ -1,11 +1,12 @@ -#ifndef PUSDISTRIBUTORIF_H_ -#define PUSDISTRIBUTORIF_H_ +#ifndef FSFW_TCDISTRIBUTION_PUSDISTRIBUTORIF_H_ +#define FSFW_TCDISTRIBUTION_PUSDISTRIBUTORIF_H_ #include "../tmtcservices/AcceptsTelecommandsIF.h" #include "../ipc/MessageQueueSenderIF.h" + /** * This interface allows PUS Services to register themselves at a PUS Distributor. - * \ingroup tc_distribution + * @ingroup tc_distribution */ class PUSDistributorIF { public: @@ -17,10 +18,10 @@ public: /** * With this method, Services can register themselves at the PUS Distributor. * @param service A pointer to the registering Service. - * @return - \c RETURN_OK on success, - * - \c RETURN_FAILED on failure. + * @return - @c RETURN_OK on success, + * - @c RETURN_FAILED on failure. */ virtual ReturnValue_t registerService( AcceptsTelecommandsIF* service ) = 0; }; -#endif /* PUSDISTRIBUTORIF_H_ */ +#endif /* FSFW_TCDISTRIBUTION_PUSDISTRIBUTORIF_H_ */ diff --git a/tcdistribution/TcDistributor.cpp b/tcdistribution/TcDistributor.cpp index 49a996d9..06e1817f 100644 --- a/tcdistribution/TcDistributor.cpp +++ b/tcdistribution/TcDistributor.cpp @@ -1,12 +1,13 @@ -#include "../serviceinterface/ServiceInterfaceStream.h" -#include "../serviceinterface/ServiceInterfaceStream.h" #include "TcDistributor.h" + +#include "../serviceinterface/ServiceInterfaceStream.h" #include "../tmtcservices/TmTcMessage.h" #include "../ipc/QueueFactory.h" -TcDistributor::TcDistributor(object_id_t set_object_id) : - SystemObject(set_object_id), tcQueue(NULL) { - tcQueue = QueueFactory::instance()->createMessageQueue(DISTRIBUTER_MAX_PACKETS); +TcDistributor::TcDistributor(object_id_t objectId) : + SystemObject(objectId) { + tcQueue = QueueFactory::instance()-> + createMessageQueue(DISTRIBUTER_MAX_PACKETS); } TcDistributor::~TcDistributor() { @@ -15,7 +16,6 @@ TcDistributor::~TcDistributor() { ReturnValue_t TcDistributor::performOperation(uint8_t opCode) { ReturnValue_t status = RETURN_OK; -// debug << "TcDistributor: performing Operation." << std::endl; for (status = tcQueue->receiveMessage(¤tMessage); status == RETURN_OK; status = tcQueue->receiveMessage(¤tMessage)) { status = handlePacket(); @@ -29,7 +29,7 @@ ReturnValue_t TcDistributor::performOperation(uint8_t opCode) { ReturnValue_t TcDistributor::handlePacket() { - iterator_t queueMapIt = this->selectDestination(); + TcMqMapIter queueMapIt = this->selectDestination(); ReturnValue_t returnValue = RETURN_FAILED; if (queueMapIt != this->queueMap.end()) { returnValue = this->tcQueue->sendMessage(queueMapIt->second, @@ -39,14 +39,14 @@ ReturnValue_t TcDistributor::handlePacket() { } void TcDistributor::print() { - sif::debug << "Distributor content is: " << std::endl << "ID\t| message queue id" - << std::endl; - for (iterator_t it = this->queueMap.begin(); it != this->queueMap.end(); - it++) { - sif::debug << it->first << "\t| 0x" << std::hex << it->second << std::dec - << std::endl; + sif::debug << "Distributor content is: " << std::endl + << "ID\t| Message Queue ID" << std::endl; + sif::debug << std::setfill('0') << std::setw(8) << std::hex; + for (const auto& queueMapIter: queueMap) { + sif::debug << queueMapIter.first << "\t| 0x" << queueMapIter.second + << std::endl; } - sif::debug << std::dec; + sif::debug << std::setfill(' ') << std::dec; } diff --git a/tcdistribution/TcDistributor.h b/tcdistribution/TcDistributor.h index fed1cb3e..5d0ca45d 100644 --- a/tcdistribution/TcDistributor.h +++ b/tcdistribution/TcDistributor.h @@ -1,5 +1,6 @@ -#ifndef TCDISTRIBUTOR_H_ -#define TCDISTRIBUTOR_H_ +#ifndef FSFW_TMTCSERVICES_TCDISTRIBUTOR_H_ +#define FSFW_TMTCSERVICES_TCDISTRIBUTOR_H_ + #include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/SystemObject.h" #include "../returnvalues/HasReturnvaluesIF.h" @@ -9,16 +10,12 @@ #include "../ipc/MessageQueueIF.h" #include - /** - * \defgroup tc_distribution Telecommand Distribution - * All classes associated with Routing and Distribution of Telecommands belong to this group. + * @defgroup tc_distribution Telecommand Distribution + * All classes associated with Routing and Distribution of Telecommands + * belong to this group. */ -/** - * This typedef simplifies writing down the \c map iterator. - */ -typedef std::map::iterator iterator_t; /** * This is the base class to implement distributors for Space Packets. @@ -28,62 +25,19 @@ typedef std::map::iterator iterator_t; * message queue ids to some identifier. The process of unpacking the * destination information from the packet is handled by the child class * implementations. - * \ingroup tc_distribution + * @ingroup tc_distribution */ -class TcDistributor : public SystemObject, public ExecutableObjectIF, public HasReturnvaluesIF { -private: - /** - * This constant sets the maximum number of packets distributed per call. - */ - static const uint8_t DISTRIBUTER_MAX_PACKETS = 128; -protected: - /** - * This is the receiving queue for incoming Telecommands. - * The child classes must make its queue id public. - */ - MessageQueueIF* tcQueue; - /** - * The last received incoming packet information is stored in this - * member. - * As different child classes unpack the incoming packet differently - * (i.e. as a CCSDS Space Packet or as a PUS Telecommand Packet), it - * is not tried to unpack the packet information within this class. - */ - TmTcMessage currentMessage; - /** - * The map that links certain packet information to a destination. - * The packet information may be the APID of the packet or the service - * identifier. Filling of the map is under control of the different child - * classes. - */ - std::map queueMap; - /** - * This method shall unpack the routing information from the incoming - * packet and select the map entry which represents the packet's target. - * @return An iterator to the map element to forward to or queuMap.end(). - */ - virtual iterator_t selectDestination() = 0; - /** - * The handlePacket method calls the child class's selectDestination method - * and forwards the packet to its destination, if found. - * @return The message queue return value or \c RETURN_FAILED, in case no - * destination was found. - */ - ReturnValue_t handlePacket(); - /** - * This method gives the child class a chance to perform some kind of operation - * after the parent tried to forward the message. - * A typically application would be sending success/failure messages. - * The default implementation just returns \c RETURN_OK. - * @param queueStatus The status of the message queue after an attempt to send the TC. - * @return - \c RETURN_OK on success - * - \c RETURN_FAILED on failure - */ - virtual ReturnValue_t callbackAfterSending( ReturnValue_t queueStatus ); +class TcDistributor : public SystemObject, + public ExecutableObjectIF, + public HasReturnvaluesIF { public: - static const uint8_t INTERFACE_ID = CLASS_ID::PACKET_DISTRIBUTION; - static const ReturnValue_t PACKET_LOST = MAKE_RETURN_CODE( 1 ); - static const ReturnValue_t DESTINATION_NOT_FOUND = MAKE_RETURN_CODE( 2 ); + using TcMessageQueueMap = std::map; + using TcMqMapIter = std::map::iterator; + + static constexpr uint8_t INTERFACE_ID = CLASS_ID::PACKET_DISTRIBUTION; + static constexpr ReturnValue_t PACKET_LOST = MAKE_RETURN_CODE( 1 ); + static constexpr ReturnValue_t DESTINATION_NOT_FOUND = MAKE_RETURN_CODE( 2 ); + static constexpr ReturnValue_t SERVICE_ID_ALREADY_EXISTS = MAKE_RETURN_CODE(3); /** * Within the default constructor, the SystemObject id is set and the * message queue is initialized. @@ -91,7 +45,7 @@ public: * @param set_object_id This id is assigned to the distributor * implementation. */ - TcDistributor( object_id_t set_object_id ); + TcDistributor(object_id_t objectId); /** * The destructor is empty, the message queues are not in the vicinity of * this class. @@ -110,7 +64,59 @@ public: * queueMap. */ void print(); + +protected: + /** + * This is the receiving queue for incoming Telecommands. + * The child classes must make its queue id public. + */ + MessageQueueIF* tcQueue = nullptr; + /** + * The last received incoming packet information is stored in this + * member. + * As different child classes unpack the incoming packet differently + * (i.e. as a CCSDS Space Packet or as a PUS Telecommand Packet), it + * is not tried to unpack the packet information within this class. + */ + TmTcMessage currentMessage; + /** + * The map that links certain packet information to a destination. + * The packet information may be the APID of the packet or the service + * identifier. Filling of the map is under control of the different child + * classes. + */ + TcMessageQueueMap queueMap; + /** + * This method shall unpack the routing information from the incoming + * packet and select the map entry which represents the packet's target. + * @return An iterator to the map element to forward to or queuMap.end(). + */ + virtual TcMqMapIter selectDestination() = 0; + /** + * The handlePacket method calls the child class's selectDestination method + * and forwards the packet to its destination, if found. + * @return The message queue return value or @c RETURN_FAILED, in case no + * destination was found. + */ + ReturnValue_t handlePacket(); + /** + * This method gives the child class a chance to perform some kind of + * operation after the parent tried to forward the message. + * A typically application would be sending success/failure messages. + * The default implementation just returns @c RETURN_OK. + * @param queueStatus The status of the message queue after an attempt + * to send the TC. + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + virtual ReturnValue_t callbackAfterSending( ReturnValue_t queueStatus ); + +private: + /** + * This constant sets the maximum number of packets distributed per call. + */ + static constexpr uint8_t DISTRIBUTER_MAX_PACKETS = 128; }; -#endif /* TCDISTRIBUTOR_H_ */ +#endif /* FSFW_TMTCSERVICES_TCDISTRIBUTOR_H_ */ diff --git a/tcdistribution/TcPacketCheck.cpp b/tcdistribution/TcPacketCheck.cpp index b5881083..38ed04aa 100644 --- a/tcdistribution/TcPacketCheck.cpp +++ b/tcdistribution/TcPacketCheck.cpp @@ -1,31 +1,33 @@ +#include "TcPacketCheck.h" + #include "../globalfunctions/CRC.h" #include "../serviceinterface/ServiceInterfaceStream.h" #include "../storagemanager/StorageManagerIF.h" -#include "TcPacketCheck.h" #include "../tmtcservices/VerificationCodes.h" -TcPacketCheck::TcPacketCheck( uint16_t set_apid ) : apid(set_apid) { +TcPacketCheck::TcPacketCheck( uint16_t setApid ) : apid(setApid) { } -ReturnValue_t TcPacketCheck::checkPacket( TcPacketStored* current_packet ) { - uint16_t calculated_crc = CRC::crc16ccitt( current_packet->getWholeData(), current_packet->getFullSize() ); +ReturnValue_t TcPacketCheck::checkPacket( TcPacketStored* currentPacket ) { + uint16_t calculated_crc = CRC::crc16ccitt( currentPacket->getWholeData(), + currentPacket->getFullSize() ); if ( calculated_crc != 0 ) { return INCORRECT_CHECKSUM; } - bool condition = !(current_packet->hasSecondaryHeader()) || - current_packet->getPacketVersionNumber() != CCSDS_VERSION_NUMBER || - !(current_packet->isTelecommand()); + bool condition = (not currentPacket->hasSecondaryHeader()) or + (currentPacket->getPacketVersionNumber() != CCSDS_VERSION_NUMBER) or + (not currentPacket->isTelecommand()); if ( condition ) { return INCORRECT_PRIMARY_HEADER; } - if ( current_packet->getAPID() != this->apid ) + if ( currentPacket->getAPID() != this->apid ) return ILLEGAL_APID; - if ( !current_packet->isSizeCorrect() ) { + if ( not currentPacket->isSizeCorrect() ) { return INCOMPLETE_PACKET; } - condition = (current_packet->getSecondaryHeaderFlag() != CCSDS_SECONDARY_HEADER_FLAG) || - (current_packet->getPusVersionNumber() != PUS_VERSION_NUMBER); + condition = (currentPacket->getSecondaryHeaderFlag() != CCSDS_SECONDARY_HEADER_FLAG) || + (currentPacket->getPusVersionNumber() != PUS_VERSION_NUMBER); if ( condition ) { return INCORRECT_SECONDARY_HEADER; } diff --git a/tcdistribution/TcPacketCheck.h b/tcdistribution/TcPacketCheck.h index 4ba269f5..703bb1bb 100644 --- a/tcdistribution/TcPacketCheck.h +++ b/tcdistribution/TcPacketCheck.h @@ -1,28 +1,29 @@ -#ifndef TCPACKETCHECK_H_ -#define TCPACKETCHECK_H_ +#ifndef FSFW_TCDISTRIBUTION_TCPACKETCHECK_H_ +#define FSFW_TCDISTRIBUTION_TCPACKETCHECK_H_ #include "../returnvalues/HasReturnvaluesIF.h" #include "../tmtcpacket/pus/TcPacketStored.h" #include "../tmtcservices/PusVerificationReport.h" + /** * This class performs a formal packet check for incoming PUS Telecommand Packets. * Currently, it only checks if the APID and CRC are correct. - * \ingroup tc_distribution + * @ingroup tc_distribution */ class TcPacketCheck : public HasReturnvaluesIF { protected: /** * Describes the version number a packet must have to pass. */ - static const uint8_t CCSDS_VERSION_NUMBER = 0; + static constexpr uint8_t CCSDS_VERSION_NUMBER = 0; /** * Describes the secondary header a packet must have to pass. */ - static const uint8_t CCSDS_SECONDARY_HEADER_FLAG = 0; + static constexpr uint8_t CCSDS_SECONDARY_HEADER_FLAG = 0; /** * Describes the TC Packet PUS Version Number a packet must have to pass. */ - static const uint8_t PUS_VERSION_NUMBER = 1; + static constexpr uint8_t PUS_VERSION_NUMBER = 1; /** * The packet id each correct packet should have. * It is composed of the APID and some static fields. @@ -41,19 +42,19 @@ public: * The constructor only sets the APID attribute. * @param set_apid The APID to set. */ - TcPacketCheck( uint16_t set_apid ); + TcPacketCheck( uint16_t setApid ); /** * This is the actual method to formally check a certain Telecommand Packet. * The packet's Application Data can not be checked here. * @param current_packet The packt to check - * @return - \c RETURN_OK on success. - * - \c INCORRECT_CHECKSUM if checksum is invalid. - * - \c ILLEGAL_APID if APID does not match. + * @return - @c RETURN_OK on success. + * - @c INCORRECT_CHECKSUM if checksum is invalid. + * - @c ILLEGAL_APID if APID does not match. */ - ReturnValue_t checkPacket( TcPacketStored* current_packet ); + ReturnValue_t checkPacket( TcPacketStored* currentPacket ); uint16_t getApid() const; }; -#endif /* TCPACKETCHECK_H_ */ +#endif /* FSFW_TCDISTRIBUTION_TCPACKETCHECK_H_ */ From 1f3a10b37554c1b8872a2dd82e0ebb4673e270f7 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 1 Oct 2020 13:30:28 +0200 Subject: [PATCH 414/653] Fixes and comments in FixedOrderedMultimap --- container/FixedOrderedMultimap.h | 208 +++++++++++++++++++++++-------- 1 file changed, 159 insertions(+), 49 deletions(-) diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 717575d7..a9f093d6 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -5,6 +5,24 @@ #include #include /** + * @brief A "Map" which allows multiple entries of the same key. + * @details + * Same keys are ordered by KEY_COMPARE function which is std::less > by default. + * + * It uses the ArrayList, so technically this is not a real map, it is an array of pairs + * of type key_t, T. It is ordered by key_t as FixedMap but allows same keys. + * + * Its of fixed size so no allocations are performed after the construction. + * + * The maximum size is given as first parameter of the constructor. + * + * It provides an iterator to do list iterations. + * + * The type T must have a copy constructor if it is not trivial copy-able. + * + * @warning Iterators return a non-const key_t in the pair. + * @warning A User is not allowed to change the key, otherwise the map is corrupted. + * * \ingroup container */ template> @@ -14,78 +32,84 @@ public: static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01); static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02); -private: - typedef KEY_COMPARE compare; - compare myComp; - ArrayList, uint32_t> theMap; - uint32_t _size; - - uint32_t findFirstIndex(key_t key, uint32_t startAt = 0) const { - if (startAt >= _size) { - return startAt + 1; - } - uint32_t i = startAt; - for (i = startAt; i < _size; ++i) { - if (theMap[i].first == key) { - return i; - } - } - return i; - } - - uint32_t findNicePlace(key_t key) const { - uint32_t i = 0; - for (i = 0; i < _size; ++i) { - if (myComp(key, theMap[i].first)) { - return i; - } - } - return i; - } - - void removeFromPosition(uint32_t position) { - if (_size <= position) { - return; - } - memmove(static_cast(&theMap[position]), static_cast(&theMap[position + 1]), - (_size - position - 1) * sizeof(std::pair)); - --_size; - } -public: - FixedOrderedMultimap(uint32_t maxSize) : - theMap(maxSize), _size(0) { + /*** + * Constructor which needs a size_t for the maximum allowed size + * + * Can not be resized during runtime + * + * Allocates memory at construction + * @param maxSize size_t of Maximum allowed size + */ + FixedOrderedMultimap(size_t maxSize) : + theMap(maxSize), _size(0) { } + /*** + * Virtual destructor frees Memory by deleting its member + */ virtual ~FixedOrderedMultimap() { } - class Iterator: public ArrayList, uint32_t>::Iterator { + /*** + * Special iterator for FixedOrderedMultimap + */ + class Iterator: public ArrayList, size_t>::Iterator { public: Iterator() : - ArrayList, uint32_t>::Iterator() { + ArrayList, size_t>::Iterator() { } Iterator(std::pair *pair) : - ArrayList, uint32_t>::Iterator(pair) { + ArrayList, size_t>::Iterator(pair) { } }; + friend bool operator==(const typename FixedOrderedMultimap::Iterator& lhs, + const typename FixedOrderedMultimap::Iterator& rhs) { + return (lhs.value == rhs.value); + } + + friend bool operator!=(const typename FixedOrderedMultimap::Iterator& lhs, + const typename FixedOrderedMultimap::Iterator& rhs) { + return not (lhs.value == rhs.value); + } + + /*** + * Returns an iterator on the first element + * @return Iterator pointing to first element + */ Iterator begin() const { return Iterator(&theMap[0]); } + /** + * Returns an iterator pointing to one element past the end + * @return Iterator pointing to one element past the end + */ Iterator end() const { return Iterator(&theMap[_size]); } - uint32_t size() const { + /*** + * Returns the current size of the map (not maximum size!) + * @return Current size + */ + size_t size() const { return _size; } + /*** + * Used to insert a key and value separately. + * + * @param[in] key Key of the new element + * @param[in] value Value of the new element + * @param[in/out] (optional) storedValue On success this points to the new value, otherwise a nullptr + * @return RETURN_OK if insert was successful, MAP_FULL if no space is available + */ ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) { if (_size == theMap.maxSize()) { return MAP_FULL; } - uint32_t position = findNicePlace(key); + size_t position = findNicePlace(key); memmove(static_cast(&theMap[position + 1]),static_cast(&theMap[position]), (_size - position) * sizeof(std::pair)); theMap[position].first = key; @@ -97,10 +121,21 @@ public: return HasReturnvaluesIF::RETURN_OK; } + /*** + * Used to insert new pair instead of single values + * + * @param pair Pair to be inserted + * @return RETURN_OK if insert was successful, MAP_FULL if no space is available + */ ReturnValue_t insert(std::pair pair) { return insert(pair.first, pair.second); } + /*** + * Can be used to check if a certain key is in the map + * @param key Key to be checked + * @return RETURN_OK if the key exists KEY_DOES_NOT_EXIST otherwise + */ ReturnValue_t exists(key_t key) const { ReturnValue_t result = KEY_DOES_NOT_EXIST; if (findFirstIndex(key) < _size) { @@ -109,8 +144,18 @@ public: return result; } + /*** + * Used to delete the element in the iterator + * + * The iterator will point to the element before or begin(), + * but never to one element in front of the map. + * + * @warning The iterator needs to be valid and dereferenceable + * @param[in/out] iter Pointer to iterator to the element that needs to be ereased + * @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this + */ ReturnValue_t erase(Iterator *iter) { - uint32_t i; + size_t i; if ((i = findFirstIndex((*iter).value->first)) >= _size) { return KEY_DOES_NOT_EXIST; } @@ -123,8 +168,13 @@ public: return HasReturnvaluesIF::RETURN_OK; } + /*** + * Used to erase by key + * @param key Key to be erased + * @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this + */ ReturnValue_t erase(key_t key) { - uint32_t i; + size_t i; if ((i = findFirstIndex(key)) >= _size) { return KEY_DOES_NOT_EXIST; } @@ -135,6 +185,14 @@ public: return HasReturnvaluesIF::RETURN_OK; } + /*** + * Find returns the first appearance of the key + * + * If the key does not exist, it points to end() + * + * @param key Key to search for + * @return Iterator pointing to the first entry of key + */ Iterator find(key_t key) const { ReturnValue_t result = exists(key); if (result != HasReturnvaluesIF::RETURN_OK) { @@ -143,6 +201,15 @@ public: return Iterator(&theMap[findFirstIndex(key)]); } + /*** + * Finds first entry of the given key and returns a + * pointer to the value + * + * @param key Key to search for + * @param value Found value + * @return RETURN_OK if it points to the value, + * KEY_DOES_NOT_EXIST if the key is not in the map + */ ReturnValue_t find(key_t key, T **value) const { ReturnValue_t result = exists(key); if (result != HasReturnvaluesIF::RETURN_OK) { @@ -151,15 +218,58 @@ public: *value = &theMap[findFirstIndex(key)].second; return HasReturnvaluesIF::RETURN_OK; } - + /** + * Clears the map, does not deallocate any memory + */ void clear() { _size = 0; } - uint32_t maxSize() const { + /** + * Returns the maximum size of the map + * @return Maximum size of the map + */ + size_t maxSize() const { return theMap.maxSize(); } +private: + typedef KEY_COMPARE compare; + compare myComp; + ArrayList, size_t> theMap; + size_t _size; + + size_t findFirstIndex(key_t key, size_t startAt = 0) const { + if (startAt >= _size) { + return startAt + 1; + } + size_t i = startAt; + for (i = startAt; i < _size; ++i) { + if (theMap[i].first == key) { + return i; + } + } + return i; + } + + size_t findNicePlace(key_t key) const { + size_t i = 0; + for (i = 0; i < _size; ++i) { + if (myComp(key, theMap[i].first)) { + return i; + } + } + return i; + } + + void removeFromPosition(size_t position) { + if (_size <= position) { + return; + } + memmove(static_cast(&theMap[position]), static_cast(&theMap[position + 1]), + (_size - position - 1) * sizeof(std::pair)); + --_size; + } }; #endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ */ From c86d654fdfedfb3319e9ace45dc83874ce8d5c6a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 1 Oct 2020 13:58:20 +0200 Subject: [PATCH 415/653] tpp file added --- container/FixedOrderedMultimap.h | 197 ++++++++++++----------------- container/FixedOrderedMultimap.tpp | 143 +++++++++++++++++++++ 2 files changed, 222 insertions(+), 118 deletions(-) create mode 100644 container/FixedOrderedMultimap.tpp diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 717575d7..cb8ab10f 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -1,24 +1,91 @@ -#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ -#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ +#ifndef FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_ +#define FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_ #include "ArrayList.h" #include -#include + /** - * \ingroup container + * @brief Map implementation which allows entries with identical keys + * @details + * Performs no dynamic memory allocation except on initialization. + * Uses an ArrayList as the underlying container and thus has a linear + * complexity O(n). As long as the number of entries remains low, this + * should not be an issue. + * The number of insertion and deletion operation should be minimized + * as those incur exensive memory move operations (the underlying container + * is not node based). + * @ingroup container */ template> class FixedOrderedMultimap { public: static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP; - static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01); - static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02); + 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); + + /** + * Initializes the ordered multimap with a fixed maximum size. + * @param maxSize + */ + FixedOrderedMultimap(size_t maxSize); + + virtual ~FixedOrderedMultimap() {} + + class Iterator: public ArrayList, uint32_t>::Iterator { + public: + /** Returns an iterator to nullptr */ + Iterator(); + /** Initializes iterator to given entry */ + Iterator(std::pair *pair); + }; + + /** Iterator to start of map */ + Iterator begin() const; + /** Iterator to end of map */ + Iterator end() const; + /** Current (variable) size of the map */ + size_t size() const; + + /** + * Insert a key/value pair inside the map. An iterator to the stored + * value might be returned optionally. + * @param key + * @param value + * @param storedValue + * @return + */ + ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr); + /** + * Insert a given std::pair + * @param pair + * @return + */ + ReturnValue_t insert(std::pair pair); + /** + * Checks existence of key in map. + * @param key + * @return + * - @c KEY_DOES_NOT_EXIST if key does not exists. + * - @c RETURN_OK otherwise. + */ + ReturnValue_t exists(key_t key) const; + + ReturnValue_t erase(Iterator *iter); + ReturnValue_t erase(key_t key); + + Iterator find(key_t key) const; + ReturnValue_t find(key_t key, T **value) const; + + void clear(); + + size_t maxSize() const; private: typedef KEY_COMPARE compare; compare myComp; ArrayList, uint32_t> theMap; - uint32_t _size; + size_t _size; uint32_t findFirstIndex(key_t key, uint32_t startAt = 0) const { if (startAt >= _size) { @@ -47,119 +114,13 @@ private: if (_size <= position) { return; } - memmove(static_cast(&theMap[position]), static_cast(&theMap[position + 1]), + std::memmove(static_cast(&theMap[position]), + static_cast(&theMap[position + 1]), (_size - position - 1) * sizeof(std::pair)); --_size; } -public: - FixedOrderedMultimap(uint32_t maxSize) : - theMap(maxSize), _size(0) { - } - virtual ~FixedOrderedMultimap() { - } - - class Iterator: public ArrayList, uint32_t>::Iterator { - public: - Iterator() : - ArrayList, uint32_t>::Iterator() { - } - - Iterator(std::pair *pair) : - ArrayList, uint32_t>::Iterator(pair) { - } - }; - - Iterator begin() const { - return Iterator(&theMap[0]); - } - - Iterator end() const { - return Iterator(&theMap[_size]); - } - - uint32_t size() const { - return _size; - } - - ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) { - if (_size == theMap.maxSize()) { - return MAP_FULL; - } - uint32_t position = findNicePlace(key); - memmove(static_cast(&theMap[position + 1]),static_cast(&theMap[position]), - (_size - position) * sizeof(std::pair)); - theMap[position].first = key; - theMap[position].second = value; - ++_size; - if (storedValue != nullptr) { - *storedValue = Iterator(&theMap[position]); - } - return HasReturnvaluesIF::RETURN_OK; - } - - ReturnValue_t insert(std::pair pair) { - return insert(pair.first, pair.second); - } - - ReturnValue_t exists(key_t key) const { - ReturnValue_t result = KEY_DOES_NOT_EXIST; - if (findFirstIndex(key) < _size) { - result = HasReturnvaluesIF::RETURN_OK; - } - return result; - } - - ReturnValue_t erase(Iterator *iter) { - uint32_t i; - if ((i = findFirstIndex((*iter).value->first)) >= _size) { - return KEY_DOES_NOT_EXIST; - } - removeFromPosition(i); - if (*iter != begin()) { - (*iter)--; - } else { - *iter = begin(); - } - return HasReturnvaluesIF::RETURN_OK; - } - - ReturnValue_t erase(key_t key) { - uint32_t i; - if ((i = findFirstIndex(key)) >= _size) { - return KEY_DOES_NOT_EXIST; - } - do { - removeFromPosition(i); - i = findFirstIndex(key, i); - } while (i < _size); - return HasReturnvaluesIF::RETURN_OK; - } - - Iterator find(key_t key) const { - ReturnValue_t result = exists(key); - if (result != HasReturnvaluesIF::RETURN_OK) { - return end(); - } - return Iterator(&theMap[findFirstIndex(key)]); - } - - ReturnValue_t find(key_t key, T **value) const { - ReturnValue_t result = exists(key); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - *value = &theMap[findFirstIndex(key)].second; - return HasReturnvaluesIF::RETURN_OK; - } - - void clear() { - _size = 0; - } - - uint32_t maxSize() const { - return theMap.maxSize(); - } - }; -#endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ */ +#include "FixedOrderedMultimap.tpp" + +#endif /* FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_ */ diff --git a/container/FixedOrderedMultimap.tpp b/container/FixedOrderedMultimap.tpp new file mode 100644 index 00000000..bc76c594 --- /dev/null +++ b/container/FixedOrderedMultimap.tpp @@ -0,0 +1,143 @@ +#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ +#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ + +template +inline FixedOrderedMultimap::Iterator::Iterator(): + ArrayList, uint32_t>::Iterator(){} + +template +inline FixedOrderedMultimap::Iterator::Iterator( + std::pair *pair): + ArrayList, uint32_t>::Iterator(pair){} + +template +inline typename FixedOrderedMultimap::Iterator +FixedOrderedMultimap::begin() const { + return Iterator(&theMap[0]); +} + +template +inline typename FixedOrderedMultimap::Iterator +FixedOrderedMultimap::end() const { + return Iterator(&theMap[_size]); +} + + +template +inline size_t FixedOrderedMultimap::size() const { + return _size; +} + +template +inline FixedOrderedMultimap::FixedOrderedMultimap( + size_t maxSize): theMap(maxSize), _size(0) {} + + +template +inline ReturnValue_t FixedOrderedMultimap::insert( + key_t key, T value, Iterator *storedValue) { + if (_size == theMap.maxSize()) { + return MAP_FULL; + } + uint32_t position = findNicePlace(key); + // Compiler might emitt warning because std::pair is not a POD type (yet..) + // See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm#std::pair-example + // Circumvent warning by casting to void* + std::memmove(static_cast(&theMap[position + 1]), + static_cast(&theMap[position]), + (_size - position) * sizeof(std::pair)); + theMap[position].first = key; + theMap[position].second = value; + ++_size; + if (storedValue != nullptr) { + *storedValue = Iterator(&theMap[position]); + } + return HasReturnvaluesIF::RETURN_OK; +} + +template +inline ReturnValue_t FixedOrderedMultimap::insert( + std::pair pair) { + return insert(pair.fist, pair.second); +} + +template +inline ReturnValue_t FixedOrderedMultimap::exists( + key_t key) const { + ReturnValue_t result = KEY_DOES_NOT_EXIST; + if (findFirstIndex(key) < _size) { + result = HasReturnvaluesIF::RETURN_OK; + } + return result; +} + +template +inline ReturnValue_t FixedOrderedMultimap::erase( + Iterator *iter) +{ + uint32_t i; + if ((i = findFirstIndex((*iter).value->first)) >= _size) { + return KEY_DOES_NOT_EXIST; + } + removeFromPosition(i); + if (*iter != begin()) { + (*iter)--; + } else { + *iter = begin(); + } + return HasReturnvaluesIF::RETURN_OK; +} + +template +inline ReturnValue_t FixedOrderedMultimap::erase( + key_t key) +{ + uint32_t i; + if ((i = findFirstIndex(key)) >= _size) { + return KEY_DOES_NOT_EXIST; + } + do { + removeFromPosition(i); + i = findFirstIndex(key, i); + } while (i < _size); + return HasReturnvaluesIF::RETURN_OK; +} + +template +inline ReturnValue_t FixedOrderedMultimap::find( + key_t key, T **value) const +{ + ReturnValue_t result = exists(key); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + *value = &theMap[findFirstIndex(key)].second; + return HasReturnvaluesIF::RETURN_OK; +} + +template +inline typename FixedOrderedMultimap::Iterator +FixedOrderedMultimap::find( + key_t key) const +{ + ReturnValue_t result = exists(key); + if (result != HasReturnvaluesIF::RETURN_OK) { + return end(); + } + return Iterator(&theMap[findFirstIndex(key)]); +} + +template +inline void FixedOrderedMultimap::clear() +{ + _size = 0; +} + +template +inline size_t FixedOrderedMultimap::maxSize() const +{ + return theMap.maxSize(); +} + + +#endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ */ From 587f87d270b282726363f348467f130370d61f96 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 1 Oct 2020 17:27:24 +0200 Subject: [PATCH 416/653] Feedback from Robin --- container/FixedOrderedMultimap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 4bbea302..82d388c9 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -5,7 +5,7 @@ #include /** - * @brief A "Map" which allows multiple entries of the same key. + * @brief An associative container which allows multiple entries of the same key. * @details * Same keys are ordered by KEY_COMPARE function which is std::less > by default. * From f1bc9972f3217981b895a6e48e9aca816340512c Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 1 Oct 2020 17:36:46 +0200 Subject: [PATCH 417/653] Fixed bugs --- container/FixedOrderedMultimap.tpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/container/FixedOrderedMultimap.tpp b/container/FixedOrderedMultimap.tpp index 715bf474..16a7124b 100644 --- a/container/FixedOrderedMultimap.tpp +++ b/container/FixedOrderedMultimap.tpp @@ -2,8 +2,8 @@ #define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ -template> -ReturnValue_t FixedOrderedMultimap::insert(key_t key, T value, Iterator *storedValue = nullptr) { +template +ReturnValue_t FixedOrderedMultimap::insert(key_t key, T value, Iterator *storedValue) { if (_size == theMap.maxSize()) { return MAP_FULL; } @@ -18,12 +18,12 @@ ReturnValue_t FixedOrderedMultimap::insert(key_t key, T v } return HasReturnvaluesIF::RETURN_OK; } -template> +template ReturnValue_t FixedOrderedMultimap::insert(std::pair pair) { return insert(pair.first, pair.second); } -template> +template ReturnValue_t FixedOrderedMultimap::exists(key_t key) const { ReturnValue_t result = KEY_DOES_NOT_EXIST; if (findFirstIndex(key) < _size) { @@ -32,7 +32,7 @@ ReturnValue_t FixedOrderedMultimap::exists(key_t key) con return result; } -template> +template ReturnValue_t FixedOrderedMultimap::erase(Iterator *iter) { size_t i; if ((i = findFirstIndex((*iter).value->first)) >= _size) { @@ -47,7 +47,7 @@ ReturnValue_t FixedOrderedMultimap::erase(Iterator *iter) return HasReturnvaluesIF::RETURN_OK; } -template> +template ReturnValue_t FixedOrderedMultimap::erase(key_t key) { size_t i; if ((i = findFirstIndex(key)) >= _size) { @@ -60,7 +60,7 @@ ReturnValue_t FixedOrderedMultimap::erase(key_t key) { return HasReturnvaluesIF::RETURN_OK; } -template> +template FixedOrderedMultimap::Iterator FixedOrderedMultimap::find(key_t key) const { ReturnValue_t result = exists(key); if (result != HasReturnvaluesIF::RETURN_OK) { @@ -69,7 +69,7 @@ FixedOrderedMultimap::Iterator FixedOrderedMultimap> +template ReturnValue_t FixedOrderedMultimap::find(key_t key, T **value) const { ReturnValue_t result = exists(key); if (result != HasReturnvaluesIF::RETURN_OK) { @@ -79,8 +79,8 @@ ReturnValue_t FixedOrderedMultimap::find(key_t key, T **v return HasReturnvaluesIF::RETURN_OK; } -template> -size_t FixedOrderedMultimap::findFirstIndex(key_t key, size_t startAt = 0) const { +template +size_t FixedOrderedMultimap::findFirstIndex(key_t key, size_t startAt) const { if (startAt >= _size) { return startAt + 1; } @@ -93,7 +93,7 @@ size_t FixedOrderedMultimap::findFirstIndex(key_t key, si return i; } -template> +template size_t FixedOrderedMultimap::findNicePlace(key_t key) const { size_t i = 0; for (i = 0; i < _size; ++i) { @@ -104,7 +104,7 @@ size_t FixedOrderedMultimap::findNicePlace(key_t key) con return i; } -template> +template void FixedOrderedMultimap::removeFromPosition(size_t position) { if (_size <= position) { return; From 6776ca86eb0df44f2580139c48f6f394b5e6a727 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 1 Oct 2020 17:44:23 +0200 Subject: [PATCH 418/653] Made tpp file less cluttered and added inline qualifier --- container/FixedOrderedMultimap.h | 8 +++++++- container/FixedOrderedMultimap.tpp | 27 +++++++++------------------ 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 82d388c9..96bc0073 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -159,7 +159,13 @@ public: * @param key Key to search for * @return Iterator pointing to the first entry of key */ - Iterator find(key_t key) const; + Iterator find(key_t key) const{ + ReturnValue_t result = exists(key); + if (result != HasReturnvaluesIF::RETURN_OK) { + return end(); + } + return Iterator(&theMap[findFirstIndex(key)]); + }; /*** * Finds first entry of the given key and returns a diff --git a/container/FixedOrderedMultimap.tpp b/container/FixedOrderedMultimap.tpp index 16a7124b..4aa85e97 100644 --- a/container/FixedOrderedMultimap.tpp +++ b/container/FixedOrderedMultimap.tpp @@ -3,7 +3,7 @@ template -ReturnValue_t FixedOrderedMultimap::insert(key_t key, T value, Iterator *storedValue) { +inline ReturnValue_t FixedOrderedMultimap::insert(key_t key, T value, Iterator *storedValue) { if (_size == theMap.maxSize()) { return MAP_FULL; } @@ -19,12 +19,12 @@ ReturnValue_t FixedOrderedMultimap::insert(key_t key, T v return HasReturnvaluesIF::RETURN_OK; } template -ReturnValue_t FixedOrderedMultimap::insert(std::pair pair) { +inline ReturnValue_t FixedOrderedMultimap::insert(std::pair pair) { return insert(pair.first, pair.second); } template -ReturnValue_t FixedOrderedMultimap::exists(key_t key) const { +inline ReturnValue_t FixedOrderedMultimap::exists(key_t key) const { ReturnValue_t result = KEY_DOES_NOT_EXIST; if (findFirstIndex(key) < _size) { result = HasReturnvaluesIF::RETURN_OK; @@ -33,7 +33,7 @@ ReturnValue_t FixedOrderedMultimap::exists(key_t key) con } template -ReturnValue_t FixedOrderedMultimap::erase(Iterator *iter) { +inline ReturnValue_t FixedOrderedMultimap::erase(Iterator *iter) { size_t i; if ((i = findFirstIndex((*iter).value->first)) >= _size) { return KEY_DOES_NOT_EXIST; @@ -48,7 +48,7 @@ ReturnValue_t FixedOrderedMultimap::erase(Iterator *iter) } template -ReturnValue_t FixedOrderedMultimap::erase(key_t key) { +inline ReturnValue_t FixedOrderedMultimap::erase(key_t key) { size_t i; if ((i = findFirstIndex(key)) >= _size) { return KEY_DOES_NOT_EXIST; @@ -61,16 +61,7 @@ ReturnValue_t FixedOrderedMultimap::erase(key_t key) { } template -FixedOrderedMultimap::Iterator FixedOrderedMultimap::find(key_t key) const { - ReturnValue_t result = exists(key); - if (result != HasReturnvaluesIF::RETURN_OK) { - return end(); - } - return Iterator(&theMap[findFirstIndex(key)]); -} - -template -ReturnValue_t FixedOrderedMultimap::find(key_t key, T **value) const { +inline ReturnValue_t FixedOrderedMultimap::find(key_t key, T **value) const { ReturnValue_t result = exists(key); if (result != HasReturnvaluesIF::RETURN_OK) { return result; @@ -80,7 +71,7 @@ ReturnValue_t FixedOrderedMultimap::find(key_t key, T **v } template -size_t FixedOrderedMultimap::findFirstIndex(key_t key, size_t startAt) const { +inline size_t FixedOrderedMultimap::findFirstIndex(key_t key, size_t startAt) const { if (startAt >= _size) { return startAt + 1; } @@ -94,7 +85,7 @@ size_t FixedOrderedMultimap::findFirstIndex(key_t key, si } template -size_t FixedOrderedMultimap::findNicePlace(key_t key) const { +inline size_t FixedOrderedMultimap::findNicePlace(key_t key) const { size_t i = 0; for (i = 0; i < _size; ++i) { if (myComp(key, theMap[i].first)) { @@ -105,7 +96,7 @@ size_t FixedOrderedMultimap::findNicePlace(key_t key) con } template -void FixedOrderedMultimap::removeFromPosition(size_t position) { +inline void FixedOrderedMultimap::removeFromPosition(size_t position) { if (_size <= position) { return; } From ea8ef8b874248e8ef19667a25a20b63aa646af1e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 3 Oct 2020 14:19:42 +0200 Subject: [PATCH 419/653] important bugfix --- tcdistribution/PUSDistributor.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tcdistribution/PUSDistributor.cpp b/tcdistribution/PUSDistributor.cpp index 3baef7d1..63d1dcde 100644 --- a/tcdistribution/PUSDistributor.cpp +++ b/tcdistribution/PUSDistributor.cpp @@ -17,8 +17,11 @@ PUSDistributor::TcMqMapIter PUSDistributor::selectDestination() { // << this->current_packet_id.store_index << ", " // << this->current_packet_id.packet_index << std::endl; TcMqMapIter queueMapIt = this->queueMap.end(); + if(this->currentPacket == nullptr) { + return queueMapIt; + } this->currentPacket->setStoreAddress(this->currentMessage.getStorageId()); - if (currentPacket->getWholeData() != NULL) { + if (currentPacket->getWholeData() != nullptr) { tcStatus = checker.checkPacket(currentPacket); #ifdef DEBUG if(tcStatus != HasReturnvaluesIF::RETURN_OK) { @@ -94,6 +97,7 @@ uint16_t PUSDistributor::getIdentifier() { ReturnValue_t PUSDistributor::initialize() { CCSDSDistributorIF* ccsdsDistributor = objectManager->get(packetSource); + currentPacket = new TcPacketStored(); if (ccsdsDistributor == nullptr) { sif::error << "PUSDistributor::initialize: Packet source invalid." << " Make sure it exists and implements CCSDSDistributorIF!" @@ -103,6 +107,4 @@ ReturnValue_t PUSDistributor::initialize() { else { return ccsdsDistributor->registerApplication(this); } - - currentPacket = new TcPacketStored(); } From 17ea3127a79f7c0d575cb857cd9197de741ff5ac Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 10 Oct 2020 17:04:43 +0200 Subject: [PATCH 420/653] minor form improvements, include guards --- action/ActionHelper.cpp | 15 +++++---- action/ActionHelper.h | 74 ++++++++++++++++++++++++++--------------- 2 files changed, 56 insertions(+), 33 deletions(-) diff --git a/action/ActionHelper.cpp b/action/ActionHelper.cpp index 361f7dc3..ab986c6c 100644 --- a/action/ActionHelper.cpp +++ b/action/ActionHelper.cpp @@ -3,8 +3,9 @@ #include "../ipc/MessageQueueSenderIF.h" #include "../objectmanager/ObjectManagerIF.h" -ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue) : - owner(setOwner), queueToUse(useThisQueue), ipcStore(nullptr) { +ActionHelper::ActionHelper(HasActionsIF* setOwner, + MessageQueueIF* useThisQueue) : + owner(setOwner), queueToUse(useThisQueue) { } ActionHelper::~ActionHelper() { @@ -33,13 +34,15 @@ ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) { return HasReturnvaluesIF::RETURN_OK; } -void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result) { +void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo, + ActionId_t commandId, ReturnValue_t result) { CommandMessage reply; ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result); queueToUse->sendMessage(reportTo, &reply); } -void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result) { +void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId, + ReturnValue_t result) { CommandMessage reply; ActionMessage::setCompletionReply(&reply, commandId, result); queueToUse->sendMessage(reportTo, &reply); @@ -49,8 +52,8 @@ void ActionHelper::setQueueToUse(MessageQueueIF* queue) { queueToUse = queue; } -void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, - store_address_t dataAddress) { +void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, + ActionId_t actionId, store_address_t dataAddress) { const uint8_t* dataPtr = NULL; size_t size = 0; ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size); diff --git a/action/ActionHelper.h b/action/ActionHelper.h index bbc6d114..a20f286a 100644 --- a/action/ActionHelper.h +++ b/action/ActionHelper.h @@ -1,15 +1,18 @@ -#ifndef ACTIONHELPER_H_ -#define ACTIONHELPER_H_ +#ifndef FSFW_ACTION_ACTIONHELPER_H_ +#define FSFW_ACTION_ACTIONHELPER_H_ #include "ActionMessage.h" #include "../serialize/SerializeIF.h" #include "../ipc/MessageQueueIF.h" /** - * \brief Action Helper is a helper class which handles action messages + * @brief Action Helper is a helper class which handles action messages * - * Components which use the HasActionIF this helper can be used to handle the action messages. - * It does handle step messages as well as other answers to action calls. It uses the executeAction function - * of its owner as callback. The call of the initialize function is mandatory and it needs a valid messageQueueIF pointer! + * Components which use the HasActionIF this helper can be used to handle + * the action messages. + * It does handle step messages as well as other answers to action calls. + * It uses the executeAction function of its owner as callback. + * The call of the initialize function is mandatory and needs a + * valid MessageQueueIF pointer! */ class HasActionsIF; @@ -18,7 +21,8 @@ public: /** * Constructor of the action helper * @param setOwner Pointer to the owner of the interface - * @param useThisQueue messageQueue to be used, can be set during initialize function as well. + * @param useThisQueue messageQueue to be used, can be set during + * initialize function as well. */ ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue); @@ -26,28 +30,35 @@ public: /** * Function to be called from the owner with a new command message * - * If the message is a valid action message the helper will use the executeAction function from HasActionsIF. - * If the message is invalid or the callback fails a message reply will be send to the sender of the message automatically. + * If the message is a valid action message the helper will use the + * executeAction function from HasActionsIF. + * If the message is invalid or the callback fails a message reply will be + * send to the sender of the message automatically. * * @param command Pointer to a command message received by the owner - * @return HasReturnvaluesIF::RETURN_OK if the message is a action message, CommandMessage::UNKNOW_COMMAND if this message ID is unkown + * @return HasReturnvaluesIF::RETURN_OK if the message is a action message, + * CommandMessage::UNKNOW_COMMAND if this message ID is unkown */ ReturnValue_t handleActionMessage(CommandMessage* command); /** - * Helper initialize function. Must be called before use of any other helper function - * @param queueToUse_ Pointer to the messageQueue to be used, optional if queue was set in constructor + * Helper initialize function. Must be called before use of any other + * helper function + * @param queueToUse_ Pointer to the messageQueue to be used, optional + * if queue was set in constructor * @return Returns RETURN_OK if successful */ ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr); /** - * Function to be called from the owner to send a step message. Success or failure will be determined by the result value. + * Function to be called from the owner to send a step message. + * Success or failure will be determined by the result value. * * @param step Number of steps already done * @param reportTo The messageQueueId to report the step message to * @param commandId ID of the executed command * @param result Result of the execution */ - void step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); + void step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId, + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); /** * Function to be called by the owner to send a action completion message * @@ -55,39 +66,48 @@ public: * @param commandId ID of the executed command * @param result Result of the execution */ - void finish(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); /** * Function to be called by the owner if an action does report data * - * @param reportTo MessageQueueId_t to report the action completion message to + * @param reportTo MessageQueueId_t to report the action completion + * message to * @param replyId ID of the executed command * @param data Pointer to the data * @return Returns RETURN_OK if successful, otherwise failure code */ - ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data, bool hideSender = false); + ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, + SerializeIF* data, bool hideSender = false); /** - * Function to setup the MessageQueueIF* of the helper. Can be used to set the messageQueueIF* if - * message queue is unavailable at construction and initialize but must be setup before first call of other functions. + * Function to setup the MessageQueueIF* of the helper. Can be used to + * set the MessageQueueIF* if message queue is unavailable at construction + * and initialize but must be setup before first call of other functions. * @param queue Queue to be used by the helper */ void setQueueToUse(MessageQueueIF *queue); protected: - static const uint8_t STEP_OFFSET = 1;//!< Increase of value of this per step + //!< Increase of value of this per step + static const uint8_t STEP_OFFSET = 1; HasActionsIF* owner;//!< Pointer to the owner - MessageQueueIF* queueToUse;//!< Queue to be used as response sender, has to be set with - StorageManagerIF* ipcStore;//!< Pointer to an IPC Store, initialized during construction or initialize(MessageQueueIF* queueToUse_) or with setQueueToUse(MessageQueueIF *queue) + //! Queue to be used as response sender, has to be set in ctor or with + //! setQueueToUse + MessageQueueIF* queueToUse; + //! Pointer to an IPC Store, initialized during construction or + StorageManagerIF* ipcStore = nullptr; + /** - *Internal function called by handleActionMessage(CommandMessage* command) - * + * Internal function called by handleActionMessage * @param commandedBy MessageQueueID of Commander * @param actionId ID of action to be done * @param dataAddress Address of additional data in IPC Store */ - virtual void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress); + virtual void prepareExecution(MessageQueueId_t commandedBy, + ActionId_t actionId, store_address_t dataAddress); /** - * + * @brief Default implementation is empty. */ virtual void resetHelper(); }; -#endif /* ACTIONHELPER_H_ */ +#endif /* FSFW_ACTION_ACTIONHELPER_H_ */ From b6a23727f2dcbe498276b3c86306d24a8e1462f8 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 12 Oct 2020 15:40:27 +0200 Subject: [PATCH 421/653] added extended controller base --- controller/ExtendedControllerBase.cpp | 114 ++++++++++++++++++++++++++ controller/ExtendedControllerBase.h | 72 ++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 controller/ExtendedControllerBase.cpp create mode 100644 controller/ExtendedControllerBase.h diff --git a/controller/ExtendedControllerBase.cpp b/controller/ExtendedControllerBase.cpp new file mode 100644 index 00000000..f69d2ea1 --- /dev/null +++ b/controller/ExtendedControllerBase.cpp @@ -0,0 +1,114 @@ +#include "ExtendedControllerBase.h" + + +ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, + object_id_t parentId, size_t commandQueueDepth): + ControllerBase(objectId, parentId, commandQueueDepth), + localPoolManager(this, commandQueue), + actionHelper(this, commandQueue) { +} + +ReturnValue_t ExtendedControllerBase::executeAction(ActionId_t actionId, + MessageQueueId_t commandedBy, const uint8_t *data, size_t size) { + // needs to be overriden and implemented by child class. + return HasReturnvaluesIF::RETURN_OK; +} + + + +ReturnValue_t ExtendedControllerBase::initializeLocalDataPool( + LocalDataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { + // needs to be overriden and implemented by child class. + return HasReturnvaluesIF::RETURN_OK; +} + +object_id_t ExtendedControllerBase::getObjectId() const { + return SystemObject::getObjectId(); +} + +LocalDataPoolManager* ExtendedControllerBase::getHkManagerHandle() { + return &localPoolManager; +} + +uint32_t ExtendedControllerBase::getPeriodicOperationFrequency() const { + return this->executingTask->getPeriodMs(); +} + +ReturnValue_t ExtendedControllerBase::handleCommandMessage( + CommandMessage *message) { + ReturnValue_t result = actionHelper.handleActionMessage(message); + if(result == HasReturnvaluesIF::RETURN_OK) { + return result; + } + return localPoolManager.handleHousekeepingMessage(message); +} + +void ExtendedControllerBase::handleQueue() { + CommandMessage command; + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + for (result = commandQueue->receiveMessage(&command); + result == RETURN_OK; + result = commandQueue->receiveMessage(&command)) { + result = actionHelper.handleActionMessage(&command); + if (result == RETURN_OK) { + continue; + } + + result = modeHelper.handleModeCommand(&command); + if (result == RETURN_OK) { + continue; + } + + result = healthHelper.handleHealthCommand(&command); + if (result == RETURN_OK) { + continue; + } + + result = localPoolManager.handleHousekeepingMessage(&command); + if (result == RETURN_OK) { + continue; + } + + result = handleCommandMessage(&command); + if (result == RETURN_OK) { + continue; + } + command.setToUnknownCommand(); + commandQueue->reply(&command); + } +} + +ReturnValue_t ExtendedControllerBase::initialize() { + ReturnValue_t result = ControllerBase::initialize(); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = actionHelper.initialize(commandQueue); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + return localPoolManager.initialize(commandQueue); +} + +ReturnValue_t ExtendedControllerBase::initializeAfterTaskCreation() { + return localPoolManager.initializeAfterTaskCreation(); +} + +ReturnValue_t ExtendedControllerBase::performOperation(uint8_t opCode) { + handleQueue(); + hkSwitcher.performOperation(); + localPoolManager.performHkOperation(); + performControlOperation(); + return RETURN_OK; +} + +MessageQueueId_t ExtendedControllerBase::getCommandQueue() const { + return commandQueue->getId(); +} + +LocalPoolDataSetBase* ExtendedControllerBase::getDataSetHandle(sid_t sid) { + sif::warning << "ExtendedControllerBase::getDataSetHandle: No child " + << " implementation provided, returning nullptr!" << std::endl; + return nullptr; +} diff --git a/controller/ExtendedControllerBase.h b/controller/ExtendedControllerBase.h new file mode 100644 index 00000000..02c5728e --- /dev/null +++ b/controller/ExtendedControllerBase.h @@ -0,0 +1,72 @@ +#ifndef FSFW_CONTROLLER_EXTENDEDCONTROLLERBASE_H_ +#define FSFW_CONTROLLER_EXTENDEDCONTROLLERBASE_H_ + +#include "ControllerBase.h" + +#include "../action/HasActionsIF.h" +#include "../datapoollocal/HasLocalDataPoolIF.h" +#include "../action/ActionHelper.h" +#include "../datapoollocal/LocalDataPoolManager.h" + +/** + * @brief Extendes the basic ControllerBase with the common components + * HasActionsIF for commandability and HasLocalDataPoolIF to keep + * a pool of local data pool variables. + * @details + * Default implementations required for the interfaces will be empty and have + * to be implemented by child class. + */ +class ExtendedControllerBase: public ControllerBase, + public HasActionsIF, + public HasLocalDataPoolIF { +public: + ExtendedControllerBase(object_id_t objectId, object_id_t parentId, + size_t commandQueueDepth = 3); + + /** SystemObjectIF overrides */ + virtual ReturnValue_t initialize() override; + + virtual MessageQueueId_t getCommandQueue() const override; + + /** ExecutableObjectIF overrides */ + virtual ReturnValue_t performOperation(uint8_t opCode) override; + virtual ReturnValue_t initializeAfterTaskCreation() override; + +protected: + LocalDataPoolManager localPoolManager; + ActionHelper actionHelper; + + /** + * Implemented by child class. Handle all command messages which are + * not health, mode, action or housekeeping messages. + * @param message + * @return + */ + virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0; + + /** + * Periodic helper from ControllerBase, implemented by child class. + */ + virtual void performControlOperation() = 0; + + /** Handle the four messages mentioned above */ + void handleQueue() override; + + /** HasActionsIF overrides */ + virtual ReturnValue_t executeAction(ActionId_t actionId, + MessageQueueId_t commandedBy, const uint8_t* data, + size_t size) override; + + /** HasLocalDatapoolIF overrides */ + virtual object_id_t getObjectId() const override; + virtual ReturnValue_t initializeLocalDataPool( + LocalDataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override; + virtual LocalDataPoolManager* getHkManagerHandle() override; + virtual uint32_t getPeriodicOperationFrequency() const override; + virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; +}; + + + +#endif /* FSFW_CONTROLLER_EXTENDEDCONTROLLERBASE_H_ */ From 829be0f08298c8aea79eccfff9403a2c23e381c8 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 12 Oct 2020 16:58:04 +0200 Subject: [PATCH 422/653] doc correction, action helper new helper function --- action/ActionHelper.cpp | 56 +++++++++++++++++++++++++++++++++++------ action/ActionHelper.h | 15 +++++++++-- action/HasActionsIF.h | 7 +++--- 3 files changed, 65 insertions(+), 13 deletions(-) diff --git a/action/ActionHelper.cpp b/action/ActionHelper.cpp index ab986c6c..8122885b 100644 --- a/action/ActionHelper.cpp +++ b/action/ActionHelper.cpp @@ -89,22 +89,28 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - result = data->serialize(&dataPtr, &size, maxSize, SerializeIF::Endianness::BIG); + result = data->serialize(&dataPtr, &size, maxSize, + SerializeIF::Endianness::BIG); if (result != HasReturnvaluesIF::RETURN_OK) { ipcStore->deleteData(storeAddress); 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. + // 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); - //TODO Service Implementation sucks at the moment - if (hideSender){ + // TODO: Service Implementation sucks at the moment + // TODO: why does it suck and why would someone need to hide the sender? + if (hideSender) { result = MessageQueueSenderIF::sendMessage(reportTo, &reply); - } else { + } + else { result = queueToUse->sendMessage(reportTo, &reply); } - if ( result != HasReturnvaluesIF::RETURN_OK){ + + if (result != HasReturnvaluesIF::RETURN_OK){ ipcStore->deleteData(storeAddress); } return result; @@ -112,3 +118,39 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, void ActionHelper::resetHelper() { } + +ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, + ActionId_t replyId, const uint8_t *data, size_t dataSize, + bool hideSender) { + CommandMessage reply; + store_address_t storeAddress; + ReturnValue_t result = ipcStore->addData(&storeAddress, data, dataSize); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + if (result != HasReturnvaluesIF::RETURN_OK) { + ipcStore->deleteData(storeAddress); + 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); + + // TODO: Service Implementation sucks at the moment + // TODO: why does it suck and why would someone need to hide the sender? + if (hideSender) { + result = MessageQueueSenderIF::sendMessage(reportTo, &reply); + } + else { + result = queueToUse->sendMessage(reportTo, &reply); + } + + if (result != HasReturnvaluesIF::RETURN_OK){ + ipcStore->deleteData(storeAddress); + } + return result; +} diff --git a/action/ActionHelper.h b/action/ActionHelper.h index a20f286a..17ca3ebd 100644 --- a/action/ActionHelper.h +++ b/action/ActionHelper.h @@ -69,8 +69,8 @@ public: void finish(MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); /** - * Function to be called by the owner if an action does report data - * + * Function to be called by the owner if an action does report data. + * Takes a SerializeIF* pointer and serializes it into the IPC store. * @param reportTo MessageQueueId_t to report the action completion * message to * @param replyId ID of the executed command @@ -79,6 +79,17 @@ public: */ ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data, bool hideSender = false); + /** + * Function to be called by the owner if an action does report data. + * Takes the raw data and writes it into the IPC store. + * @param reportTo MessageQueueId_t to report the action completion + * message to + * @param replyId ID of the executed command + * @param data Pointer to the data + * @return Returns RETURN_OK if successful, otherwise failure code + */ + ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, + const uint8_t* data, size_t dataSize, bool hideSender = false); /** * Function to setup the MessageQueueIF* of the helper. Can be used to * set the MessageQueueIF* if message queue is unavailable at construction diff --git a/action/HasActionsIF.h b/action/HasActionsIF.h index 886d0837..a26ed588 100644 --- a/action/HasActionsIF.h +++ b/action/HasActionsIF.h @@ -47,10 +47,9 @@ public: virtual MessageQueueId_t getCommandQueue() const = 0; /** * Execute or initialize the execution of a certain function. - * Returning #EXECUTION_FINISHED or a failure code, nothing else needs to - * be done. When needing more steps, return RETURN_OK and issue steps and - * completion manually. - * One "step failed" or completion report must be issued! + * When used in conjunction with the ActionHelper class, returning + * a return code which is not equal to RETURN_OK will trigger a step reply + * with step 0. */ virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0; From 140aa3ab422cc220dbbcf16f1d24242a73b3c933 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 12 Oct 2020 18:18:41 +0200 Subject: [PATCH 423/653] form improvements DHB --- devicehandlers/AcceptsDeviceResponsesIF.h | 22 +-- devicehandlers/AssemblyBase.cpp | 13 +- devicehandlers/AssemblyBase.h | 90 ++++++--- devicehandlers/ChildHandlerBase.cpp | 10 +- devicehandlers/ChildHandlerBase.h | 14 +- devicehandlers/ChildHandlerFDIR.cpp | 3 +- devicehandlers/ChildHandlerFDIR.h | 4 +- devicehandlers/CookieIF.h | 10 +- devicehandlers/DeviceCommunicationIF.h | 43 ++-- devicehandlers/DeviceHandlerBase.cpp | 183 ++++++++++++------ devicehandlers/DeviceHandlerBase.h | 170 ++++++++-------- .../DeviceHandlerFailureIsolation.cpp | 8 + devicehandlers/DeviceHandlerIF.h | 20 +- devicehandlers/DeviceHandlerMessage.cpp | 19 +- devicehandlers/DeviceHandlerMessage.h | 78 +++----- devicehandlers/DeviceTmReportingWrapper.cpp | 1 - devicehandlers/DeviceTmReportingWrapper.h | 6 +- devicehandlers/HealthDevice.cpp | 6 +- devicehandlers/HealthDevice.h | 6 +- 19 files changed, 403 insertions(+), 303 deletions(-) diff --git a/devicehandlers/AcceptsDeviceResponsesIF.h b/devicehandlers/AcceptsDeviceResponsesIF.h index 8dc69de4..8e13ba0c 100644 --- a/devicehandlers/AcceptsDeviceResponsesIF.h +++ b/devicehandlers/AcceptsDeviceResponsesIF.h @@ -1,23 +1,19 @@ -/** - * @file AcceptsDeviceResponsesIF.h - * @brief This file defines the AcceptsDeviceResponsesIF class. - * @date 15.05.2013 - * @author baetz - */ - -#ifndef ACCEPTSDEVICERESPONSESIF_H_ -#define ACCEPTSDEVICERESPONSESIF_H_ +#ifndef FSFW_DEVICEHANDLERS_ACCEPTSDEVICERESPONSESIF_H_ +#define FSFW_DEVICEHANDLERS_ACCEPTSDEVICERESPONSESIF_H_ #include "../ipc/MessageQueueSenderIF.h" +/** + * This interface is used by the device handler to send a device response + * to the queue ID, which is returned in the implemented abstract method. + */ class AcceptsDeviceResponsesIF { public: /** * Default empty virtual destructor. */ - virtual ~AcceptsDeviceResponsesIF() { -} -virtual MessageQueueId_t getDeviceQueue() = 0; + virtual ~AcceptsDeviceResponsesIF() {} + virtual MessageQueueId_t getDeviceQueue() = 0; }; -#endif /* ACCEPTSDEVICERESPONSESIF_H_ */ +#endif /* FSFW_DEVICEHANDLERS_ACCEPTSDEVICERESPONSESIF_H_ */ diff --git a/devicehandlers/AssemblyBase.cpp b/devicehandlers/AssemblyBase.cpp index 8b3f7f4d..46b2211a 100644 --- a/devicehandlers/AssemblyBase.cpp +++ b/devicehandlers/AssemblyBase.cpp @@ -2,10 +2,10 @@ AssemblyBase::AssemblyBase(object_id_t objectId, object_id_t parentId, uint16_t commandQueueDepth) : - SubsystemBase(objectId, parentId, MODE_OFF, commandQueueDepth), internalState( - STATE_NONE), recoveryState(RECOVERY_IDLE), recoveringDevice( - childrenMap.end()), targetMode(MODE_OFF), targetSubmode( - SUBMODE_NONE) { + SubsystemBase(objectId, parentId, MODE_OFF, commandQueueDepth), + internalState(STATE_NONE), recoveryState(RECOVERY_IDLE), + recoveringDevice(childrenMap.end()), targetMode(MODE_OFF), + targetSubmode(SUBMODE_NONE) { recoveryOffTimer.setTimeout(POWER_OFF_TIME_MS); } @@ -165,9 +165,8 @@ ReturnValue_t AssemblyBase::checkChildrenState() { } ReturnValue_t AssemblyBase::checkChildrenStateOff() { - for (std::map::iterator iter = childrenMap.begin(); - iter != childrenMap.end(); iter++) { - if (checkChildOff(iter->first) != RETURN_OK) { + for (const auto& childIter: childrenMap) { + if (checkChildOff(childIter.first) != RETURN_OK) { return NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE; } } diff --git a/devicehandlers/AssemblyBase.h b/devicehandlers/AssemblyBase.h index bd2e8fad..353d5f89 100644 --- a/devicehandlers/AssemblyBase.h +++ b/devicehandlers/AssemblyBase.h @@ -1,10 +1,30 @@ -#ifndef ASSEMBLYBASE_H_ -#define ASSEMBLYBASE_H_ +#ifndef FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ +#define FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ -#include "../container/FixedArrayList.h" #include "DeviceHandlerBase.h" +#include "../container/FixedArrayList.h" #include "../subsystem/SubsystemBase.h" +/** + * @brief Base class to implement reconfiguration and failure handling for + * redundant devices by monitoring their modes health states. + * @details + * Documentation: Dissertation Baetz p.156, 157. + * + * This class reduces the complexity of controller components which would + * otherwise be needed for the handling of redundant devices. + * + * The template class monitors mode and health state of its children + * and checks availability of devices on every detected change. + * AssemblyBase does not implement any redundancy logic by itself, but provides + * adaptation points for implementations to do so. Since most monitoring + * activities rely on mode and health state only and are therefore + * generic, it is sufficient for subclasses to provide: + * + * 1. check logic when active-> checkChildrenStateOn + * 2. transition logic to change the mode -> commandChildren + * + */ class AssemblyBase: public SubsystemBase { public: static const uint8_t INTERFACE_ID = CLASS_ID::ASSEMBLY_BASE; @@ -16,10 +36,41 @@ public: static const ReturnValue_t NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE = MAKE_RETURN_CODE(0xa1); - AssemblyBase(object_id_t objectId, object_id_t parentId, uint16_t commandQueueDepth = 8); + AssemblyBase(object_id_t objectId, object_id_t parentId, + uint16_t commandQueueDepth = 8); virtual ~AssemblyBase(); protected: + + // SHOULDDO: Change that OVERWRITE_HEALTH may be returned + // (or return internalState directly?) + /** + * Command children to reach [mode,submode] combination + * Can be done by setting #commandsOutstanding correctly, + * or using executeTable() + * @param mode + * @param submode + * @return + * - @c RETURN_OK if ok + * - @c NEED_SECOND_STEP if children need to be commanded again + */ + virtual ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) = 0; + + /** + * Check whether desired assembly mode was achieved by checking the modes + * or/and health states of child device handlers. + * The assembly template class will also call this function if a health + * or mode change of a child device handler was detected. + * @param wantedMode + * @param wantedSubmode + * @return + */ + virtual ReturnValue_t checkChildrenStateOn(Mode_t wantedMode, + Submode_t wantedSubmode) = 0; + + virtual ReturnValue_t isModeCombinationValid(Mode_t mode, + Submode_t submode) = 0; + enum InternalState { STATE_NONE, STATE_OVERWRITE_HEALTH, @@ -36,6 +87,7 @@ protected: RECOVERY_WAIT } recoveryState; //!< Indicates if one of the children requested a recovery. ChildrenMap::iterator recoveringDevice; + /** * the mode the current transition is trying to achieve. * Can be different from the modehelper.commandedMode! @@ -61,8 +113,8 @@ protected: bool handleChildrenChanged(); /** - * This method is called if the children changed its mode in a way that the current - * mode can't be kept. + * This method is called if the children changed its mode in a way that + * the current mode can't be kept. * Default behavior is to go to MODE_OFF. * @param result The failure code which was returned by checkChildrenState. */ @@ -75,9 +127,6 @@ protected: ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode); - virtual ReturnValue_t isModeCombinationValid(Mode_t mode, - Submode_t submode) = 0; - virtual void startTransition(Mode_t mode, Submode_t submode); virtual void doStartTransition(Mode_t mode, Submode_t submode); @@ -90,24 +139,6 @@ protected: void sendHealthCommand(MessageQueueId_t sendTo, HealthState health); - //SHOULDDO: Change that OVERWRITE_HEALTH may be returned (or return internalState directly?) - /** - * command children to reach mode,submode - * - * set #commandsOutstanding correctly, or use executeTable() - * - * @param mode - * @param submode - * @return - * - @c RETURN_OK if ok - * - @c NEED_SECOND_STEP if children need to be commanded again - */ - virtual ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) = 0; - - //SHOULDDO: Remove wantedMode, wantedSubmode, as targetMode/submode is available? - virtual ReturnValue_t checkChildrenStateOn(Mode_t wantedMode, - Submode_t wantedSubmode) = 0; - virtual ReturnValue_t checkChildrenStateOff(); ReturnValue_t checkChildrenState(); @@ -125,8 +156,9 @@ protected: * Also sets state to STATE_OVERWRITE_HEATH. * @param objectId Must be a registered child. */ - void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth); + void overwriteDeviceHealth(object_id_t objectId, + HasHealthIF::HealthState oldHealth); }; -#endif /* ASSEMBLYBASE_H_ */ +#endif /* FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ */ diff --git a/devicehandlers/ChildHandlerBase.cpp b/devicehandlers/ChildHandlerBase.cpp index e800cd56..d4ef67ad 100644 --- a/devicehandlers/ChildHandlerBase.cpp +++ b/devicehandlers/ChildHandlerBase.cpp @@ -1,16 +1,18 @@ +#include "ChildHandlerBase.h" #include "../subsystem/SubsystemBase.h" -#include "../devicehandlers/ChildHandlerBase.h" #include "../subsystem/SubsystemBase.h" ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF * cookie, - uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, - object_id_t parent, FailureIsolationBase* customFdir, - size_t cmdQueueSize) : + object_id_t hkDestination, uint32_t thermalStatePoolId, + uint32_t thermalRequestPoolId, + object_id_t parent, + FailureIsolationBase* customFdir, size_t cmdQueueSize) : DeviceHandlerBase(setObjectId, deviceCommunication, cookie, (customFdir == nullptr? &childHandlerFdir : customFdir), cmdQueueSize), parentId(parent), childHandlerFdir(setObjectId) { + this->setHkDestination(hkDestination); this->setThermalStateRequestPoolIds(thermalStatePoolId, thermalRequestPoolId); diff --git a/devicehandlers/ChildHandlerBase.h b/devicehandlers/ChildHandlerBase.h index f6bf318a..eed4c95e 100644 --- a/devicehandlers/ChildHandlerBase.h +++ b/devicehandlers/ChildHandlerBase.h @@ -1,17 +1,18 @@ -#ifndef FSFW_DEVICES_CHILDHANDLERBASE_H_ -#define FSFW_DEVICES_CHILDHANDLERBASE_H_ +#ifndef FSFW_DEVICEHANDLER_CHILDHANDLERBASE_H_ +#define FSFW_DEVICEHANDLER_CHILDHANDLERBASE_H_ -#include "ChildHandlerFDIR.h" #include "DeviceHandlerBase.h" +#include "ChildHandlerFDIR.h" class ChildHandlerBase: public DeviceHandlerBase { public: ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, - CookieIF * cookie, uint32_t thermalStatePoolId, - uint32_t thermalRequestPoolId, + CookieIF * cookie, object_id_t hkDestination, + uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, object_id_t parent = objects::NO_OBJECT, FailureIsolationBase* customFdir = nullptr, size_t cmdQueueSize = 20); + virtual ~ChildHandlerBase(); virtual ReturnValue_t initialize(); @@ -22,5 +23,4 @@ protected: }; -#endif /* FSFW_DEVICES_CHILDHANDLERBASE_H_ */ - +#endif /* FSFW_DEVICEHANDLER_CHILDHANDLERBASE_H_ */ diff --git a/devicehandlers/ChildHandlerFDIR.cpp b/devicehandlers/ChildHandlerFDIR.cpp index 14043a77..cb4c75ea 100644 --- a/devicehandlers/ChildHandlerFDIR.cpp +++ b/devicehandlers/ChildHandlerFDIR.cpp @@ -1,6 +1,7 @@ #include "ChildHandlerFDIR.h" -ChildHandlerFDIR::ChildHandlerFDIR(object_id_t owner, object_id_t faultTreeParent, uint32_t recoveryCount) : +ChildHandlerFDIR::ChildHandlerFDIR(object_id_t owner, + object_id_t faultTreeParent, uint32_t recoveryCount) : DeviceHandlerFailureIsolation(owner, faultTreeParent) { recoveryCounter.setFailureThreshold(recoveryCount); } diff --git a/devicehandlers/ChildHandlerFDIR.h b/devicehandlers/ChildHandlerFDIR.h index ce844518..13d1345c 100644 --- a/devicehandlers/ChildHandlerFDIR.h +++ b/devicehandlers/ChildHandlerFDIR.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_DEVICEHANDLERS_CHILDHANDLERFDIR_H_ -#define FRAMEWORK_DEVICEHANDLERS_CHILDHANDLERFDIR_H_ +#ifndef FSFW_DEVICEHANDLERS_CHILDHANDLERFDIR_H_ +#define FSFW_DEVICEHANDLERS_CHILDHANDLERFDIR_H_ #include "DeviceHandlerFailureIsolation.h" diff --git a/devicehandlers/CookieIF.h b/devicehandlers/CookieIF.h index 496cf0d2..5911bfdb 100644 --- a/devicehandlers/CookieIF.h +++ b/devicehandlers/CookieIF.h @@ -1,11 +1,12 @@ -#ifndef COOKIE_H_ -#define COOKIE_H_ +#ifndef FSFW_DEVICEHANDLER_COOKIE_H_ +#define FSFW_DEVICEHANDLER_COOKIE_H_ + #include /** * @brief Physical address type */ -typedef std::uint32_t address_t; +using address_t = uint32_t; /** * @brief This datatype is used to identify different connection over a @@ -16,7 +17,6 @@ typedef std::uint32_t address_t; * calling @code{.cpp} CookieIF* childCookie = new ChildCookie(...) * @endcode . * - * [not implemented yet] * This cookie is then passed to the child device handlers, which stores the * pointer and passes it to the communication interface functions. * @@ -31,4 +31,4 @@ public: virtual ~CookieIF() {}; }; -#endif /* COOKIE_H_ */ +#endif /* FSFW_DEVICEHANDLER_COOKIE_H_ */ diff --git a/devicehandlers/DeviceCommunicationIF.h b/devicehandlers/DeviceCommunicationIF.h index 11960d8e..e0b473d3 100644 --- a/devicehandlers/DeviceCommunicationIF.h +++ b/devicehandlers/DeviceCommunicationIF.h @@ -1,9 +1,10 @@ -#ifndef DEVICECOMMUNICATIONIF_H_ -#define DEVICECOMMUNICATIONIF_H_ +#ifndef FSFW_DEVICES_DEVICECOMMUNICATIONIF_H_ +#define FSFW_DEVICES_DEVICECOMMUNICATIONIF_H_ #include "CookieIF.h" +#include "DeviceHandlerIF.h" + #include "../returnvalues/HasReturnvaluesIF.h" -#include /** * @defgroup interfaces Interfaces * @brief Interfaces for flight software objects @@ -19,8 +20,8 @@ * the device handler to allow reuse of these components. * @details * Documentation: Dissertation Baetz p.138. - * It works with the assumption that received data - * is polled by a component. There are four generic steps of device communication: + * 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 @@ -38,24 +39,20 @@ class DeviceCommunicationIF: public HasReturnvaluesIF { public: static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_COMMUNICATION_IF; - //! Standard Error Codes + //! This is returned in readReceivedMessage() if no reply was reived. + static const ReturnValue_t NO_REPLY_RECEIVED = MAKE_RETURN_CODE(0x01); + //! General protocol error. Define more concrete errors in child handler - static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0x01); + static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0x02); //! If cookie is a null pointer - static const ReturnValue_t NULLPOINTER = MAKE_RETURN_CODE(0x02); - static const ReturnValue_t INVALID_COOKIE_TYPE = MAKE_RETURN_CODE(0x03); + static const ReturnValue_t NULLPOINTER = MAKE_RETURN_CODE(0x03); + static const ReturnValue_t INVALID_COOKIE_TYPE = MAKE_RETURN_CODE(0x04); // is this needed if there is no open/close call? static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x05); - static const ReturnValue_t INVALID_ADDRESS = MAKE_RETURN_CODE(0x06); - static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x07); - static const ReturnValue_t CANT_CHANGE_REPLY_LEN = MAKE_RETURN_CODE(0x08); - - //! Can be used in readReceivedMessage() if no reply was received. - static const ReturnValue_t NO_REPLY_RECEIVED = MAKE_RETURN_CODE(0xA1); + static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x06); virtual ~DeviceCommunicationIF() {} - /** * @brief Device specific initialization, using the cookie. * @details @@ -76,13 +73,13 @@ public: * by implementing and calling related drivers or wrapper functions. * @param cookie * @param data - * @param len + * @param len If this is 0, nothing shall be sent. * @return * - @c RETURN_OK for successfull send * - Everything else triggers failure event with returnvalue as parameter 1 */ - virtual ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t * sendData, - size_t sendLen) = 0; + virtual ReturnValue_t sendMessage(CookieIF *cookie, + const uint8_t * sendData, size_t sendLen) = 0; /** * Called by DHB in the GET_WRITE doGetWrite(). @@ -108,7 +105,7 @@ public: * returnvalue as parameter 1 */ virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie, - size_t requestLen) = 0; + size_t requestLen) = 0; /** * Called by DHB in the GET_WRITE doGetRead(). @@ -124,8 +121,8 @@ public: * - Everything else triggers failure event with * returnvalue as parameter 1 */ - virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, - size_t *size) = 0; + virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, + uint8_t **buffer, size_t *size) = 0; }; -#endif /* DEVICECOMMUNICATIONIF_H_ */ +#endif /* FSFW_DEVICES_DEVICECOMMUNICATIONIF_H_ */ diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 017ea8d2..227d5b6d 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -2,15 +2,17 @@ #include "AcceptsDeviceResponsesIF.h" #include "DeviceTmReportingWrapper.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../datapoolglob/GlobalDataSet.h" +#include "../datapoolglob/GlobalPoolVariable.h" #include "../objectmanager/ObjectManager.h" #include "../storagemanager/StorageManagerIF.h" #include "../thermal/ThermalComponentIF.h" -#include "../datapool/DataSet.h" -#include "../datapool/PoolVariable.h" #include "../globalfunctions/CRC.h" -#include "../subsystem/SubsystemBase.h" +#include "../housekeeping/HousekeepingMessage.h" +#include "../ipc/MessageQueueMessage.h" #include "../ipc/QueueFactory.h" -#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../subsystem/SubsystemBase.h" #include @@ -25,10 +27,11 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, wiretappingMode(OFF), storedRawData(StorageManagerIF::INVALID_ADDRESS), deviceCommunicationId(deviceCommunication), comCookie(comCookie), healthHelper(this,setObjectId), modeHelper(this), parameterHelper(this), - actionHelper(this, nullptr), childTransitionFailure(RETURN_OK), - fdirInstance(fdirInstance), hkSwitcher(this), - defaultFDIRUsed(fdirInstance == nullptr), switchOffWasReported(false), - childTransitionDelay(5000), transitionSourceMode(_MODE_POWER_DOWN), + actionHelper(this, nullptr), hkManager(this, nullptr), + childTransitionFailure(RETURN_OK), fdirInstance(fdirInstance), + hkSwitcher(this), defaultFDIRUsed(fdirInstance == nullptr), + switchOffWasReported(false), childTransitionDelay(5000), + transitionSourceMode(_MODE_POWER_DOWN), transitionSourceSubMode(SUBMODE_NONE) { commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE); @@ -48,6 +51,10 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, } } +void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) { + this->hkDestination = hkDestination; +} + void DeviceHandlerBase::setThermalStateRequestPoolIds( uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId) { this->deviceThermalRequestPoolId = thermalStatePoolId; @@ -74,6 +81,7 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { decrementDeviceReplyMap(); fdirInstance->checkForFailures(); hkSwitcher.performOperation(); + hkManager.performHkOperation(); performOperationHook(); } if (mode == MODE_OFF) { @@ -120,7 +128,9 @@ ReturnValue_t DeviceHandlerBase::initialize() { result = communicationInterface->initializeInterface(comCookie); if (result != RETURN_OK) { - return result; + sif::error << "DeviceHandlerBase::initialize: Initializing " + "communication interface failed!" << std::endl; + return result; } IPCStore = objectManager->get(objects::IPC_STORE); @@ -183,11 +193,16 @@ ReturnValue_t DeviceHandlerBase::initialize() { return result; } + result = hkManager.initialize(commandQueue); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + fillCommandAndReplyMap(); //Set temperature target state to NON_OP. - DataSet mySet; - db_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, + GlobDataSet mySet; + gp_uint8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_WRITE); mySet.read(); thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; @@ -245,10 +260,10 @@ void DeviceHandlerBase::readCommandQueue() { return; } -// result = hkManager.handleHousekeepingMessage(&command); -// if (result == RETURN_OK) { -// return; -// } + result = hkManager.handleHousekeepingMessage(&command); + if (result == RETURN_OK) { + return; + } result = handleDeviceHandlerMessage(&command); if (result == RETURN_OK) { @@ -376,24 +391,28 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode, ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap( DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, - size_t replyLen, bool periodic, bool hasDifferentReplyId, - DeviceCommandId_t replyId) { + LocalPoolDataSetBase* replyDataSet, size_t replyLen, bool periodic, + bool hasDifferentReplyId, DeviceCommandId_t replyId) { //No need to check, as we may try to insert multiple times. insertInCommandMap(deviceCommand); if (hasDifferentReplyId) { - return insertInReplyMap(replyId, maxDelayCycles, replyLen, periodic); + return insertInReplyMap(replyId, maxDelayCycles, + replyDataSet, replyLen, periodic); } else { - return insertInReplyMap(deviceCommand, maxDelayCycles, replyLen, periodic); + return insertInReplyMap(deviceCommand, maxDelayCycles, + replyDataSet, replyLen, periodic); } } ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId, - uint16_t maxDelayCycles, size_t replyLen, bool periodic) { + uint16_t maxDelayCycles, LocalPoolDataSetBase* dataSet, + size_t replyLen, bool periodic) { DeviceReplyInfo info; info.maxDelayCycles = maxDelayCycles; info.periodic = periodic; info.delayCycles = 0; info.replyLen = replyLen; + info.dataSet = dataSet; info.command = deviceCommandMap.end(); auto resultPair = deviceReplyMap.emplace(replyId, info); if (resultPair.second) { @@ -419,13 +438,12 @@ ReturnValue_t DeviceHandlerBase::insertInCommandMap( ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply, uint16_t delayCycles, uint16_t maxDelayCycles, bool periodic) { - std::map::iterator iter = - deviceReplyMap.find(deviceReply); - if (iter == deviceReplyMap.end()) { + auto replyIter = deviceReplyMap.find(deviceReply); + if (replyIter == deviceReplyMap.end()) { triggerEvent(INVALID_DEVICE_COMMAND, deviceReply); return RETURN_FAILED; } else { - DeviceReplyInfo *info = &(iter->second); + DeviceReplyInfo *info = &(replyIter->second); if (maxDelayCycles != 0) { info->maxDelayCycles = maxDelayCycles; } @@ -435,6 +453,17 @@ ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceRep } } + +ReturnValue_t DeviceHandlerBase::setReplyDataset(DeviceCommandId_t replyId, + LocalPoolDataSetBase *dataSet) { + auto replyIter = deviceReplyMap.find(replyId); + if(replyIter == deviceReplyMap.end()) { + return HasReturnvaluesIF::RETURN_FAILED; + } + replyIter->second.dataSet = dataSet; + return HasReturnvaluesIF::RETURN_OK; +} + void DeviceHandlerBase::callChildStatemachine() { if (mode == _MODE_START_UP) { doStartUp(); @@ -469,8 +498,8 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) { Clock::getUptime(&timeoutStart); if (mode == MODE_OFF) { - DataSet mySet; - db_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, + GlobDataSet mySet; + gp_uint8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { @@ -649,7 +678,7 @@ void DeviceHandlerBase::doGetRead() { void DeviceHandlerBase::parseReply(const uint8_t* receivedData, size_t receivedDataLen) { ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; - DeviceCommandId_t foundId = 0xFFFFFFFF; + DeviceCommandId_t foundId = 0xffffffff; size_t foundLen = 0; // The loop may not execute more often than the number of received bytes // (worst case). This approach avoids infinite loops due to buggy @@ -661,18 +690,26 @@ void DeviceHandlerBase::parseReply(const uint8_t* receivedData, switch (result) { case RETURN_OK: handleReply(receivedData, foundId, foundLen); + if(foundLen == 0) { + sif::warning << "DeviceHandlerBase::parseReply: foundLen is 0!" + " Packet parsing will be stuck." << std::endl; + } break; case APERIODIC_REPLY: { result = interpretDeviceReply(foundId, receivedData); if (result != RETURN_OK) { - replyRawReplyIfnotWiretapped(receivedData, foundLen); - triggerEvent(DEVICE_INTERPRETING_REPLY_FAILED, result, - foundId); + replyRawReplyIfnotWiretapped(receivedData, foundLen); + triggerEvent(DEVICE_INTERPRETING_REPLY_FAILED, result, + foundId); + } + if(foundLen == 0) { + sif::warning << "DeviceHandlerBase::parseReply: foundLen is 0!" + " Packet parsing will be stuck." << std::endl; } - } - break; - case IGNORE_REPLY_DATA: break; + } + case IGNORE_REPLY_DATA: + continue; case IGNORE_FULL_PACKET: return; default: @@ -704,16 +741,19 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, DeviceReplyInfo *info = &(iter->second); if (info->delayCycles != 0) { + result = interpretDeviceReply(foundId, receivedData); - if (info->periodic != false) { + if(result == IGNORE_REPLY_DATA) { + return; + } + + if (info->periodic) { info->delayCycles = info->maxDelayCycles; } else { info->delayCycles = 0; } - result = interpretDeviceReply(foundId, receivedData); - if (result != RETURN_OK) { // Report failed interpretation to FDIR. replyRawReplyIfnotWiretapped(receivedData, foundLen); @@ -926,10 +966,10 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, if ((commandedMode == MODE_ON) && (mode == MODE_OFF) && (deviceThermalStatePoolId != PoolVariableIF::NO_PARAMETER)) { - DataSet mySet; - db_int8_t thermalState(deviceThermalStatePoolId, &mySet, + GlobDataSet mySet; + gp_uint8_t thermalState(deviceThermalStatePoolId, &mySet, PoolVariableIF::VAR_READ); - db_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, + gp_uint8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_READ); mySet.read(); if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { @@ -956,8 +996,8 @@ void DeviceHandlerBase::startTransition(Mode_t commandedMode, childTransitionDelay = getTransitionDelayMs(_MODE_START_UP, MODE_ON); triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode); - DataSet mySet; - db_int8_t thermalRequest(deviceThermalRequestPoolId, + GlobDataSet mySet; + gp_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { @@ -1089,19 +1129,6 @@ ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage( } replyReturnvalueToCommand(RETURN_OK); return RETURN_OK; -// case DeviceHandlerMessage::CMD_SWITCH_IOBOARD: -// if (mode != MODE_OFF) { -// replyReturnvalueToCommand(WRONG_MODE_FOR_COMMAND); -// } else { -// result = switchCookieChannel( -// DeviceHandlerMessage::getIoBoardObjectId(message)); -// if (result == RETURN_OK) { -// replyReturnvalueToCommand(RETURN_OK); -// } else { -// replyReturnvalueToCommand(CANT_SWITCH_IO_ADDRESS); -// } -// } -// return RETURN_OK; case DeviceHandlerMessage::CMD_RAW: if ((mode != MODE_RAW)) { DeviceHandlerMessage::clear(message); @@ -1185,7 +1212,7 @@ void DeviceHandlerBase::handleDeviceTM(SerializeIF* data, } //Try to cast to GlobDataSet and commit data. if (!neverInDataPool) { - DataSet* dataSet = dynamic_cast(data); + GlobDataSet* dataSet = dynamic_cast(data); if (dataSet != NULL) { dataSet->commit(PoolVariableIF::VALID); } @@ -1248,10 +1275,14 @@ void DeviceHandlerBase::buildInternalCommand(void) { if (iter == deviceCommandMap.end()) { result = COMMAND_NOT_SUPPORTED; } else if (iter->second.isExecuting) { + //so we can track misconfigurations sif::debug << std::hex << getObjectId() << ": 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 + << deviceCommandId << " isExecuting" << std::dec + << std::endl; + // 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 + return; } else { iter->second.sendReplyTo = NO_COMMANDER; iter->second.isExecuting = true; @@ -1340,12 +1371,50 @@ void DeviceHandlerBase::debugInterface(uint8_t positionTracker, void DeviceHandlerBase::performOperationHook() { } +ReturnValue_t DeviceHandlerBase::initializeLocalDataPool( + LocalDataPool &localDataPoolMap, + LocalDataPoolManager& poolManager) { + return RETURN_OK; +} + +LocalDataPoolManager* DeviceHandlerBase::getHkManagerHandle() { + return &hkManager; +} + + ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() { // In this function, the task handle should be valid if the task // was implemented correctly. We still check to be 1000 % sure :-) if(executingTask != nullptr) { pstIntervalMs = executingTask->getPeriodMs(); } + this->hkManager.initializeAfterTaskCreation(); + + if(setStartupImmediately) { + startTransition(MODE_ON, SUBMODE_NONE); + } return HasReturnvaluesIF::RETURN_OK; } +LocalPoolDataSetBase* DeviceHandlerBase::getDataSetHandle(sid_t sid) { + auto iter = deviceReplyMap.find(sid.ownerSetId); + if(iter != deviceReplyMap.end()) { + return iter->second.dataSet; + } + else { + return nullptr; + } +} + +object_id_t DeviceHandlerBase::getObjectId() const { + return SystemObject::getObjectId(); +} + +void DeviceHandlerBase::setStartUpImmediately() { + this->setStartupImmediately = true; +} + +dur_millis_t DeviceHandlerBase::getPeriodicOperationFrequency() const { + return pstIntervalMs; +} + diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 5666f35e..eda318cb 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -1,12 +1,11 @@ -#ifndef FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ -#define FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ +#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ +#define FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ #include "DeviceHandlerIF.h" #include "DeviceCommunicationIF.h" #include "DeviceHandlerFailureIsolation.h" #include "../objectmanager/SystemObject.h" -#include "../tasks/PeriodicTaskIF.h" #include "../tasks/ExecutableObjectIF.h" #include "../returnvalues/HasReturnvaluesIF.h" #include "../action/HasActionsIF.h" @@ -14,10 +13,13 @@ #include "../modes/HasModesIF.h" #include "../power/PowerSwitchIF.h" #include "../ipc/MessageQueueIF.h" +#include "../tasks/PeriodicTaskIF.h" #include "../action/ActionHelper.h" #include "../health/HealthHelper.h" #include "../parameters/ParameterHelper.h" #include "../datapool/HkSwitchHelper.h" +#include "../datapoollocal/HasLocalDataPoolIF.h" +#include "../datapoollocal/LocalDataPoolManager.h" #include @@ -38,17 +40,16 @@ class StorageManagerIF; * Documentation: Dissertation Baetz p.138,139, p.141-149 * * It features handling of @link DeviceHandlerIF::Mode_t Modes @endlink, - * communication with physical devices, using the @link DeviceCommunicationIF @endlink, - * and communication with commanding objects. - * It inherits SystemObject and thus can be created by the ObjectManagerIF. + * communication with physical devices, using the + * @link DeviceCommunicationIF @endlink, and communication with commanding + * objects. 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 (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. - * NOTE: RMAP is a standard which is used for FLP. + * This class uses the opcode of ExecutableObjectIF to perform a + * step-wise execution. For each step a different action is selected and + * executed. Currently, the device handler base performs a 4-step + * execution related to 4 communication steps (based on RMAP). + * NOTE: RMAP is a standard which is used for Flying Laptop. * 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. @@ -69,9 +70,6 @@ class StorageManagerIF; * * Other important virtual methods with a default implementation * are the getTransitionDelayMs() function and the getSwitches() function. - * Please ensure that getSwitches() returns DeviceHandlerIF::NO_SWITCHES if - * power switches are not implemented yet. Otherwise, the device handler will - * not transition to MODE_ON, even if setMode(MODE_ON) is called. * If a transition to MODE_ON is desired without commanding, override the * intialize() function and call setMode(_MODE_START_UP) before calling * DeviceHandlerBase::initialize(). @@ -85,20 +83,18 @@ class DeviceHandlerBase: public DeviceHandlerIF, public HasModesIF, public HasHealthIF, public HasActionsIF, - public ReceivesParameterMessagesIF { + public ReceivesParameterMessagesIF, + public HasLocalDataPoolIF { friend void (Factory::setStaticFrameworkObjectIds)(); public: /** * The constructor passes the objectId to the SystemObject(). * * @param setObjectId the ObjectId to pass to the SystemObject() Constructor - * @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() * @param deviceCommuncation Communcation Interface object which is used * to implement communication functions - * @param thermalStatePoolId - * @param thermalRequestPoolId + * @param comCookie This object will be passed to the communication inter- + * face and can contain user-defined information about the communication. * @param fdirInstance * @param cmdQueueSize */ @@ -106,8 +102,21 @@ public: CookieIF * comCookie, FailureIsolationBase* fdirInstance = nullptr, size_t cmdQueueSize = 20); + void setHkDestination(object_id_t hkDestination); void setThermalStateRequestPoolIds(uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId); + /** + * @brief Helper function to ease device handler development. + * This will instruct the transition to MODE_ON immediately + * (leading to doStartUp() being called for the transition to the ON mode), + * so external mode commanding is not necessary anymore. + * + * This has to be called before the task is started! + * (e.g. in the task factory). This is only a helper function for + * development. Regular mode commanding should be performed by commanding + * the AssemblyBase or Subsystem objects resposible for the device handler. + */ + void setStartUpImmediately(); /** * @brief This function is the device handler base core component and is @@ -153,6 +162,14 @@ public: * @return */ virtual ReturnValue_t initialize(); + + /** + * @brief Intialization steps performed after all tasks have been created. + * This function will be called by the executing task. + * @return + */ + virtual ReturnValue_t initializeAfterTaskCreation() override; + /** Destructor. */ virtual ~DeviceHandlerBase(); @@ -320,6 +337,8 @@ protected: * @param packet * @return * - @c RETURN_OK when the reply was interpreted. + * - @c IGNORE_REPLY_DATA Ignore the reply and don't reset reply cycle + * counter. * - @c RETURN_FAILED when the reply could not be interpreted, * e.g. logical errors or range violations occurred */ @@ -347,22 +366,10 @@ protected: * set to the maximum expected number of PST cycles between two replies * (also a tolerance should be added, as an FDIR message will be * generated if it is missed). - * - * (Robin) This part confuses me. "must do as soon as" implies that - * the developer must do something somewhere else in the code. Is - * that really the case? If I understood correctly, DHB performs - * almost everything (e.g. in erirm function) as long as the commands - * are inserted correctly. - * - * As soon as the replies are enabled, DeviceCommandInfo.periodic must - * be set to true, DeviceCommandInfo.delayCycles to - * DeviceCommandInfo.maxDelayCycles. * From then on, the base class handles the reception. * Then, scanForReply returns the id of the reply or the placeholder id * and the base class will take care of checking that all replies are * received and the interval is correct. - * When the replies are disabled, DeviceCommandInfo.periodic must be set - * to 0, DeviceCommandInfo.delayCycles to 0; * * - Aperiodic, unrequested replies. These are replies that are sent * by the device without any preceding command and not in a defined @@ -376,13 +383,17 @@ protected: * @param deviceCommand Identifier of the command to add. * @param maxDelayCycles The maximum number of delay cycles the command * waits until it times out. + * @param replyLen Will be supplied to the requestReceiveMessage call of + * the communication interface. * @param periodic Indicates if the command is periodic (i.e. it is sent * by the device repeatedly without request) or not. Default is aperiodic (0) * @return - @c RETURN_OK when the command was successfully inserted, * - @c RETURN_FAILED else. */ ReturnValue_t insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, - uint16_t maxDelayCycles, size_t replyLen = 0, bool periodic = false, + uint16_t maxDelayCycles, + LocalPoolDataSetBase* replyDataSet = nullptr, + size_t replyLen = 0, bool periodic = false, bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0); /** @@ -396,7 +407,8 @@ protected: * - @c RETURN_FAILED else. */ ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, - uint16_t maxDelayCycles, size_t replyLen = 0, bool periodic = false); + uint16_t maxDelayCycles, LocalPoolDataSetBase* dataSet = nullptr, + size_t replyLen = 0, bool periodic = false); /** * @brief A simple command to add a command to the commandList. @@ -424,6 +436,9 @@ protected: uint16_t delayCycles, uint16_t maxDelayCycles, bool periodic = false); + ReturnValue_t setReplyDataset(DeviceCommandId_t replyId, + LocalPoolDataSetBase* dataset); + /** * @brief Can be implemented by child handler to * perform debugging @@ -477,18 +492,22 @@ protected: * @param localDataPoolMap * @return */ - //virtual ReturnValue_t initializePoolEntries( - // LocalDataPool& localDataPoolMap) override; + virtual ReturnValue_t initializeLocalDataPool(LocalDataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override; /** Get the HK manager object handle */ - //virtual LocalDataPoolManager* getHkManagerHandle() override; + virtual LocalDataPoolManager* getHkManagerHandle() override; /** * @brief Hook function for child handlers which is called once per * performOperation(). Default implementation is empty. */ virtual void performOperationHook(); + public: + /** Explicit interface implementation of getObjectId */ + virtual object_id_t getObjectId() const override; + /** * @param parentQueueId */ @@ -608,7 +627,7 @@ protected: /** Action helper for HasActionsIF */ ActionHelper actionHelper; /** Housekeeping Manager */ - //LocalDataPoolManager hkManager; + LocalDataPoolManager hkManager; /** * @brief Information about commands @@ -647,7 +666,7 @@ protected: //! The dataset used to access housekeeping data related to the //! respective device reply. Will point to a dataset held by //! the child handler (if one is specified) - // DataSetIF* dataSet = nullptr; + LocalPoolDataSetBase* dataSet; //! The command that expects this reply. DeviceCommandMap::iterator command; }; @@ -689,14 +708,18 @@ protected: uint32_t deviceThermalRequestPoolId = PoolVariableIF::NO_PARAMETER; /** - * Optional Error code - * Can be set in doStartUp(), doShutDown() and doTransition() to signal cause for Transition failure. + * Optional Error code. Can be set in doStartUp(), doShutDown() and + * doTransition() to signal cause for Transition failure. */ ReturnValue_t childTransitionFailure; - uint32_t ignoreMissedRepliesCount = 0; //!< Counts if communication channel lost a reply, so some missed replys can be ignored. + /** Counts if communication channel lost a reply, so some missed + * replys can be ignored. */ + uint32_t ignoreMissedRepliesCount = 0; - FailureIsolationBase* fdirInstance; //!< Pointer to the used FDIR instance. If not provided by child, default class is instantiated. + /** Pointer to the used FDIR instance. If not provided by child, + * default class is instantiated. */ + FailureIsolationBase* fdirInstance; HkSwitchHelper hkSwitcher; @@ -944,14 +967,17 @@ protected: virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode); - virtual void startTransition(Mode_t mode, Submode_t submode); - virtual void setToExternalControl(); - virtual void announceMode(bool recursive); + + /* HasModesIF overrides */ + virtual void startTransition(Mode_t mode, Submode_t submode) override; + virtual void setToExternalControl() override; + virtual void announceMode(bool recursive) override; virtual ReturnValue_t letChildHandleMessage(CommandMessage *message); /** - * Overwrites SystemObject::triggerEvent in order to inform FDIR"Helper" faster about executed events. + * Overwrites SystemObject::triggerEvent in order to inform FDIR"Helper" + * faster about executed events. * This is a bit sneaky, but improves responsiveness of the device FDIR. * @param event The event to be thrown * @param parameter1 Optional parameter 1 @@ -1034,12 +1060,17 @@ private: /** the object used to set power switches */ PowerSwitchIF *powerSwitcher = nullptr; + /** HK destination can also be set individually */ + object_id_t hkDestination = objects::NO_OBJECT; + /** * @brief Used for timing out mode transitions. * Set when setMode() is called. */ uint32_t timeoutStart = 0; + bool setStartupImmediately = false; + /** * Delay for the current mode transition, used for time out */ @@ -1080,11 +1111,6 @@ private: void buildRawDeviceCommand(CommandMessage* message); void buildInternalCommand(void); -// /** -// * Send a reply with the current mode and submode. -// */ -// void announceMode(void); - /** * Decrement the counter for the timout of replies. * @@ -1111,10 +1137,14 @@ private: /** * Build and send a command to the device. * - * This routine checks whether a raw or direct command has been received, checks the content of the received command and - * calls buildCommandFromCommand() for direct commands or sets #rawpacket to the received raw packet. - * If no external command is received or the received command is invalid and the current mode is @c MODE_NORMAL or a transitional mode, - * it asks the child class to build a command (via getNormalDeviceCommand() or getTransitionalDeviceCommand() and buildCommand()) and + * This routine checks whether a raw or direct command has been received, + * checks the content of the received command and calls + * buildCommandFromCommand() for direct commands or sets #rawpacket + * to the received raw packet. + * If no external command is received or the received command is invalid and + * the current mode is @c MODE_NORMAL or a transitional mode, it asks the + * child class to build a command (via getNormalDeviceCommand() or + * getTransitionalDeviceCommand() and buildCommand()) and * sends the command via RMAP. */ void doSendWrite(void); @@ -1159,7 +1189,6 @@ private: ReturnValue_t getStorageData(store_address_t storageAddress, uint8_t **data, uint32_t *len); - /** * @param modeTo either @c MODE_ON, MODE_NORMAL or MODE_RAW NOTHING ELSE!!! */ @@ -1170,25 +1199,14 @@ private: */ void callChildStatemachine(); - /** - * Switches the channel of the cookie used for the communication - * - * - * @param newChannel the object Id of the channel to switch to - * @return - * - @c RETURN_OK when cookie was changed - * - @c RETURN_FAILED when cookies could not be changed, eg because the newChannel is not enabled - * - @c returnvalues of RMAPChannelIF::isActive() - */ - ReturnValue_t switchCookieChannel(object_id_t newChannelId); - ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message); - virtual ReturnValue_t initializeAfterTaskCreation() override; + virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; - void parseReply(const uint8_t* receivedData, - size_t receivedDataLen); + virtual dur_millis_t getPeriodicOperationFrequency() const override; + + void parseReply(const uint8_t* receivedData, + size_t receivedDataLen); }; -#endif /* FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */ - +#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */ diff --git a/devicehandlers/DeviceHandlerFailureIsolation.cpp b/devicehandlers/DeviceHandlerFailureIsolation.cpp index 9fbe71d8..24fe15a0 100644 --- a/devicehandlers/DeviceHandlerFailureIsolation.cpp +++ b/devicehandlers/DeviceHandlerFailureIsolation.cpp @@ -247,6 +247,14 @@ bool DeviceHandlerFailureIsolation::isFdirInActionOrAreWeFaulty( } return true; } + + if (owner == nullptr) { + // Configuration error. + sif::error << "DeviceHandlerFailureIsolation::" + << "isFdirInActionOrAreWeFaulty: Owner not set!" << std::endl; + return false; + } + if (owner->getHealth() == HasHealthIF::FAULTY || owner->getHealth() == HasHealthIF::PERMANENT_FAULTY) { //Ignore all events in case device is already faulty. diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index 52a3be4d..9c8eb098 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -1,12 +1,19 @@ -#ifndef DEVICEHANDLERIF_H_ -#define DEVICEHANDLERIF_H_ +#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ +#define FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ + +#include "DeviceHandlerMessage.h" #include "../action/HasActionsIF.h" -#include "DeviceHandlerMessage.h" #include "../events/Event.h" #include "../modes/HasModesIF.h" #include "../ipc/MessageQueueSenderIF.h" +/** + * This is used to uniquely identify commands that are sent to a device + * The values are defined in the device-specific implementations + */ +using DeviceCommandId_t = uint32_t; + /** * @brief This is the Interface used to communicate with a device handler. * @details Includes all expected return values, events and modes. @@ -15,6 +22,7 @@ class DeviceHandlerIF { public: + static const uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20; static const uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10; @@ -47,6 +55,8 @@ public: //! 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. + //! It is possible to set the mode to _MODE_SHUT_DOWN to use the to off + //! transition if available. static const Mode_t _MODE_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6; //! It is possible to set the mode to _MODE_TO_ON to use the to on //! transition if available. @@ -96,7 +106,7 @@ public: static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF; // Standard codes used when building commands. - static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If the command size is 0. Checked in DHB + static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If no command data was given when expected. static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1); //!< Command ID not in commandMap. Checked in DHB static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA2); //!< Command was already executed. Checked in DHB static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3); @@ -150,4 +160,4 @@ public: }; -#endif /* DEVICEHANDLERIF_H_ */ +#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ */ diff --git a/devicehandlers/DeviceHandlerMessage.cpp b/devicehandlers/DeviceHandlerMessage.cpp index 564fae21..cb9043db 100644 --- a/devicehandlers/DeviceHandlerMessage.cpp +++ b/devicehandlers/DeviceHandlerMessage.cpp @@ -1,10 +1,6 @@ -#include "../objectmanager/ObjectManagerIF.h" #include "DeviceHandlerMessage.h" #include "../objectmanager/ObjectManagerIF.h" -DeviceHandlerMessage::DeviceHandlerMessage() { -} - store_address_t DeviceHandlerMessage::getStoreAddress( const CommandMessage* message) { return store_address_t(message->getParameter2()); @@ -25,14 +21,6 @@ uint8_t DeviceHandlerMessage::getWiretappingMode( return message->getParameter(); } -//void DeviceHandlerMessage::setDeviceHandlerDirectCommandMessage( -// CommandMessage* message, DeviceCommandId_t deviceCommand, -// store_address_t commandParametersStoreId) { -// message->setCommand(CMD_DIRECT); -// message->setParameter(deviceCommand); -// message->setParameter2(commandParametersStoreId.raw); -//} - void DeviceHandlerMessage::setDeviceHandlerRawCommandMessage( CommandMessage* message, store_address_t rawPacketStoreId) { message->setCommand(CMD_RAW); @@ -47,7 +35,7 @@ void DeviceHandlerMessage::setDeviceHandlerWiretappingMessage( void DeviceHandlerMessage::setDeviceHandlerSwitchIoBoardMessage( CommandMessage* message, uint32_t ioBoardIdentifier) { - message->setCommand(CMD_SWITCH_IOBOARD); + message->setCommand(CMD_SWITCH_ADDRESS); message->setParameter(ioBoardIdentifier); } @@ -79,18 +67,17 @@ void DeviceHandlerMessage::setDeviceHandlerDirectCommandReply( void DeviceHandlerMessage::clear(CommandMessage* message) { switch (message->getCommand()) { case CMD_RAW: -// case CMD_DIRECT: case REPLY_RAW_COMMAND: case REPLY_RAW_REPLY: case REPLY_DIRECT_COMMAND_DATA: { StorageManagerIF *ipcStore = objectManager->get( objects::IPC_STORE); - if (ipcStore != NULL) { + if (ipcStore != nullptr) { ipcStore->deleteData(getStoreAddress(message)); } } /* NO BREAK falls through*/ - case CMD_SWITCH_IOBOARD: + case CMD_SWITCH_ADDRESS: case CMD_WIRETAPPING: message->setCommand(CommandMessage::CMD_NONE); message->setParameter(0); diff --git a/devicehandlers/DeviceHandlerMessage.h b/devicehandlers/DeviceHandlerMessage.h index 8d1c94f4..e5da01c8 100644 --- a/devicehandlers/DeviceHandlerMessage.h +++ b/devicehandlers/DeviceHandlerMessage.h @@ -1,69 +1,56 @@ -#ifndef DEVICEHANDLERMESSAGE_H_ -#define DEVICEHANDLERMESSAGE_H_ +#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ +#define FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ #include "../action/ActionMessage.h" #include "../ipc/CommandMessage.h" #include "../objectmanager/SystemObjectIF.h" #include "../storagemanager/StorageManagerIF.h" -//SHOULDDO: 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 - * - * The values are defined in the device-specific implementations - */ -typedef uint32_t DeviceCommandId_t; - -/** - * The DeviceHandlerMessage is used to send Commands to a DeviceHandlerIF + * @brief The DeviceHandlerMessage is used to send commands to classes + * implementing DeviceHandlerIF */ class DeviceHandlerMessage { -private: - DeviceHandlerMessage(); public: + /** + * Instantiation forbidden. Instead, use static functions to operate + * on messages. + */ + DeviceHandlerMessage() = delete; + virtual ~DeviceHandlerMessage() {} /** * These are the commands that can be sent to a DeviceHandlerBase */ static const uint8_t MESSAGE_ID = messagetypes::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 - static const Command_t CMD_WIRETAPPING = MAKE_COMMAND_ID( 4 ); //!< (De)Activates the monitoring of all raw traffic in DeviceHandlers, setParameter is 0 to deactivate, 1 to activate + //! Sends a raw command, setParameter is a storeId containing the + //! raw packet to send + static const Command_t CMD_RAW = MAKE_COMMAND_ID(1); + //! Requests a IO-Board switch, setParameter() is the IO-Board identifier + static const Command_t CMD_SWITCH_ADDRESS = MAKE_COMMAND_ID(3); + //! (De)Activates the monitoring of all raw traffic in DeviceHandlers, + //! setParameter is 0 to deactivate, 1 to activate + static const Command_t CMD_WIRETAPPING = MAKE_COMMAND_ID(4); - /*static const Command_t REPLY_SWITCHED_IOBOARD = MAKE_COMMAND_ID(1 );//!< Reply to a @c CMD_SWITCH_IOBOARD, indicates switch was successful, getParameter() contains the board switched to (0: nominal, 1: redundant) - static const Command_t REPLY_CANT_SWITCH_IOBOARD = MAKE_COMMAND_ID( 2); //!< Reply to a @c CMD_SWITCH_IOBOARD, indicating the switch could not be performed, getParameter() contains the error message - static const Command_t REPLY_WIRETAPPING = MAKE_COMMAND_ID( 3); //!< Reply to a @c CMD_WIRETAPPING, getParameter() is the current state, 1 enabled, 0 disabled - - static const Command_t REPLY_COMMAND_WAS_SENT = MAKE_COMMAND_ID(4 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates the command was successfully sent to the device, getParameter() contains the ::DeviceCommandId_t - static const Command_t REPLY_COMMAND_NOT_SUPPORTED = MAKE_COMMAND_ID(5 );//!< Reply to a @c CMD_DIRECT, the requested ::DeviceCommand_t is not supported, getParameter() contains the requested ::DeviceCommand_t, getParameter2() contains the ::DeviceCommandId_t - static const Command_t REPLY_COMMAND_WAS_NOT_SENT = MAKE_COMMAND_ID(6 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates the command was not sent, getParameter contains the RMAP Return code (@see rmap.h), getParameter2() contains the ::DeviceCommandId_t - - static const Command_t REPLY_COMMAND_ALREADY_SENT = MAKE_COMMAND_ID(7 );//!< Reply to a @c CMD_DIRECT, the requested ::DeviceCommand_t has already been sent to the device and not ye been answered - static const Command_t REPLY_WRONG_MODE_FOR_CMD = MAKE_COMMAND_ID(8 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates that the requested command can not be sent in the curent mode, getParameter() contains the DeviceHandlerCommand_t - static const Command_t REPLY_NO_DATA = MAKE_COMMAND_ID(9 ); //!< Reply to a CMD_RAW or @c CMD_DIRECT, indicates that the ::store_id_t was invalid, getParameter() contains the ::DeviceCommandId_t, getPrameter2() contains the error code - */ - static const Command_t REPLY_DIRECT_COMMAND_SENT = ActionMessage::STEP_SUCCESS; //!< Signals that a direct command was sent - static const Command_t REPLY_RAW_COMMAND = MAKE_COMMAND_ID(0x11 ); //!< Contains a raw command sent to the Device - static const Command_t REPLY_RAW_REPLY = MAKE_COMMAND_ID( 0x12); //!< Contains a raw reply from the Device, getParameter() is the ObjcetId of the sender, getParameter2() is a ::store_id_t containing the raw packet received + //! Signals that a direct command was sent + static const Command_t REPLY_DIRECT_COMMAND_SENT = ActionMessage::STEP_SUCCESS; + //! Contains a raw command sent to the Device + static const Command_t REPLY_RAW_COMMAND = MAKE_COMMAND_ID(0x11); + //! Contains a raw reply from the Device, getParameter() is the ObjcetId + //! of the sender, getParameter2() is a ::store_id_t containing the + //! raw packet received + static const Command_t REPLY_RAW_REPLY = MAKE_COMMAND_ID(0x12); static const Command_t REPLY_DIRECT_COMMAND_DATA = ActionMessage::DATA_REPLY; - /** - * Default Destructor - */ - virtual ~DeviceHandlerMessage() { - } - static store_address_t getStoreAddress(const CommandMessage* message); static uint32_t getDeviceCommandId(const CommandMessage* message); static object_id_t getDeviceObjectId(const CommandMessage *message); static object_id_t getIoBoardObjectId(const CommandMessage* message); static uint8_t getWiretappingMode(const CommandMessage* message); -// static void setDeviceHandlerDirectCommandMessage(CommandMessage* message, -// DeviceCommandId_t deviceCommand, -// store_address_t commandParametersStoreId); - static void setDeviceHandlerDirectCommandReply(CommandMessage* message, object_id_t deviceObjectid, store_address_t commandParametersStoreId); @@ -75,11 +62,6 @@ public: object_id_t deviceObjectid, store_address_t rawPacketStoreId, bool isCommand); -// static void setDeviceHandlerMessage(CommandMessage* message, -// Command_t command, DeviceCommandId_t deviceCommand, -// store_address_t commandParametersStoreId); -// static void setDeviceHandlerMessage(CommandMessage* message, -// Command_t command, store_address_t rawPacketStoreId); static void setDeviceHandlerWiretappingMessage(CommandMessage* message, uint8_t wiretappingMode); static void setDeviceHandlerSwitchIoBoardMessage(CommandMessage* message, @@ -88,4 +70,4 @@ public: static void clear(CommandMessage* message); }; -#endif /* DEVICEHANDLERMESSAGE_H_ */ +#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ */ diff --git a/devicehandlers/DeviceTmReportingWrapper.cpp b/devicehandlers/DeviceTmReportingWrapper.cpp index 84f926f0..c70f57d6 100644 --- a/devicehandlers/DeviceTmReportingWrapper.cpp +++ b/devicehandlers/DeviceTmReportingWrapper.cpp @@ -1,4 +1,3 @@ -#include "../serialize/SerializeAdapter.h" #include "DeviceTmReportingWrapper.h" #include "../serialize/SerializeAdapter.h" diff --git a/devicehandlers/DeviceTmReportingWrapper.h b/devicehandlers/DeviceTmReportingWrapper.h index a14c4261..447e95f2 100644 --- a/devicehandlers/DeviceTmReportingWrapper.h +++ b/devicehandlers/DeviceTmReportingWrapper.h @@ -1,5 +1,5 @@ -#ifndef DEVICETMREPORTINGWRAPPER_H_ -#define DEVICETMREPORTINGWRAPPER_H_ +#ifndef FSFW_DEVICEHANDLERS_DEVICETMREPORTINGWRAPPER_H_ +#define FSFW_DEVICEHANDLERS_DEVICETMREPORTINGWRAPPER_H_ #include "../action/HasActionsIF.h" #include "../objectmanager/SystemObjectIF.h" @@ -24,4 +24,4 @@ private: SerializeIF *data; }; -#endif /* DEVICETMREPORTINGWRAPPER_H_ */ +#endif /* FSFW_DEVICEHANDLERS_DEVICETMREPORTINGWRAPPER_H_ */ diff --git a/devicehandlers/HealthDevice.cpp b/devicehandlers/HealthDevice.cpp index b15e5d2b..418ed257 100644 --- a/devicehandlers/HealthDevice.cpp +++ b/devicehandlers/HealthDevice.cpp @@ -13,10 +13,10 @@ HealthDevice::~HealthDevice() { } ReturnValue_t HealthDevice::performOperation(uint8_t opCode) { - CommandMessage message; - ReturnValue_t result = commandQueue->receiveMessage(&message); + CommandMessage command; + ReturnValue_t result = commandQueue->receiveMessage(&command); if (result == HasReturnvaluesIF::RETURN_OK) { - healthHelper.handleHealthCommand(&message); + healthHelper.handleHealthCommand(&command); } return HasReturnvaluesIF::RETURN_OK; } diff --git a/devicehandlers/HealthDevice.h b/devicehandlers/HealthDevice.h index 53b0ab09..738f0c7e 100644 --- a/devicehandlers/HealthDevice.h +++ b/devicehandlers/HealthDevice.h @@ -1,5 +1,5 @@ -#ifndef HEALTHDEVICE_H_ -#define HEALTHDEVICE_H_ +#ifndef FSFW_DEVICEHANDLERS_HEALTHDEVICE_H_ +#define FSFW_DEVICEHANDLERS_HEALTHDEVICE_H_ #include "../health/HasHealthIF.h" #include "../health/HealthHelper.h" @@ -37,4 +37,4 @@ public: HealthHelper healthHelper; }; -#endif /* HEALTHDEVICE_H_ */ +#endif /* FSFW_DEVICEHANDLERS_HEALTHDEVICE_H_ */ From dbcd06527ef728c2620c4141eab58bbf40994339 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 12 Oct 2020 18:28:07 +0200 Subject: [PATCH 424/653] separate step for performOp now --- devicehandlers/DeviceHandlerBase.cpp | 39 ++++++++++++++++++---------- devicehandlers/DeviceHandlerBase.h | 3 ++- devicehandlers/DeviceHandlerIF.h | 3 ++- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 227d5b6d..d67e47d8 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -72,8 +72,13 @@ DeviceHandlerBase::~DeviceHandlerBase() { ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { this->pstStep = counter; + this->lastStep = this->pstStep; - if (getComAction() == SEND_WRITE) { + if (getComAction() == CommunicationAction::NOTHING) { + return HasReturnvaluesIF::RETURN_OK; + } + + if (getComAction() == CommunicationAction::PERFORM_OPERATION) { cookieInfo.state = COOKIE_UNUSED; readCommandQueue(); doStateMachine(); @@ -83,26 +88,29 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { hkSwitcher.performOperation(); hkManager.performHkOperation(); performOperationHook(); + return RETURN_OK; } + if (mode == MODE_OFF) { return RETURN_OK; } + switch (getComAction()) { - case SEND_WRITE: - if ((cookieInfo.state == COOKIE_UNUSED)) { + case CommunicationAction::SEND_WRITE: + if (cookieInfo.state == COOKIE_UNUSED) { + // if no external command was specified, build internal command. buildInternalCommand(); } doSendWrite(); break; - case GET_WRITE: + case CommunicationAction::GET_WRITE: doGetWrite(); break; - case SEND_READ: + case CommunicationAction::SEND_READ: doSendRead(); break; - case GET_READ: + case CommunicationAction::GET_READ: doGetRead(); - cookieInfo.state = COOKIE_UNUSED; break; default: break; @@ -821,24 +829,27 @@ void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len, } //Default child implementations -DeviceHandlerIF::CommunicationAction_t DeviceHandlerBase::getComAction() { +DeviceHandlerIF::CommunicationAction DeviceHandlerBase::getComAction() { switch (pstStep) { case 0: - return SEND_WRITE; + return CommunicationAction::PERFORM_OPERATION; break; case 1: - return GET_WRITE; - break; + return CommunicationAction::SEND_WRITE; + break; case 2: - return SEND_READ; + return CommunicationAction::GET_WRITE; break; case 3: - return GET_READ; + return CommunicationAction::SEND_READ; + break; + case 4: + return CommunicationAction::GET_READ; break; default: break; } - return NOTHING; + return CommunicationAction::NOTHING; } MessageQueueId_t DeviceHandlerBase::getCommandQueue() const { diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index eda318cb..627a6423 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -577,6 +577,7 @@ protected: /** This is the counter value from performOperation(). */ uint8_t pstStep = 0; + uint8_t lastStep = 0; uint32_t pstIntervalMs = 0; /** @@ -841,7 +842,7 @@ protected: * @return The Rmap action to execute in this step */ - virtual CommunicationAction_t getComAction(); + virtual CommunicationAction getComAction(); /** * Build the device command to send for raw mode. diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index 9c8eb098..088c1b45 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -139,7 +139,8 @@ public: * * This is used by the child class to tell the base class what to do. */ - enum CommunicationAction_t: uint8_t { + enum CommunicationAction: uint8_t { + PERFORM_OPERATION, SEND_WRITE,//!< Send write GET_WRITE, //!< Get write SEND_READ, //!< Send read From 73215baf118066c2eb5278416f302216a243cd9d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 15 Oct 2020 13:43:23 +0200 Subject: [PATCH 425/653] init commit --- storagemanager/ConstStorageAccessor.h | 2 - storagemanager/LocalPool.cpp | 346 ++++++++++++++++++++++++++ storagemanager/LocalPool.h | 233 ++++++++++------- storagemanager/PoolManager.cpp | 59 +++++ storagemanager/PoolManager.h | 41 ++- storagemanager/StorageAccessor.h | 2 - storagemanager/StorageManagerIF.h | 23 +- storagemanager/storeAddress.h | 13 +- 8 files changed, 612 insertions(+), 107 deletions(-) create mode 100644 storagemanager/LocalPool.cpp create mode 100644 storagemanager/PoolManager.cpp diff --git a/storagemanager/ConstStorageAccessor.h b/storagemanager/ConstStorageAccessor.h index 96d2dca2..570c20ce 100644 --- a/storagemanager/ConstStorageAccessor.h +++ b/storagemanager/ConstStorageAccessor.h @@ -20,9 +20,7 @@ class StorageManagerIF; */ class ConstStorageAccessor { //! StorageManager classes have exclusive access to private variables. - template friend class PoolManager; - template friend class LocalPool; public: /** diff --git a/storagemanager/LocalPool.cpp b/storagemanager/LocalPool.cpp new file mode 100644 index 00000000..8e5f4d48 --- /dev/null +++ b/storagemanager/LocalPool.cpp @@ -0,0 +1,346 @@ +#include "LocalPool.h" +#include + +LocalPool::LocalPool(object_id_t setObjectId, const LocalPoolConfig& poolConfig, + bool registered, bool spillsToHigherPools): + SystemObject(setObjectId, registered), + NUMBER_OF_POOLS(poolConfig.size()), + spillsToHigherPools(spillsToHigherPools) { + if(NUMBER_OF_POOLS == 0) { + sif::error << "LocalPool::LocalPool: Passed pool configuration is " + << " invalid!" << std::endl; + } + max_pools_t index = 0; + for (const auto& currentPoolConfig: poolConfig) { + this->numberOfElements[index] = currentPoolConfig.first; + this->elementSizes[index] = currentPoolConfig.second; + store[index] = std::vector( + numberOfElements[index] * elementSizes[index]); + sizeLists[index] = std::vector(numberOfElements[index]); + for(auto& size: sizeLists[index]) { + size = STORAGE_FREE; + } + index++; + } +} + +LocalPool::~LocalPool(void) {} + + +ReturnValue_t LocalPool::addData(store_address_t* storageId, + const uint8_t* data, size_t size, bool ignoreFault) { + ReturnValue_t status = reserveSpace(size, storageId, ignoreFault); + if (status == RETURN_OK) { + write(*storageId, data, size); + } + return status; +} + +ReturnValue_t LocalPool::getData(store_address_t packetId, + const uint8_t **packetPtr, size_t *size) { + uint8_t* tempData = nullptr; + ReturnValue_t status = modifyData(packetId, &tempData, size); + *packetPtr = tempData; + return status; +} + +ReturnValue_t LocalPool::getData(store_address_t storeId, + ConstStorageAccessor& storeAccessor) { + uint8_t* tempData = nullptr; + ReturnValue_t status = modifyData(storeId, &tempData, + &storeAccessor.size_); + storeAccessor.assignStore(this); + storeAccessor.constDataPointer = tempData; + return status; +} + +ConstAccessorPair LocalPool::getData(store_address_t storeId) { + uint8_t* tempData = nullptr; + ConstStorageAccessor constAccessor(storeId, this); + ReturnValue_t status = modifyData(storeId, &tempData, &constAccessor.size_); + constAccessor.constDataPointer = tempData; + return ConstAccessorPair(status, std::move(constAccessor)); +} + +ReturnValue_t LocalPool::getFreeElement(store_address_t *storageId, + const size_t size, uint8_t **pData, bool ignoreFault) { + ReturnValue_t status = reserveSpace(size, storageId, ignoreFault); + if (status == RETURN_OK) { + *pData = &store[storageId->poolIndex][getRawPosition(*storageId)]; + } + else { + *pData = nullptr; + } + return status; +} + + +AccessorPair LocalPool::modifyData(store_address_t storeId) { + StorageAccessor accessor(storeId, this); + ReturnValue_t status = modifyData(storeId, &accessor.dataPointer, + &accessor.size_); + accessor.assignConstPointer(); + return AccessorPair(status, std::move(accessor)); +} + +ReturnValue_t LocalPool::modifyData(store_address_t storeId, + StorageAccessor& storeAccessor) { + storeAccessor.assignStore(this); + ReturnValue_t status = modifyData(storeId, &storeAccessor.dataPointer, + &storeAccessor.size_); + storeAccessor.assignConstPointer(); + return status; +} + +ReturnValue_t LocalPool::modifyData(store_address_t storeId, + uint8_t **packetPtr, size_t *size) { + ReturnValue_t status = RETURN_FAILED; + if (storeId.poolIndex >= NUMBER_OF_POOLS) { + return ILLEGAL_STORAGE_ID; + } + if ((storeId.packetIndex >= numberOfElements[storeId.poolIndex])) { + return ILLEGAL_STORAGE_ID; + } + + if (sizeLists[storeId.poolIndex][storeId.packetIndex] + != STORAGE_FREE) { + size_type packetPosition = getRawPosition(storeId); + *packetPtr = &store[storeId.poolIndex][packetPosition]; + *size = sizeLists[storeId.poolIndex][storeId.packetIndex]; + status = RETURN_OK; + } + else { + status = DATA_DOES_NOT_EXIST; + } + return status; +} + +ReturnValue_t LocalPool::deleteData(store_address_t storeId) { +#if FSFW_DEBUGGING == 1 + sif::debug << "Delete: Pool: " << std::dec << storeId.poolIndex + << " Index: " << storeId.packetIndex << std::endl; + +#endif + ReturnValue_t status = RETURN_OK; + size_type pageSize = getPageSize(storeId.poolIndex); + if ((pageSize != 0) and + (storeId.packetIndex < numberOfElements[storeId.poolIndex])) { + uint16_t packetPosition = getRawPosition(storeId); + uint8_t* ptr = &store[storeId.poolIndex][packetPosition]; + std::memset(ptr, 0, pageSize); + //Set free list + sizeLists[storeId.poolIndex][storeId.packetIndex] = STORAGE_FREE; + } + else { + //pool_index or packet_index is too large + sif::error << "LocalPool::deleteData: Illegal store ID, no deletion!" + << std::endl; + status = ILLEGAL_STORAGE_ID; + } + return status; +} + +ReturnValue_t LocalPool::deleteData(uint8_t *ptr, size_t size, + store_address_t *storeId) { + store_address_t localId; + ReturnValue_t result = ILLEGAL_ADDRESS; + for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { + //Not sure if new allocates all stores in order. so better be careful. + if ((store[n].data() <= ptr) and + (&store[n][numberOfElements[n]*elementSizes[n]] > ptr)) { + localId.poolIndex = n; + uint32_t deltaAddress = ptr - store[n].data(); + // Getting any data from the right "block" is ok. + // This is necessary, as IF's sometimes don't point to the first + // element of an object. + localId.packetIndex = deltaAddress / elementSizes[n]; + result = deleteData(localId); +#if FSFW_DEBUGGING == 1 + if (deltaAddress % elementSizes[n] != 0) { + sif::error << "LocalPool::deleteData: Address not aligned!" + << std::endl; + } +#endif + break; + } + } + if (storeId != nullptr) { + *storeId = localId; + } + return result; +} + + +ReturnValue_t LocalPool::initialize() { + ReturnValue_t result = SystemObject::initialize(); + if (result != RETURN_OK) { + return result; + } + internalErrorReporter = objectManager->get( + objects::INTERNAL_ERROR_REPORTER); + if (internalErrorReporter == nullptr){ + return ObjectManagerIF::INTERNAL_ERR_REPORTER_UNINIT; + } + + //Check if any pool size is large than the maximum allowed. + for (uint8_t count = 0; count < NUMBER_OF_POOLS; count++) { + if (elementSizes[count] >= STORAGE_FREE) { + sif::error << "LocalPool::initialize: Pool is too large! " + "Max. allowed size is: " << (STORAGE_FREE - 1) << std::endl; + return StorageManagerIF::POOL_TOO_LARGE; + } + } + return HasReturnvaluesIF::RETURN_OK; +} + +void LocalPool::clearStore() { + for(auto& sizeList: sizeLists) { + for(auto& size: sizeList) { + size = STORAGE_FREE; + } +// std::memset(sizeList[index], 0xff, +// numberOfElements[index] * sizeof(size_type)); + } + +} + +ReturnValue_t LocalPool::reserveSpace(const size_t size, + store_address_t *storeId, bool ignoreFault) { + ReturnValue_t status = getPoolIndex(size, &storeId->poolIndex); + if (status != RETURN_OK) { + sif::error << "LocalPool( " << std::hex << getObjectId() << std::dec + << " )::reserveSpace: Packet too large." << std::endl; + return status; + } + status = findEmpty(storeId->poolIndex, &storeId->packetIndex); + while (status != RETURN_OK && spillsToHigherPools) { + status = getPoolIndex(size, &storeId->poolIndex, storeId->poolIndex + 1); + if (status != RETURN_OK) { + //We don't find any fitting pool anymore. + break; + } + status = findEmpty(storeId->poolIndex, &storeId->packetIndex); + } + if (status == RETURN_OK) { +#if FSFW_DEBUGGING == 1 + sif::debug << "Reserve: Pool: " << std::dec + << storeId->poolIndex << " Index: " << storeId->packetIndex + << std::endl; +#endif + sizeLists[storeId->poolIndex][storeId->packetIndex] = size; + } + else { + if ((not ignoreFault) and (internalErrorReporter != nullptr)) { + internalErrorReporter->storeFull(); + } + } + return status; +} + +void LocalPool::write(store_address_t storeId, const uint8_t *data, + size_t size) { + uint8_t* ptr = nullptr; + size_type packetPosition = getRawPosition(storeId); + + // Size was checked before calling this function. + ptr = &store[storeId.poolIndex][packetPosition]; + std::memcpy(ptr, data, size); + sizeLists[storeId.poolIndex][storeId.packetIndex] = size; +} + +LocalPool::size_type LocalPool::getPageSize(max_pools_t poolIndex) { + if (poolIndex < NUMBER_OF_POOLS) { + return elementSizes[poolIndex]; + } + else { + return 0; + } +} + +void LocalPool::setToSpillToHigherPools(bool enable) { + this->spillsToHigherPools = enable; +} + +ReturnValue_t LocalPool::getPoolIndex(size_t packetSize, uint16_t *poolIndex, + uint16_t startAtIndex) { + for (uint16_t n = startAtIndex; n < NUMBER_OF_POOLS; n++) { +#if FSFW_DEBUGGING == 1 + sif::debug << "LocalPool " << getObjectId() << "::getPoolIndex: Pool: " + << n << ", Element Size: " << elementSizes[n] << std::endl; +#endif + if (elementSizes[n] >= packetSize) { + *poolIndex = n; + return RETURN_OK; + } + } + return DATA_TOO_LARGE; +} + +LocalPool::size_type LocalPool::getRawPosition(store_address_t storeId) { + return storeId.packetIndex * elementSizes[storeId.poolIndex]; +} + +ReturnValue_t LocalPool::findEmpty(n_pool_elem_t poolIndex, uint16_t *element) { + ReturnValue_t status = DATA_STORAGE_FULL; + for (uint16_t foundElement = 0; foundElement < numberOfElements[poolIndex]; + foundElement++) { + if (sizeLists[poolIndex][foundElement] == STORAGE_FREE) { + *element = foundElement; + status = RETURN_OK; + break; + } + } + return status; +} + +size_t LocalPool::getTotalSize(size_t* additionalSize) { + size_t totalSize = 0; + size_t sizesSize = 0; + for(uint8_t idx = 0; idx < NUMBER_OF_POOLS; idx ++) { + totalSize += elementSizes[idx] * numberOfElements[idx]; + sizesSize += numberOfElements[idx] * sizeof(size_type); + } + if(additionalSize != nullptr) { + *additionalSize = sizesSize; + } + return totalSize; +} + +void LocalPool::getFillCount(uint8_t *buffer, uint8_t *bytesWritten) { + if(bytesWritten == nullptr or buffer == nullptr) { + return; + } + + uint16_t reservedHits = 0; + uint8_t idx = 0; + uint16_t sum = 0; + for(; idx < NUMBER_OF_POOLS; idx ++) { + for(const auto& size: sizeLists[idx]) { + if(size != STORAGE_FREE) { + reservedHits++; + } + } + buffer[idx] = static_cast(reservedHits) / + numberOfElements[idx] * 100; + *bytesWritten += 1; + sum += buffer[idx]; + reservedHits = 0; + } + buffer[idx] = sum / NUMBER_OF_POOLS; + *bytesWritten += 1; +} + + +void LocalPool::clearPage(max_pools_t pageIndex) { + if(pageIndex >= NUMBER_OF_POOLS) { + return; + } + + // Mark the storage as free + for(auto& size: sizeLists[pageIndex]) { + size = STORAGE_FREE; + } + + // Set all the page content to 0. + std::memset(store[pageIndex].data(), 0, elementSizes[pageIndex]); +} diff --git a/storagemanager/LocalPool.h b/storagemanager/LocalPool.h index 3a94c03d..db771152 100644 --- a/storagemanager/LocalPool.h +++ b/storagemanager/LocalPool.h @@ -7,57 +7,93 @@ #include "../serviceinterface/ServiceInterfaceStream.h" #include "../internalError/InternalErrorReporterIF.h" #include "../storagemanager/StorageAccessor.h" -#include + +#include +#include +#include +#include /** - * @brief The LocalPool class provides an intermediate data storage with - * a fixed pool size policy. - * @details The class implements the StorageManagerIF interface. While the - * total number of pools is fixed, the element sizes in one pool and - * the number of pool elements per pool are set on construction. - * The full amount of memory is allocated on construction. - * The overhead is 4 byte per pool element to store the size - * information of each stored element. - * To maintain an "empty" information, the pool size is limited to - * 0xFFFF-1 bytes. - * It is possible to store empty packets in the pool. - * The local pool is NOT thread-safe. - * @author Bastian Baetz + * @brief The LocalPool class provides an intermediate data storage with + * a fixed pool size policy. + * @details + * The class implements the StorageManagerIF interface. While the total number + * of pools is fixed, the element sizes in one pool and the number of pool + * elements per pool are set on construction. The full amount of memory is + * allocated on construction. + * The overhead is 4 byte per pool element to store the size information of + * each stored element. To maintain an "empty" information, the pool size is + * limited to 0xFFFF-1 bytes. + * It is possible to store empty packets in the pool. + * The local pool is NOT thread-safe. */ -template class LocalPool: public SystemObject, public StorageManagerIF { public: - /** - * @brief This definition generally sets the number of different sized pools. - * @details This must be less than the maximum number of pools (currently 0xff). - */ - // static const uint32_t NUMBER_OF_POOLS; - /** - * @brief This is the default constructor for a pool manager instance. - * @details By passing two arrays of size NUMBER_OF_POOLS, the constructor - * allocates memory (with @c new) for store and size_list. These - * regions are all set to zero on start up. - * @param setObjectId The object identifier to be set. This allows for - * multiple instances of LocalPool in the system. - * @param element_sizes An array of size NUMBER_OF_POOLS in which the size - * of a single element in each pool is determined. - * The sizes must be provided in ascending order. - * - * @param n_elements An array of size NUMBER_OF_POOLS in which the - * number of elements for each pool is determined. - * The position of these values correspond to those in - * element_sizes. - * @param registered Register the pool in object manager or not. - * Default is false (local pool). - * @param spillsToHigherPools A variable to determine whether - * higher n pools are used if the store is full. - */ - LocalPool(object_id_t setObjectId, - const uint16_t element_sizes[NUMBER_OF_POOLS], - const uint16_t n_elements[NUMBER_OF_POOLS], - bool registered = false, - bool spillsToHigherPools = false); + using pool_elem_size_t = size_type; + using n_pool_elem_t = uint16_t; + using LocalPoolCfgPair = std::pair; + + // The configuration needs to be provided with the pool sizes ascending + // but the number of pool elements as the first value is more intuitive. + // Therefore, a custom comparator was provided. + struct LocalPoolConfigCmp + { + bool operator ()(const LocalPoolCfgPair &a, + const LocalPoolCfgPair &b) const + { + if(a.second < b.second) { + return true; + } + else if(a.second > b.second) { + return false; + } + else { + if(a.first < b.first) { + return true; + } + else { + return false; + } + } + } + }; + using LocalPoolConfig = std::multiset; + + /** + * @brief This definition generally sets the number of + * different sized pools. It is derived from the number of pairs + * inside the LocalPoolConfig set on object creation. + * @details + * This must be less than the maximum number of pools (currently 0xff). + */ + const max_pools_t NUMBER_OF_POOLS; + + /** + * @brief This is the default constructor for a pool manager instance. + * @details + * The pool is configured by passing a set of pairs into the constructor. + * The first value of that pair determines the number of one elements on + * the respective page of the pool while the second value determines how + * many elements with that size are created on that page. + * All regions are to zero on start up. + * @param setObjectId The object identifier to be set. This allows for + * multiple instances of LocalPool in the system. + * @param poolConfig + * This is a set of pairs to configure the number of pages in the pool, + * the size of an element on a page, the number of elements on a page + * and the total size of the pool at once while also implicitely + * sorting the pairs in the right order. + * @param registered + * Determines whether the pool is registered in the object manager or not. + * @param spillsToHigherPools A variable to determine whether + * higher n pools are used if the store is full. + */ + LocalPool(object_id_t setObjectId, const LocalPoolConfig& poolConfig, + bool registered = false, bool spillsToHigherPools = false); + + void setToSpillToHigherPools(bool enable); + /** * @brief In the LocalPool's destructor all allocated memory is freed. */ @@ -66,25 +102,49 @@ public: /** * Documentation: See StorageManagerIF.h */ - ReturnValue_t addData(store_address_t* storageId, const uint8_t * data, + ReturnValue_t addData(store_address_t* storeId, const uint8_t * data, size_t size, bool ignoreFault = false) override; - ReturnValue_t getFreeElement(store_address_t* storageId,const size_t size, - uint8_t** p_data, bool ignoreFault = false) override; + ReturnValue_t getFreeElement(store_address_t* storeId,const size_t size, + uint8_t** pData, bool ignoreFault = false) override; - ConstAccessorPair getData(store_address_t packet_id) override; - ReturnValue_t getData(store_address_t packet_id, ConstStorageAccessor&) override; - ReturnValue_t getData(store_address_t packet_id, const uint8_t** packet_ptr, + ConstAccessorPair getData(store_address_t storeId) override; + ReturnValue_t getData(store_address_t storeId, + ConstStorageAccessor& constAccessor) override; + ReturnValue_t getData(store_address_t storeId, + const uint8_t** packet_ptr, size_t * size) override; + + AccessorPair modifyData(store_address_t storeId) override; + ReturnValue_t modifyData(store_address_t storeId, + StorageAccessor& storeAccessor) override; + ReturnValue_t modifyData(store_address_t storeId, uint8_t** packet_ptr, size_t * size) override; - AccessorPair modifyData(store_address_t packet_id) override; - ReturnValue_t modifyData(store_address_t packet_id, StorageAccessor&) override; - ReturnValue_t modifyData(store_address_t packet_id, uint8_t** packet_ptr, - size_t * size) override; - - virtual ReturnValue_t deleteData(store_address_t) override; + virtual ReturnValue_t deleteData(store_address_t storeId) override; virtual ReturnValue_t deleteData(uint8_t* ptr, size_t size, - store_address_t* storeId = NULL) override; + store_address_t* storeId = nullptr) override; + + /** + * Get the total size of allocated memory for pool data. + * There is an additional overhead of the sizes of elements which will + * be assigned to additionalSize + * @return + */ + size_t getTotalSize(size_t* additionalSize) override; + + /** + * Get the fill count of the pool. Each character inside the provided + * buffer will be assigned to a rounded percentage fill count for each + * page. The last written byte (at the index bytesWritten - 1) + * will contain the total fill count of the pool as a mean of the + * percentages of single pages. + * @param buffer + * @param maxSize + */ + void getFillCount(uint8_t* buffer, uint8_t* bytesWritten) override; + void clearStore() override; + void clearPage(max_pools_t pageIndex) override; + ReturnValue_t initialize() override; protected: /** @@ -94,43 +154,48 @@ protected: * @return - #RETURN_OK on success, * - the return codes of #getPoolIndex or #findEmpty otherwise. */ - virtual ReturnValue_t reserveSpace(const uint32_t size, + virtual ReturnValue_t reserveSpace(const size_t size, store_address_t* address, bool ignoreFault); - InternalErrorReporterIF *internalErrorReporter; private: - /** - * Indicates that this element is free. - * This value limits the maximum size of a pool. Change to larger data type - * if increase is required. - */ - static const uint32_t STORAGE_FREE = 0xFFFFFFFF; + /** + * Indicates that this element is free. + * This value limits the maximum size of a pool. + * Change to larger data type if increase is required. + */ + static const size_type STORAGE_FREE = std::numeric_limits::max(); /** * @brief In this array, the element sizes of each pool is stored. * @details The sizes are maintained for internal pool management. The sizes * must be set in ascending order on construction. */ - uint32_t element_sizes[NUMBER_OF_POOLS]; + std::vector elementSizes = + std::vector(NUMBER_OF_POOLS); /** * @brief n_elements stores the number of elements per pool. * @details These numbers are maintained for internal pool management. */ - uint16_t n_elements[NUMBER_OF_POOLS]; + std::vector numberOfElements = + std::vector(NUMBER_OF_POOLS); /** * @brief store represents the actual memory pool. * @details It is an array of pointers to memory, which was allocated with * a @c new call on construction. */ - uint8_t* store[NUMBER_OF_POOLS]; + std::vector> store = + std::vector>(NUMBER_OF_POOLS); + /** * @brief The size_list attribute stores the size values of every pool element. * @details As the number of elements is determined on construction, the size list * is also dynamically allocated there. */ - uint32_t* size_list[NUMBER_OF_POOLS]; + std::vector> sizeLists = + std::vector>(NUMBER_OF_POOLS); + //! A variable to determine whether higher n pools are used if //! the store is full. - bool spillsToHigherPools; + bool spillsToHigherPools = false; /** * @brief This method safely stores the given data in the given packet_id. * @details It also sets the size in size_list. The method does not perform @@ -139,30 +204,24 @@ private: * @param data The data to be stored. * @param size The size of the data to be stored. */ - void write(store_address_t packet_id, const uint8_t* data, size_t size); + void write(store_address_t packetId, const uint8_t* data, size_t size); /** * @brief A helper method to read the element size of a certain pool. * @param pool_index The pool in which to look. * @return Returns the size of an element or 0. */ - uint32_t getPageSize(uint16_t pool_index); - /** - * @brief This helper method looks up a fitting pool for a given size. - * @details The pools are looked up in ascending order, so the first that - * fits is used. - * @param packet_size The size of the data to be stored. - * @return Returns the pool that fits or StorageManagerIF::INVALID_ADDRESS. - */ + size_type getPageSize(max_pools_t poolIndex); + /** * @brief This helper method looks up a fitting pool for a given size. * @details The pools are looked up in ascending order, so the first that * fits is used. * @param packet_size The size of the data to be stored. * @param[out] poolIndex The fitting pool index found. - * @return - #RETURN_OK on success, - * - #DATA_TOO_LARGE otherwise. + * @return - @c RETURN_OK on success, + * - @c DATA_TOO_LARGE otherwise. */ - ReturnValue_t getPoolIndex(size_t packet_size, uint16_t* poolIndex, + ReturnValue_t getPoolIndex(size_t packetSize, uint16_t* poolIndex, uint16_t startAtIndex = 0); /** * @brief This helper method calculates the true array position in store @@ -172,7 +231,7 @@ private: * @param packet_id The packet id to look up. * @return Returns the position of the data in store. */ - uint32_t getRawPosition(store_address_t packet_id); + size_type getRawPosition(store_address_t storeId); /** * @brief This is a helper method to find an empty element in a given pool. * @details The method searches size_list for the first empty element, so @@ -182,9 +241,9 @@ private: * @return - #RETURN_OK on success, * - #DATA_STORAGE_FULL if the store is full */ - ReturnValue_t findEmpty(uint16_t pool_index, uint16_t* element); + ReturnValue_t findEmpty(n_pool_elem_t poolIndex, uint16_t* element); + + InternalErrorReporterIF *internalErrorReporter = nullptr; }; -#include "LocalPool.tpp" - #endif /* FSFW_STORAGEMANAGER_LOCALPOOL_H_ */ diff --git a/storagemanager/PoolManager.cpp b/storagemanager/PoolManager.cpp new file mode 100644 index 00000000..9c801a3d --- /dev/null +++ b/storagemanager/PoolManager.cpp @@ -0,0 +1,59 @@ +#include "PoolManager.h" + +PoolManager::PoolManager(object_id_t setObjectId, + const LocalPoolConfig& localPoolConfig): + LocalPool(setObjectId, localPoolConfig, true) { + mutex = MutexFactory::instance()->createMutex(); +} + + +PoolManager::~PoolManager(void) { + MutexFactory::instance()->deleteMutex(mutex); +} + + +ReturnValue_t PoolManager::reserveSpace(const size_t size, + store_address_t* address, bool ignoreFault) { + MutexHelper mutexHelper(mutex, MutexIF::TimeoutType::WAITING, + mutexTimeoutMs); + ReturnValue_t status = LocalPool::reserveSpace(size, + address,ignoreFault); + return status; +} + + +ReturnValue_t PoolManager::deleteData( + store_address_t storeId) { +#if FSFW_DEBUGGING == 1 + sif::debug << "PoolManager( " << translateObject(getObjectId()) << + " )::deleteData from store " << storeId.poolIndex << + ". id is "<< storeId.packetIndex << std::endl; +#endif + MutexHelper mutexHelper(mutex, MutexIF::TimeoutType::WAITING, + mutexTimeoutMs); + return LocalPool::deleteData(storeId); +} + + +ReturnValue_t PoolManager::deleteData(uint8_t* buffer, + size_t size, store_address_t* storeId) { + MutexHelper mutexHelper(mutex, MutexIF::TimeoutType::WAITING, 20); + ReturnValue_t status = LocalPool::deleteData(buffer, + size, storeId); + return status; +} + + +void PoolManager::setMutexTimeout( + uint32_t mutexTimeoutMs) { + this->mutexTimeoutMs = mutexTimeoutMs; +} + +ReturnValue_t PoolManager::lockMutex(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { + return mutex->lockMutex(timeoutType, timeoutMs); +} + +ReturnValue_t PoolManager::unlockMutex() { + return mutex->unlockMutex(); +} diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index 8cc6c065..5786a225 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -9,16 +9,20 @@ /** * @brief The PoolManager class provides an intermediate data storage with * a fixed pool size policy for inter-process communication. - * @details Uses local pool calls but is thread safe by protecting the call - * with a lock. + * @details + * Uses local pool calls but is thread safe by protecting most calls + * with a lock. The developer can lock the pool with the provided API + * if the lock needs to persists beyond the function call. + * + * Other than that, the class provides the same interface as the LocalPool + * class. The class is always registered as a system object as it is assumed + * it will always be used concurrently (if this is not the case, it is + * recommended to use the LocalPool class instead). * @author Bastian Baetz */ -template -class PoolManager : public LocalPool { +class PoolManager: public LocalPool { public: - PoolManager(object_id_t setObjectId, - const uint16_t element_sizes[NUMBER_OF_POOLS], - const uint16_t n_elements[NUMBER_OF_POOLS]); + PoolManager(object_id_t setObjectId, const LocalPoolConfig& poolConfig); /** * @brief In the PoolManager's destructor all allocated memory @@ -26,6 +30,12 @@ public: */ virtual ~PoolManager(); + /** + * Set the default mutex timeout for internal calls. + * @param mutexTimeoutMs + */ + void setMutexTimeout(uint32_t mutexTimeoutMs); + /** * @brief LocalPool overrides for thread-safety. Decorator function * which wraps LocalPool calls with a mutex protection. @@ -34,12 +44,23 @@ public: ReturnValue_t deleteData(uint8_t* buffer, size_t size, store_address_t* storeId = nullptr) override; - void setMutexTimeout(uint32_t mutexTimeoutMs); + /** + * The developer is allowed to lock the mutex in case the lock needs + * to persist beyond the function calls which are not protected by the + * class. + * @param timeoutType + * @param timeoutMs + * @return + */ + ReturnValue_t lockMutex(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs); + ReturnValue_t unlockMutex(); + protected: //! Default mutex timeout value to prevent permanent blocking. uint32_t mutexTimeoutMs = 20; - ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address, + ReturnValue_t reserveSpace(const size_t size, store_address_t* address, bool ignoreFault) override; /** @@ -51,6 +72,4 @@ protected: MutexIF* mutex; }; -#include "PoolManager.tpp" - #endif /* FSFW_STORAGEMANAGER_POOLMANAGER_H_ */ diff --git a/storagemanager/StorageAccessor.h b/storagemanager/StorageAccessor.h index 5cf15d50..d5b383eb 100644 --- a/storagemanager/StorageAccessor.h +++ b/storagemanager/StorageAccessor.h @@ -10,9 +10,7 @@ class StorageManagerIF; */ class StorageAccessor: public ConstStorageAccessor { //! StorageManager classes have exclusive access to private variables. - template friend class PoolManager; - template friend class LocalPool; public: StorageAccessor(store_address_t storeId); diff --git a/storagemanager/StorageManagerIF.h b/storagemanager/StorageManagerIF.h index 834e7563..769616d7 100644 --- a/storagemanager/StorageManagerIF.h +++ b/storagemanager/StorageManagerIF.h @@ -28,6 +28,9 @@ using ConstAccessorPair = std::pair; */ class StorageManagerIF : public HasReturnvaluesIF { public: + using size_type = size_t; + using max_pools_t = uint8_t; + static const uint8_t INTERFACE_ID = CLASS_ID::STORAGE_MANAGER_IF; //!< The unique ID for return codes for this interface. static const ReturnValue_t DATA_TOO_LARGE = MAKE_RETURN_CODE(1); //!< This return code indicates that the data to be stored is too large for the store. static const ReturnValue_t DATA_STORAGE_FULL = MAKE_RETURN_CODE(2); //!< This return code indicates that a data storage is full. @@ -40,7 +43,9 @@ public: static const Event GET_DATA_FAILED = MAKE_EVENT(0, SEVERITY::LOW); static const Event STORE_DATA_FAILED = MAKE_EVENT(1, SEVERITY::LOW); - static const uint32_t INVALID_ADDRESS = 0xFFFFFFFF; //!< Indicates an invalid (i.e unused) storage address. + //!< Indicates an invalid (i.e unused) storage address. + static const uint32_t INVALID_ADDRESS = 0xFFFFFFFF; + /** * @brief This is the empty virtual destructor as required for C++ interfaces. */ @@ -164,6 +169,22 @@ public: * Use with care! */ virtual void clearStore() = 0; + + /** + * Clears a page in the store. Use with care! + * @param pageIndex + */ + virtual void clearPage(uint8_t pageIndex) = 0; + + /** + * Get the fill count of the pool. The exact form will be implementation + * dependant. + * @param buffer + * @param bytesWritten + */ + virtual void getFillCount(uint8_t* buffer, uint8_t* bytesWritten) = 0; + + virtual size_t getTotalSize(size_t* additionalSize) = 0; }; #endif /* FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_ */ diff --git a/storagemanager/storeAddress.h b/storagemanager/storeAddress.h index 044c0790..ea72f6f8 100644 --- a/storagemanager/storeAddress.h +++ b/storagemanager/storeAddress.h @@ -3,16 +3,21 @@ #include +namespace storeId { +static constexpr uint32_t INVALID_STORE_ADDRESS = 0xffffffff; +} + /** * This union defines the type that identifies where a data packet is * stored in the store. It comprises of a raw part to read it as raw value and * a structured part to use it in pool-like stores. */ union store_address_t { + /** * Default Constructor, initializing to INVALID_ADDRESS */ - store_address_t():raw(0xFFFFFFFF){} + store_address_t(): raw(storeId::INVALID_STORE_ADDRESS){} /** * Constructor to create an address object using the raw address * @@ -28,7 +33,7 @@ union store_address_t { * @param packetIndex */ store_address_t(uint16_t poolIndex, uint16_t packetIndex): - pool_index(poolIndex),packet_index(packetIndex){} + poolIndex(poolIndex), packetIndex(packetIndex){} /** * A structure with two elements to access the store address pool-like. */ @@ -36,11 +41,11 @@ union store_address_t { /** * The index in which pool the packet lies. */ - uint16_t pool_index; + uint16_t poolIndex; /** * The position in the chosen pool. */ - uint16_t packet_index; + uint16_t packetIndex; }; /** * Alternative access to the raw value. From 67e33918e0fb07fe3dd6afbfda9eb5bbfcd044fe Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 15 Oct 2020 13:44:09 +0200 Subject: [PATCH 426/653] event manager uses refactored pool now --- events/EventManager.cpp | 18 +++++++++--------- events/EventManager.h | 10 +++++++--- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/events/EventManager.cpp b/events/EventManager.cpp index e71951e3..57bda13f 100644 --- a/events/EventManager.cpp +++ b/events/EventManager.cpp @@ -1,23 +1,23 @@ #include "EventManager.h" -#include "EventMessage.h" #include "../serviceinterface/ServiceInterfaceStream.h" #include "../ipc/QueueFactory.h" #include "../ipc/MutexFactory.h" -const uint16_t EventManager::POOL_SIZES[N_POOLS] = { - sizeof(EventMatchTree::Node), sizeof(EventIdRangeMatcher), - sizeof(ReporterRangeMatcher) }; // 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. -// SHOULDDO: Shouldn't this be in the config folder and passed via ctor? -const uint16_t EventManager::N_ELEMENTS[N_POOLS] = { 240, 120, 120 }; +// This should be configurable.. +const LocalPool::LocalPoolConfig EventManager::poolConfig = { + {240, sizeof(EventMatchTree::Node)}, + {120, sizeof(EventIdRangeMatcher)}, + {120, sizeof(ReporterRangeMatcher)} +}; EventManager::EventManager(object_id_t setObjectId) : SystemObject(setObjectId), - factoryBackend(0, POOL_SIZES, N_ELEMENTS, false, true) { + factoryBackend(0, poolConfig, false, true) { mutex = MutexFactory::instance()->createMutex(); eventReportQueue = QueueFactory::instance()->createMessageQueue( MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE); @@ -109,13 +109,13 @@ ReturnValue_t EventManager::unsubscribeFromEventRange(MessageQueueId_t listener, return result; } -#ifdef DEBUG +#if FSFW_DEBUG_OUTPUT == 1 void EventManager::printEvent(EventMessage* message) { const char *string = 0; switch (message->getSeverity()) { case SEVERITY::INFO: -#ifdef DEBUG_INFO_EVENT +#if DEBUG_INFO_EVENT == 1 string = translateObject(message->getReporter()); sif::info << "EVENT: "; if (string != 0) { diff --git a/events/EventManager.h b/events/EventManager.h index 2602aeb2..fe35d9d3 100644 --- a/events/EventManager.h +++ b/events/EventManager.h @@ -8,9 +8,11 @@ #include "../tasks/ExecutableObjectIF.h" #include "../ipc/MessageQueueIF.h" #include "../ipc/MutexIF.h" +#include + #include -#ifdef DEBUG +#if FSFW_DEBUG_OUTPUT == 1 // forward declaration, should be implemented by mission extern const char* translateObject(object_id_t object); extern const char* translateEvents(Event event); @@ -49,13 +51,15 @@ protected: MutexIF* mutex = nullptr; static const uint8_t N_POOLS = 3; - LocalPool factoryBackend; + LocalPool factoryBackend; + static const LocalPool::LocalPoolConfig poolConfig; + static const uint16_t POOL_SIZES[N_POOLS]; static const uint16_t N_ELEMENTS[N_POOLS]; void notifyListeners(EventMessage *message); -#ifdef DEBUG +#if FSFW_DEBUG_OUTPUT == 1 void printEvent(EventMessage *message); #endif From 7d358483dd1f684609d52f144e64aa02e1e82425 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 15 Oct 2020 13:44:59 +0200 Subject: [PATCH 427/653] added back config includes --- storagemanager/LocalPool.cpp | 1 + storagemanager/PoolManager.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/storagemanager/LocalPool.cpp b/storagemanager/LocalPool.cpp index 8e5f4d48..48934a0c 100644 --- a/storagemanager/LocalPool.cpp +++ b/storagemanager/LocalPool.cpp @@ -1,4 +1,5 @@ #include "LocalPool.h" +#include #include LocalPool::LocalPool(object_id_t setObjectId, const LocalPoolConfig& poolConfig, diff --git a/storagemanager/PoolManager.cpp b/storagemanager/PoolManager.cpp index 9c801a3d..85376b28 100644 --- a/storagemanager/PoolManager.cpp +++ b/storagemanager/PoolManager.cpp @@ -1,4 +1,5 @@ #include "PoolManager.h" +#include PoolManager::PoolManager(object_id_t setObjectId, const LocalPoolConfig& localPoolConfig): From bd2f8b3e8ce09c6328519a9047d7144ff7932d37 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 15 Oct 2020 13:45:47 +0200 Subject: [PATCH 428/653] packet matcher uses refactored pool now --- tmtcpacket/packetmatcher/PacketMatchTree.cpp | 28 ++++++++++++-------- tmtcpacket/packetmatcher/PacketMatchTree.h | 3 ++- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/tmtcpacket/packetmatcher/PacketMatchTree.cpp b/tmtcpacket/packetmatcher/PacketMatchTree.cpp index a4579657..ac72b3e7 100644 --- a/tmtcpacket/packetmatcher/PacketMatchTree.cpp +++ b/tmtcpacket/packetmatcher/PacketMatchTree.cpp @@ -3,19 +3,30 @@ #include "ServiceMatcher.h" #include "SubserviceMatcher.h" +// This should be configurable.. +const LocalPool::LocalPoolConfig PacketMatchTree::poolConfig = { + {10, sizeof(ServiceMatcher)}, + {20, sizeof(SubServiceMatcher)}, + {2, sizeof(ApidMatcher)}, + {40, sizeof(PacketMatchTree::Node)} +}; + PacketMatchTree::PacketMatchTree(Node* root) : - MatchTree(root, 2), factoryBackend(0, POOL_SIZES, - N_ELEMENTS, false, true), factory(&factoryBackend) { + MatchTree(root, 2), + factoryBackend(0, poolConfig, false, true), + factory(&factoryBackend) { } PacketMatchTree::PacketMatchTree(iterator root) : - MatchTree(root.element, 2), factoryBackend(0, - POOL_SIZES, N_ELEMENTS, false, true), factory(&factoryBackend) { + MatchTree(root.element, 2), + factoryBackend(0, poolConfig, false, true), + factory(&factoryBackend) { } PacketMatchTree::PacketMatchTree() : - MatchTree((Node*) NULL, 2), factoryBackend(0, - POOL_SIZES, N_ELEMENTS, false, true), factory(&factoryBackend) { + MatchTree((Node*) NULL, 2), + factoryBackend(0, poolConfig, false, true), + factory(&factoryBackend) { } PacketMatchTree::~PacketMatchTree() { @@ -172,11 +183,6 @@ ReturnValue_t PacketMatchTree::initialize() { return factoryBackend.initialize(); } -const uint16_t PacketMatchTree::POOL_SIZES[N_POOLS] = { sizeof(ServiceMatcher), - sizeof(SubServiceMatcher), sizeof(ApidMatcher), - sizeof(PacketMatchTree::Node) }; -//Maximum number of types and subtypes to filter should be more than sufficient. -const uint16_t PacketMatchTree::N_ELEMENTS[N_POOLS] = { 10, 20, 2, 40 }; ReturnValue_t PacketMatchTree::changeMatch(bool addToMatch, uint16_t apid, uint8_t type, uint8_t subtype) { diff --git a/tmtcpacket/packetmatcher/PacketMatchTree.h b/tmtcpacket/packetmatcher/PacketMatchTree.h index 86fb087e..54fc856c 100644 --- a/tmtcpacket/packetmatcher/PacketMatchTree.h +++ b/tmtcpacket/packetmatcher/PacketMatchTree.h @@ -23,8 +23,9 @@ protected: ReturnValue_t cleanUpElement(iterator position); private: static const uint8_t N_POOLS = 4; - LocalPool factoryBackend; + LocalPool factoryBackend; PlacementFactory factory; + static const LocalPool::LocalPoolConfig poolConfig; static const uint16_t POOL_SIZES[N_POOLS]; static const uint16_t N_ELEMENTS[N_POOLS]; template From 8cea7b05db428b80bc90abd1ae5440bd9e9562a7 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 20 Oct 2020 14:42:58 +0200 Subject: [PATCH 429/653] include improvement --- osal/FreeRTOS/QueueFactory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osal/FreeRTOS/QueueFactory.cpp b/osal/FreeRTOS/QueueFactory.cpp index 5b3c73dc..ed29e10c 100644 --- a/osal/FreeRTOS/QueueFactory.cpp +++ b/osal/FreeRTOS/QueueFactory.cpp @@ -1,8 +1,8 @@ +#include "MessageQueue.h" + #include "../../ipc/MessageQueueSenderIF.h" #include "../../ipc/QueueFactory.h" -#include "../../osal/FreeRTOS/MessageQueue.h" - QueueFactory* QueueFactory::factoryInstance = nullptr; From fa67f8246206e7b5a76a235a14d2b63f888e4fe0 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 20 Oct 2020 15:04:28 +0200 Subject: [PATCH 430/653] structure improved --- tcdistribution/PUSDistributor.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tcdistribution/PUSDistributor.cpp b/tcdistribution/PUSDistributor.cpp index 63d1dcde..d964202f 100644 --- a/tcdistribution/PUSDistributor.cpp +++ b/tcdistribution/PUSDistributor.cpp @@ -95,16 +95,19 @@ uint16_t PUSDistributor::getIdentifier() { } ReturnValue_t PUSDistributor::initialize() { + currentPacket = new TcPacketStored(); + if(currentPacket == nullptr) { + // Should not happen, memory allocation failed! + return ObjectManagerIF::CHILD_INIT_FAILED; + } + CCSDSDistributorIF* ccsdsDistributor = objectManager->get(packetSource); - currentPacket = new TcPacketStored(); if (ccsdsDistributor == nullptr) { sif::error << "PUSDistributor::initialize: Packet source invalid." << " Make sure it exists and implements CCSDSDistributorIF!" << std::endl; return RETURN_FAILED; } - else { - return ccsdsDistributor->registerApplication(this); - } + return ccsdsDistributor->registerApplication(this); } From 7821cc2870e4e74a6bd37542127bb9b637b7a6e4 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 20 Oct 2020 16:52:34 +0200 Subject: [PATCH 431/653] submodule added --- .gitmodules | 3 +++ unittest | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 unittest diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..a24e36e5 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "unittest"] + path = unittest + url = https://egit.irs.uni-stuttgart.de/fsfw/fsfw_tests.git diff --git a/unittest b/unittest new file mode 160000 index 00000000..b99077c7 --- /dev/null +++ b/unittest @@ -0,0 +1 @@ +Subproject commit b99077c7f94916b677f45a97ccb80613c0932f47 From c677358343551340d57396a6259fe026c3cf662b Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 20 Oct 2020 17:06:09 +0200 Subject: [PATCH 432/653] include adaption --- events/Event.h | 2 +- returnvalues/HasReturnvaluesIF.h | 2 +- unittest | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/events/Event.h b/events/Event.h index e22c9db1..f8410f32 100644 --- a/events/Event.h +++ b/events/Event.h @@ -4,7 +4,7 @@ #include #include "fwSubsystemIdRanges.h" //could be move to more suitable location -#include +#include typedef uint16_t EventId_t; typedef uint8_t EventSeverity_t; diff --git a/returnvalues/HasReturnvaluesIF.h b/returnvalues/HasReturnvaluesIF.h index 5fef91dd..3d3e3208 100644 --- a/returnvalues/HasReturnvaluesIF.h +++ b/returnvalues/HasReturnvaluesIF.h @@ -2,7 +2,7 @@ #define FRAMEWORK_RETURNVALUES_HASRETURNVALUESIF_H_ #include "FwClassIds.h" -#include +#include #include #define MAKE_RETURN_CODE( number ) ((INTERFACE_ID << 8) + (number)) diff --git a/unittest b/unittest index b99077c7..76cbb97a 160000 --- a/unittest +++ b/unittest @@ -1 +1 @@ -Subproject commit b99077c7f94916b677f45a97ccb80613c0932f47 +Subproject commit 76cbb97ae410a7440d2b71eaecd4eea4a5cccaf3 From 865ea3386c91ed976166995cb4fd70cf2434dda7 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 20 Oct 2020 17:11:23 +0200 Subject: [PATCH 433/653] unittest now contained directly --- .gitmodules | 3 - unittest | 1 - unittest/Makefile-FSFW-Tests | 415 + unittest/README.md | 121 + unittest/catch2/LICENSE.txt | 23 + unittest/catch2/catch.hpp | 17618 ++++++++++++++++ unittest/catch2/catch_reporter_automake.hpp | 62 + unittest/catch2/catch_reporter_sonarqube.hpp | 181 + unittest/catch2/catch_reporter_tap.hpp | 253 + unittest/catch2/catch_reporter_teamcity.hpp | 219 + unittest/config/FSFWConfig.h | 32 + unittest/config/TestsConfig.h | 8 + unittest/config/cdatapool/dataPoolInit.cpp | 48 + unittest/config/cdatapool/dataPoolInit.h | 29 + unittest/config/config.mk | 15 + unittest/config/devices/logicalAddresses.cpp | 11 + unittest/config/devices/logicalAddresses.h | 15 + unittest/config/devices/powerSwitcherList.cpp | 10 + unittest/config/devices/powerSwitcherList.h | 22 + unittest/config/events/translateEvents.cpp | 20 + unittest/config/events/translateEvents.h | 16 + unittest/config/ipc/MissionMessageTypes.cpp | 11 + unittest/config/ipc/MissionMessageTypes.h | 22 + unittest/config/objects/Factory.cpp | 37 + unittest/config/objects/Factory.h | 16 + unittest/config/objects/systemObjectList.h | 30 + unittest/config/objects/translateObjects.cpp | 242 + unittest/config/objects/translateObjects.h | 16 + .../PollingSequenceFactory.cpp | 31 + .../pollingsequence/PollingSequenceFactory.h | 31 + unittest/config/returnvalues/classIds.h | 28 + unittest/config/tmtc/PusIds.hpp | 29 + unittest/config/tmtc/apid.h | 19 + unittest/config/tmtc/pusIds.h | 23 + unittest/config/tmtc/subsystemIdRanges.h | 34 + unittest/config/tmtc/tmTcSize.h | 10 + unittest/config/version.h | 7 + unittest/core/CatchDefinitions.cpp | 11 + unittest/core/CatchDefinitions.h | 19 + unittest/core/CatchRunner.cpp | 27 + unittest/core/CatchSetup.cpp | 41 + unittest/core/core.mk | 3 + unittest/core/printChar.cpp | 10 + unittest/core/printChar.h | 8 + unittest/internal/InternalUnitTester.cpp | 26 + unittest/internal/InternalUnitTester.h | 29 + unittest/internal/UnittDefinitions.cpp | 7 + unittest/internal/UnittDefinitions.h | 33 + unittest/internal/osal/IntTestMq.cpp | 52 + unittest/internal/osal/IntTestMq.h | 9 + unittest/internal/osal/IntTestMutex.cpp | 41 + unittest/internal/osal/IntTestMutex.h | 10 + unittest/internal/osal/IntTestSemaphore.cpp | 159 + unittest/internal/osal/IntTestSemaphore.h | 15 + .../serialize/IntTestSerialization.cpp | 230 + .../internal/serialize/IntTestSerialization.h | 15 + unittest/lcov.sh | 3 + unittest/tests/action/TestActionHelper.cpp | 105 + unittest/tests/action/TestActionHelper.h | 131 + unittest/tests/container/RingBufferTest.cpp | 327 + unittest/tests/container/TestArrayList.cpp | 90 + unittest/tests/container/TestDynamicFifo.cpp | 149 + unittest/tests/container/TestFifo.cpp | 138 + .../tests/container/TestFixedArrayList.cpp | 41 + unittest/tests/container/TestFixedMap.cpp | 172 + .../container/TestFixedOrderedMultimap.cpp | 203 + .../tests/container/TestPlacementFactory.cpp | 45 + unittest/tests/osal/TestMessageQueue.cpp | 40 + unittest/tests/osal/TestSemaphore.cpp | 46 + .../serialize/TestSerialBufferAdapter.cpp | 143 + .../serialize/TestSerialLinkedPacket.cpp | 73 + .../tests/serialize/TestSerialLinkedPacket.h | 61 + .../tests/serialize/TestSerialization.cpp | 129 + .../tests/storagemanager/TestNewAccessor.cpp | 161 + unittest/tests/storagemanager/TestPool.cpp | 105 + unittest/tests/tests.mk | 8 + unittest/testtemplate/TestTemplate.cpp | 31 + unittest/unlockRealtime.sh | 34 + 78 files changed, 22684 insertions(+), 4 deletions(-) delete mode 160000 unittest create mode 100644 unittest/Makefile-FSFW-Tests create mode 100644 unittest/README.md create mode 100644 unittest/catch2/LICENSE.txt create mode 100644 unittest/catch2/catch.hpp create mode 100644 unittest/catch2/catch_reporter_automake.hpp create mode 100644 unittest/catch2/catch_reporter_sonarqube.hpp create mode 100644 unittest/catch2/catch_reporter_tap.hpp create mode 100644 unittest/catch2/catch_reporter_teamcity.hpp create mode 100644 unittest/config/FSFWConfig.h create mode 100644 unittest/config/TestsConfig.h create mode 100644 unittest/config/cdatapool/dataPoolInit.cpp create mode 100644 unittest/config/cdatapool/dataPoolInit.h create mode 100644 unittest/config/config.mk create mode 100644 unittest/config/devices/logicalAddresses.cpp create mode 100644 unittest/config/devices/logicalAddresses.h create mode 100644 unittest/config/devices/powerSwitcherList.cpp create mode 100644 unittest/config/devices/powerSwitcherList.h create mode 100644 unittest/config/events/translateEvents.cpp create mode 100644 unittest/config/events/translateEvents.h create mode 100644 unittest/config/ipc/MissionMessageTypes.cpp create mode 100644 unittest/config/ipc/MissionMessageTypes.h create mode 100644 unittest/config/objects/Factory.cpp create mode 100644 unittest/config/objects/Factory.h create mode 100644 unittest/config/objects/systemObjectList.h create mode 100644 unittest/config/objects/translateObjects.cpp create mode 100644 unittest/config/objects/translateObjects.h create mode 100644 unittest/config/pollingsequence/PollingSequenceFactory.cpp create mode 100644 unittest/config/pollingsequence/PollingSequenceFactory.h create mode 100644 unittest/config/returnvalues/classIds.h create mode 100644 unittest/config/tmtc/PusIds.hpp create mode 100644 unittest/config/tmtc/apid.h create mode 100644 unittest/config/tmtc/pusIds.h create mode 100644 unittest/config/tmtc/subsystemIdRanges.h create mode 100644 unittest/config/tmtc/tmTcSize.h create mode 100644 unittest/config/version.h create mode 100644 unittest/core/CatchDefinitions.cpp create mode 100644 unittest/core/CatchDefinitions.h create mode 100644 unittest/core/CatchRunner.cpp create mode 100644 unittest/core/CatchSetup.cpp create mode 100644 unittest/core/core.mk create mode 100644 unittest/core/printChar.cpp create mode 100644 unittest/core/printChar.h create mode 100644 unittest/internal/InternalUnitTester.cpp create mode 100644 unittest/internal/InternalUnitTester.h create mode 100644 unittest/internal/UnittDefinitions.cpp create mode 100644 unittest/internal/UnittDefinitions.h create mode 100644 unittest/internal/osal/IntTestMq.cpp create mode 100644 unittest/internal/osal/IntTestMq.h create mode 100644 unittest/internal/osal/IntTestMutex.cpp create mode 100644 unittest/internal/osal/IntTestMutex.h create mode 100644 unittest/internal/osal/IntTestSemaphore.cpp create mode 100644 unittest/internal/osal/IntTestSemaphore.h create mode 100644 unittest/internal/serialize/IntTestSerialization.cpp create mode 100644 unittest/internal/serialize/IntTestSerialization.h create mode 100644 unittest/lcov.sh create mode 100644 unittest/tests/action/TestActionHelper.cpp create mode 100644 unittest/tests/action/TestActionHelper.h create mode 100644 unittest/tests/container/RingBufferTest.cpp create mode 100644 unittest/tests/container/TestArrayList.cpp create mode 100644 unittest/tests/container/TestDynamicFifo.cpp create mode 100644 unittest/tests/container/TestFifo.cpp create mode 100644 unittest/tests/container/TestFixedArrayList.cpp create mode 100644 unittest/tests/container/TestFixedMap.cpp create mode 100644 unittest/tests/container/TestFixedOrderedMultimap.cpp create mode 100644 unittest/tests/container/TestPlacementFactory.cpp create mode 100644 unittest/tests/osal/TestMessageQueue.cpp create mode 100644 unittest/tests/osal/TestSemaphore.cpp create mode 100644 unittest/tests/serialize/TestSerialBufferAdapter.cpp create mode 100644 unittest/tests/serialize/TestSerialLinkedPacket.cpp create mode 100644 unittest/tests/serialize/TestSerialLinkedPacket.h create mode 100644 unittest/tests/serialize/TestSerialization.cpp create mode 100644 unittest/tests/storagemanager/TestNewAccessor.cpp create mode 100644 unittest/tests/storagemanager/TestPool.cpp create mode 100644 unittest/tests/tests.mk create mode 100644 unittest/testtemplate/TestTemplate.cpp create mode 100644 unittest/unlockRealtime.sh diff --git a/.gitmodules b/.gitmodules index a24e36e5..e69de29b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "unittest"] - path = unittest - url = https://egit.irs.uni-stuttgart.de/fsfw/fsfw_tests.git diff --git a/unittest b/unittest deleted file mode 160000 index 76cbb97a..00000000 --- a/unittest +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 76cbb97ae410a7440d2b71eaecd4eea4a5cccaf3 diff --git a/unittest/Makefile-FSFW-Tests b/unittest/Makefile-FSFW-Tests new file mode 100644 index 00000000..d43a6edc --- /dev/null +++ b/unittest/Makefile-FSFW-Tests @@ -0,0 +1,415 @@ +#------------------------------------------------------------------------------- +# Makefile for FSFW Test +#------------------------------------------------------------------------------- +# User-modifiable options +#------------------------------------------------------------------------------- +# Fundamentals on the build process of C/C++ Software: +# https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html + +# Make documentation: https://www.gnu.org/software/make/manual/make.pdf +# Online: https://www.gnu.org/software/make/manual/make.html +# General rules: http://make.mad-scientist.net/papers/rules-of-makefiles/#rule3 +SHELL = /bin/sh + +# Chip & board used for compilation +# (can be overriden by adding CHIP=chip and BOARD=board to the command-line) +# Unit Test can only be run on host machine for now (Linux) +FRAMEWORK_PATH = fsfw +FILE_ROOT = $(FRAMEWORK_PATH)/unittest +BOARD = unittest +LINUX = 1 +OS_FSFW = linux +CUSTOM_DEFINES += -D$(OS_FSFW) + +# Copied from stackoverflow, can be used to differentiate between Windows +# and Linux +ifeq ($(OS),Windows_NT) + CUSTOM_DEFINES += -DWIN32 + ifeq ($(PROCESSOR_ARCHITEW6432),AMD64) + CUSTOM_DEFINES += -DAMD64 + else + ifeq ($(PROCESSOR_ARCHITECTURE),AMD64) + CUSTOM_DEFINES += -DAMD64 + endif + ifeq ($(PROCESSOR_ARCHITECTURE),x86) + CUSTOM_DEFINES += -DIA32 + endif + endif +else + UNAME_S := $(shell uname -s) + ifeq ($(UNAME_S),Linux) + DETECTED_OS = LINUX + CUSTOM_DEFINES += -DLINUX + endif + ifeq ($(UNAME_S),Darwin) + CUSTOM_DEFINES += -DOSX + endif + UNAME_P := $(shell uname -p) + ifeq ($(UNAME_P),x86_64) + CUSTOM_DEFINES += -DAMD64 + endif + ifneq ($(filter %86,$(UNAME_P)),) + CUSTOM_DEFINES += -DIA32 + endif + ifneq ($(filter arm%,$(UNAME_P)),) + CUSTOM_DEFINES += -DARM + endif +endif + +UNIT_TEST = 1 +# General folder paths +CONFIG_PATH = $(FILE_ROOT)/config +UNIT_TEST_PATH = $(FILE_ROOT)/tests +CORE_PATH = $(FILE_ROOT)/core + +# Output file basename +BASENAME = fsfw +BINARY_NAME := $(BASENAME)-$(BOARD) +# Output files will be put in this directory inside +OUTPUT_FOLDER = $(OS) + +# Optimization level. Optimized for debugging. +OPTIMIZATION = -O0 + +# Default debug output. Optimized for debugging. +DEBUG_LEVEL = -g3 + +ifdef GCOV +CUSTOM_DEFINES += -DGCOV +endif + + +# Output directories +BUILDPATH = _bin +DEPENDPATH = _dep +OBJECTPATH = _obj + +ifeq ($(MAKECMDGOALS),mission) +BUILD_FOLDER = mission +else +BUILD_FOLDER = devel +endif + +DEPENDDIR = $(DEPENDPATH)/$(OUTPUT_FOLDER)/$(BUILD_FOLDER) +OBJDIR = $(OBJECTPATH)/$(OUTPUT_FOLDER)/$(BUILD_FOLDER) +BINDIR = $(BUILDPATH) + +CLEANDEP = $(DEPENDPATH)/$(OUTPUT_FOLDER) +CLEANOBJ = $(OBJECTPATH)/$(OUTPUT_FOLDER) +CLEANBIN = $(BUILDPATH) +#------------------------------------------------------------------------------- +# Tools and Includes +#------------------------------------------------------------------------------- + +# Tool suffix when cross-compiling +CROSS_COMPILE = + +# C Compiler +CC = $(CROSS_COMPILE)gcc + +# C++ compiler +CXX = $(CROSS_COMPILE)g++ + +# Additional Tools +SIZE = $(CROSS_COMPILE)size +STRIP = $(CROSS_COMPILE)strip +CP = $(CROSS_COMPILE)objcopy + +HEXCOPY = $(CP) -O ihex +BINCOPY = $(CP) -O binary +# files to be compiled, will be filled in by include makefiles +# := assignment is neccessary so we get all paths right +# https://www.gnu.org/software/make/manual/html_node/Flavors.html +CSRC := +CXXSRC := +ASRC := +INCLUDES := + +# Directories where $(directoryname).mk files should be included from +SUBDIRS := $(FRAMEWORK_PATH) $(TEST_PATH) $(UNIT_TEST_PATH) $(CONFIG_PATH) \ + $(CORE_PATH) + + +I_INCLUDES += $(addprefix -I, $(INCLUDES)) + +# This is a hack from http://make.mad-scientist.net/the-eval-function/ +# +# The problem is, that included makefiles should be aware of their relative path +# but not need to guess or hardcode it. So we set $(CURRENTPATH) for them. If +# we do this globally and the included makefiles want to include other makefiles as +# well, they would overwrite $(CURRENTPATH), screwing the include after them. +# +# By using a for-loop with an eval'd macro, we can generate the code to include all +# sub-makefiles (with the correct $(CURRENTPATH) set) before actually evaluating +# (and by this possibly changing $(CURRENTPATH)) them. +# +# This works recursively, if an included makefile wants to include, it can safely set +# $(SUBDIRS) (which has already been evaluated here) and do +# "$(foreach S,$(SUBDIRS),$(eval $(INCLUDE_FILE)))" +# $(SUBDIRS) must be relative to the project root, so to include subdir foo, set +# $(SUBDIRS) = $(CURRENTPATH)/foo. +define INCLUDE_FILE +CURRENTPATH := $S +include $(S)/$(notdir $S).mk +endef +$(foreach S,$(SUBDIRS),$(eval $(INCLUDE_FILE))) + +INCLUDES += $(FILE_ROOT) +INCLUDES += $(FILE_ROOT)/catch2/ + +#------------------------------------------------------------------------------- +# Source Files +#------------------------------------------------------------------------------- + +# All source files which are not includes by the .mk files are added here +# Please ensure that no files are included by both .mk file and here ! + +# if a target is not listed in the current directory, +# make searches in the directories specified with VPATH + +# All C Sources included by .mk files are assigned here +# Add the objects to sources so dependency handling works +C_OBJECTS += $(CSRC:.c=.o) + +# Objects built from Assembly source files +ASM_OBJECTS = $(ASRC:.S=.o) + +# Objects built from C++ source files +CXX_OBJECTS += $(CXXSRC:.cpp=.o) + +#------------------------------------------------------------------------------- +# Build Configuration + Output +#------------------------------------------------------------------------------- + +TARGET = Debug build. +DEBUG_MESSAGE = Off +OPTIMIZATION_MESSAGE = Off + +# Define Messages +MSG_INFO = Software: Hosted unittest \(Catch2\) for the FSFW. +MSG_OPTIMIZATION = Optimization: $(OPTIMIZATION), $(OPTIMIZATION_MESSAGE) +MSG_TARGET = Target Build: $(TARGET) +MSG_DEBUG = Debug level: $(DEBUG_LEVEL), FSFW Debugging: $(DEBUG_MESSAGE) + +MSG_LINKING = Linking: +MSG_COMPILING = Compiling: +MSG_ASSEMBLING = Assembling: +MSG_DEPENDENCY = Collecting dependencies for: +MSG_BINARY = Generate binary: + +# See https://stackoverflow.com/questions/6687630/how-to-remove-unused-c-c-symbols-with-gcc-and-ld +# Used to throw away unused code. Reduces code size significantly ! +# -Wl,--gc-sections: needs to be passed to the linker to throw aways unused code +ifdef KEEP_UNUSED_CODE +PROTOTYPE_OPTIMIZATION = +UNUSED_CODE_REMOVAL = +else +PROTOTYPE_OPTIMIZATION = -ffunction-sections -fdata-sections +UNUSED_CODE_REMOVAL = -Wl,--gc-sections +# Link time optimization +# See https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html for reference +# Link time is larger and size of object files can not be retrieved +# but resulting binary is smaller. Could be used in mission/deployment build +# Requires -ffunction-section in linker call +LINK_TIME_OPTIMIZATION = -flto +OPTIMIZATION += $(PROTOTYPE_OPTIMIZATION) +endif + +# Dependency Flags +# These flags tell the compiler to build dependencies +# See: https://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html +# Using following guide: http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#combine +DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPENDDIR)/$*.d + +# Flags for the compiler call +# - std: Which C++ version to use. Common versions: c++11, c++14 and c++17 +# - Wall: enable all warnings +# - Wextra: enable extra warnings +# - g: defines debug level +# - fmessage-length: to control the formatting algorithm for diagnostic messages; +# =0 means no line-wrapping is done; each error message appears on a single line +# - fno-exceptions: stops generating extra code needed to propagate exceptions, +# which can produce significant data size overhead +CUSTOM_DEFINES += -DUNIT_TEST +WARNING_FLAGS = -Wall -Wshadow=local -Wextra -Wimplicit-fallthrough=1 \ + -Wno-unused-parameter + +CXXDEFINES := $(CUSTOM_DEFINES) +CFLAGS += +CXXFLAGS += -I. $(DEBUG_LEVEL) $(WARNING_FLAGS) $(DEPFLAGS) -fmessage-length=0 $(OPTIMIZATION)\ + $(I_INCLUDES) $(CXXDEFINES) +CPPFLAGS += -std=c++11 + +# Flags for the linker call +# LINK_INCLUDES specify the path to used libraries and the linker script +# LINK_LIBRARIES: Link real time support +LDFLAGS := $(DEBUG_LEVEL) $(UNUSED_CODE_REMOVAL) $(OPTIMIZATION) -pthread +LINK_INCLUDES := +LINK_LIBRARIES := + +ifdef LINUX +LINK_LIBRARIES += -lrt +endif + +ifeq ($(OS),Windows_NT) +LINK_LIBRARIES += -lwsock32 -lws2_32 +LDFLASGS += -fuse-ld=lld +endif + +# Gnu Coverage Tools Flags +ifdef GCOV +GCOV_CXXFLAGS = -fprofile-arcs -ftest-coverage --coverage -fno-inline \ + -fno-inline-small-functions -fno-default-inline +CXXFLAGS += $(GCOV_CXXFLAGS) +GCOV_LINKER_LIBS = -lgcov -fprofile-arcs -ftest-coverage +LINK_LIBRARIES += $(GCOV_LINKER_LIBS) +endif + +# $(info $${CXXFLAGS} is [${CXXFLAGS}]) + +#------------------------------------------------------------------------------- +# Rules +#------------------------------------------------------------------------------- +# the call function assigns parameters to temporary variables +# https://www.gnu.org/software/make/manual/make.html#Call-Function +# $(1) = Memory names +# Rules are called for each memory type +# Two Expansion Symbols $$ are to escape the dollar sign for eval. +# See: http://make.mad-scientist.net/the-eval-function/ + +default: all + +# Cleans all files +hardclean: + -rm -rf $(BUILDPATH) + -rm -rf $(OBJECTPATH) + -rm -rf $(DEPENDPATH) + +# Only clean files for current build +clean: + -rm -rf $(CLEANOBJ) + -rm -rf $(CLEANBIN) + -rm -rf $(CLEANDEP) + +# Only clean binaries. Useful for changing the binary type when object files +# are already compiled so complete rebuild is not necessary +cleanbin: + -rm -rf $(CLEANBIN) + +# In this section, the binaries are built for all selected memories +# notestfw: all +all: executable + +# Build target configuration +release: OPTIMIZATION = -Os $(PROTOTYPE_OPTIMIZATION) $(LINK_TIME_OPTIMIZATION) +release: LINK_TIME_OPTIMIZATION = -flto +release: TARGET = Mission build. +release: OPTIMIZATION_MESSAGE = On with Link Time Optimization + +debug: CXXDEFINES += -DDEBUG +debug: TARGET = Debug +debug: DEBUG_MESSAGE = On + +ifndef KEEP_UNUSED_CODE +debug release: OPTIMIZATION_MESSAGE += , no unused code removal +endif + +debug release notestfw: executable + +executable: $(BINDIR)/$(BINARY_NAME).elf + @echo + @echo $(MSG_INFO) + @echo $(MSG_TARGET) + @echo $(MSG_OPTIMIZATION) + @echo $(MSG_DEBUG) + +C_OBJECTS_PREFIXED = $(addprefix $(OBJDIR)/, $(C_OBJECTS)) +CXX_OBJECTS_PREFIXED = $(addprefix $(OBJDIR)/, $(CXX_OBJECTS)) +ASM_OBJECTS_PREFIXED = $(addprefix $(OBJDIR)/, $(ASM_OBJECTS)) +ALL_OBJECTS = $(ASM_OBJECTS_PREFIXED) $(C_OBJECTS_PREFIXED) \ + $(CXX_OBJECTS_PREFIXED) + +# Useful for debugging the Makefile +# Also see: https://www.oreilly.com/openbook/make3/book/ch12.pdf +# $(info $${ALL_OBJECTS} is [${ALL_OBJECTS}]) +# $(info $${CXXSRC} is [${CXXSRC}]) + +# Automatic variables are used here extensively. Some of them +# are escaped($$) to suppress immediate evaluation. The most important ones are: +# $@: Name of Target (left side of rule) +# $<: Name of the first prerequisite (right side of rule) +# @^: List of all prerequisite, omitting duplicates +# @D: Directory and file-within-directory part of $@ + +# Generates binary and displays all build properties +# -p with mkdir ignores error and creates directory when needed. + +# SHOW_DETAILS = 1 + + +# Link with required libraries: HAL (Hardware Abstraction Layer) and +# HCC (File System Library) +$(BINDIR)/$(BINARY_NAME).elf: $(ALL_OBJECTS) + @echo + @echo $(MSG_LINKING) Target $@ + @mkdir -p $(@D) +ifdef SHOW_DETAILS + $(CXX) $(LDFLAGS) $(LINK_INCLUDES) -o $@ $^ $(LINK_LIBRARIES) +else + @$(CXX) $(LDFLAGS) $(LINK_INCLUDES) -o $@ $^ $(LINK_LIBRARIES) +endif +ifeq ($(BUILD_FOLDER), mission) +# With Link Time Optimization, section size is not available + $(SIZE) $@ +else + $(SIZE) $^ $@ +endif + +$(BINDIR)/$(BINARY_NAME).hex: $(BINDIR)/$(BINARY_NAME).elf + @echo + @echo $(MSG_BINARY) + @mkdir -p $(@D) + $(HEXCOPY) $< $@ + +# Build new objects for changed dependencies. +$(OBJDIR)/%.o: %.cpp +$(OBJDIR)/%.o: %.cpp $(DEPENDDIR)/%.d | $(DEPENDDIR) + @echo + @echo $(MSG_COMPILING) $< + @mkdir -p $(@D) +ifdef SHOW_DETAILS + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $< +else + @$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $< +endif + +$(OBJDIR)/%.o: %.c +$(OBJDIR)/%.o: %.c $(DEPENDDIR)/%.d | $(DEPENDDIR) + @echo + @echo $(MSG_COMPILING) $< + @mkdir -p $(@D) +ifdef SHOW_DETAILS + $(CC) $(CXXFLAGS) $(CFLAGS) -c -o $@ $< +else + @$(CC) $(CXXFLAGS) $(CFLAGS) -c -o $@ $< +endif + +#------------------------------------------------------------------------------- +# Dependency Handling +#------------------------------------------------------------------------------- + +# Dependency Handling according to following guide: +# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/ +$(DEPENDDIR): + @mkdir -p $(@D) +DEPENDENCY_RELATIVE = $(CSRC:.c=.d) $(CXXSRC:.cpp=.d) +# This is the list of all dependencies +DEPFILES = $(addprefix $(DEPENDDIR)/, $(DEPENDENCY_RELATIVE)) +# Create subdirectories for dependencies +$(DEPFILES): + @mkdir -p $(@D) +# Include all dependencies +include $(wildcard $(DEPFILES)) + +# .PHONY tells make that these targets aren't files +.PHONY: clean release debug all hardclean cleanbin diff --git a/unittest/README.md b/unittest/README.md new file mode 100644 index 00000000..091dd3cb --- /dev/null +++ b/unittest/README.md @@ -0,0 +1,121 @@ +## FSFW Testing +This repository contains testing and unit testing components. + +[Catch2](https://github.com/catchorg/Catch2) has been used as a framework, +and these unit tests can only be run on a linux host machine. +The makefile with default settings creates the unit test binary which can be +run in the terminal or in eclipse. + +### Instructions +Basic steps: + +1. Clone this branch + ```sh + git clone https://egit.irs.uni-stuttgart.de/fsfw/fsfw_tests.git + ``` + +2. Inititate the framework submodule (need to only be done once) + ```sh + git submodule init + git submodule sync + git submodule update + ``` + +2. Run the makefile With + + ```sh + make all -j + ``` + This will build the debug version of the unit tests. + The release version can be built with the target `release` + +4. Run the binary located in the \_bin folder in the terminal or in eclipse. + + ```sh + _bin/.elf [--success] + ``` + The success parameter is optional. Leaving it out ommits the success messages. + +5. To clear the binary, object and dependency folder, run + + ```sh + make clean + ``` + +Please note that on most UNIX environments (e.g. Ubuntu), the real time functionalities used by the UNIX pthread module are restricted, which will lead to permission errors when creating these tasks. + +To solve this issues, try following steps: + +1. Edit the /etc/security/limits.conf + file and add following lines at the end (worked on Ubuntu 19.10): + ```sh + hard rtprio 99 + soft rtprio 99 + ``` + Then restart the computer.
+ The soft limit can also be set in the console with `ulimit -Sr` if the hard + limit has been increased, + but it is recommended to add it to the file as well for convenience. + If adding the second line is not desired for security reasons, + the soft limit needs to be set for each session. If using an IDE like eclipse + in that case, the IDE needs to be started from the console after setting + the soft limit higher there. +2. Run the shell script inside the linux folder (worked on Ubuntu 18.04) + ```sh + ./unlockRealtime + ``` + This script executes the `setcap` command on bash and on the binaries. + It also increases the soft real time limit of the current shell instance + to the maximum. If running the script before executing the binary does + not help, try the following step. + +### Eclipse CDT settings + +The default eclipse terminal has issues displaying the colors used +when running the unit test binary by catch2. To fix this issue, +install the ANSI Escape In Console package from the eclipse marketplace. + +### GCOV integration + +GCOV has been integrated as a code coverage tool. +It can be enabled by adding `GCOV=1` to the build process as an additional argument. +Coverage data will be provided in form of .gcno and .gcda files. +These can be displayed in eclipse by looking +for a .gcno or .gcda file in the \_obj folder, double-clicking it +and picking the right source-binary. This will generate +information about which lines of a file have run, provided it is open in +eclipse. + +### LCOV integration + +The files generated by GCOV can also be processed by the tool LCOV. +On ubuntu, the tool can be installed with the following command: + +```sh +sudo apt-get install lcov +```` + +After that, the tool can be run by building the unit tests with `GCOV=1`, +running them at least one time and then executing the `lcov.sh` script. + +### Adding unit tests + +The catch unit tests are located in unittest/testfw. To add new unit tests, +add them to the UnitTestCatch.cpp file or add a new source file which +includes catch.hpp. + +For writing basics tests, the [assertion documentation](https://github.com/catchorg/Catch2/blob/master/docs/assertions.md#top) +or the existing examples are a good guideliens. +For more advanced tests, refer to the [catch2 documentation](https://github.com/catchorg/Catch2/blob/master/docs/Readme.md#top). + +### Compile without test framework +Alternatively, the unit tests can also be run internally without +a framework. This can be used to perform unit tests on the real hardware. +To do this, run +```sh +make -j notestfw +``` +This will instruct the makefile to exclude the test framework main.cpp +and include our own. This will also create a binary which can be used +outside the host machine (a Makefile adaptions might be neccessary +if another OS than linux is required) diff --git a/unittest/catch2/LICENSE.txt b/unittest/catch2/LICENSE.txt new file mode 100644 index 00000000..36b7cd93 --- /dev/null +++ b/unittest/catch2/LICENSE.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/unittest/catch2/catch.hpp b/unittest/catch2/catch.hpp new file mode 100644 index 00000000..51618b38 --- /dev/null +++ b/unittest/catch2/catch.hpp @@ -0,0 +1,17618 @@ +/* + * Catch v2.11.3 + * Generated: 2020-03-19 13:44:21.042491 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +// start catch.hpp + + +#define CATCH_VERSION_MAJOR 2 +#define CATCH_VERSION_MINOR 11 +#define CATCH_VERSION_PATCH 3 + +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif + +// start catch_suppress_warnings.h + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(push) +# pragma warning(disable: 161 1682) +# else // __ICC +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +# endif +#elif defined __GNUC__ + // Because REQUIREs trigger GCC's -Wparentheses, and because still + // supported version of g++ have only buggy support for _Pragmas, + // Wparentheses have to be suppressed globally. +# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details + +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic ignored "-Wpadded" +#endif +// end catch_suppress_warnings.h +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +# define CATCH_CONFIG_ALL_PARTS +#endif + +// In the impl file, we want to have access to all parts of the headers +// Can also be used to sanely support PCHs +#if defined(CATCH_CONFIG_ALL_PARTS) +# define CATCH_CONFIG_EXTERNAL_INTERFACES +# if defined(CATCH_CONFIG_DISABLE_MATCHERS) +# undef CATCH_CONFIG_DISABLE_MATCHERS +# endif +# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +# endif +#endif + +#if !defined(CATCH_CONFIG_IMPL_ONLY) +// start catch_platform.h + +#ifdef __APPLE__ +# include +# if TARGET_OS_OSX == 1 +# define CATCH_PLATFORM_MAC +# elif TARGET_OS_IPHONE == 1 +# define CATCH_PLATFORM_IPHONE +# endif + +#elif defined(linux) || defined(__linux) || defined(__linux__) +# define CATCH_PLATFORM_LINUX + +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) +# define CATCH_PLATFORM_WINDOWS +#endif + +// end catch_platform.h + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// start catch_user_interfaces.h + +namespace Catch { + unsigned int rngSeed(); +} + +// end catch_user_interfaces.h +// start catch_tag_alias_autoregistrar.h + +// start catch_common.h + +// start catch_compiler_capabilities.h + +// Detect a number of compiler features - by compiler +// The following features are defined: +// +// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? +// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? +// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? +// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +#ifdef __cplusplus + +# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) +# define CATCH_CPP14_OR_GREATER +# endif + +# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +# define CATCH_CPP17_OR_GREATER +# endif + +#endif + +#if defined(CATCH_CPP17_OR_GREATER) +# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#endif + +// We have to avoid both ICC and Clang, because they try to mask themselves +// as gcc, and we want only GCC in this block +#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) + +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) + +#endif + +#if defined(__clang__) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) + +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) + +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ + _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") + +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) + +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Assume that non-Windows platforms support posix signals by default +#if !defined(CATCH_PLATFORM_WINDOWS) + #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS +#endif + +//////////////////////////////////////////////////////////////////////////////// +// We know some environments not to support full POSIX signals +#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) + #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +#endif + +#ifdef __OS400__ +# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +# define CATCH_CONFIG_COLOUR_NONE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Android somehow still does not support std::to_string +#if defined(__ANDROID__) +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Not all Windows environments support SEH properly +#if defined(__MINGW32__) +# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH +#endif + +//////////////////////////////////////////////////////////////////////////////// +// PS4 +#if defined(__ORBIS__) +# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Cygwin +#ifdef __CYGWIN__ + +// Required for some versions of Cygwin to declare gettimeofday +// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin +# define _BSD_SOURCE +// some versions of cygwin (most) do not support std::to_string. Use the libstd check. +// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 +# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ + && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) + +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING + +# endif +#endif // __CYGWIN__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#if defined(_MSC_VER) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) + +# if _MSC_VER >= 1900 // Visual Studio 2015 or newer +# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +# endif + +// Universal Windows platform does not support SEH +// Or console colours (or console at all...) +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +# define CATCH_CONFIG_COLOUR_NONE +# else +# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +# endif + +// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ +// _MSVC_TRADITIONAL == 0 means new conformant preprocessor +// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor +# if !defined(__clang__) // Handle Clang masquerading for msvc +# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) +# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +# endif // MSVC_TRADITIONAL +# endif // __clang__ + +#endif // _MSC_VER + +#if defined(_REENTRANT) || defined(_MSC_VER) +// Enable async processing, as -pthread is specified or no additional linking is required +# define CATCH_INTERNAL_CONFIG_USE_ASYNC +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// Check if we are compiled with -fno-exceptions or equivalent +#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) +# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED +#endif + +//////////////////////////////////////////////////////////////////////////////// +// DJGPP +#ifdef __DJGPP__ +# define CATCH_INTERNAL_CONFIG_NO_WCHAR +#endif // __DJGPP__ + +//////////////////////////////////////////////////////////////////////////////// +// Embarcadero C++Build +#if defined(__BORLANDC__) + #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN +#endif + +//////////////////////////////////////////////////////////////////////////////// + +// Use of __COUNTER__ is suppressed during code analysis in +// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly +// handled by it. +// Otherwise all supported compilers support COUNTER macro, +// but user still might want to turn it off +#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) + #define CATCH_INTERNAL_CONFIG_COUNTER +#endif + +//////////////////////////////////////////////////////////////////////////////// + +// RTX is a special version of Windows that is real time. +// This means that it is detected as Windows, but does not provide +// the same set of capabilities as real Windows does. +#if defined(UNDER_RTSS) || defined(RTX64_BUILD) + #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH + #define CATCH_INTERNAL_CONFIG_NO_ASYNC + #define CATCH_CONFIG_COLOUR_NONE +#endif + +#if !defined(_GLIBCXX_USE_C99_MATH_TR1) +#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Various stdlib support checks that require __has_include +#if defined(__has_include) + // Check if string_view is available and usable + #if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW + #endif + + // Check if optional is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if byte is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_BYTE + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if variant is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # if defined(__clang__) && (__clang_major__ < 8) + // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 + // fix should be in clang 8, workaround in libstdc++ 8.2 + # include + # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # define CATCH_CONFIG_NO_CPP17_VARIANT + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__clang__) && (__clang_major__ < 8) + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) +#endif // defined(__has_include) + +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) +# define CATCH_CONFIG_COUNTER +#endif +#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) +# define CATCH_CONFIG_WINDOWS_SEH +#endif +// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. +#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) +# define CATCH_CONFIG_POSIX_SIGNALS +#endif +// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. +#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) +# define CATCH_CONFIG_WCHAR +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) +# define CATCH_CONFIG_CPP11_TO_STRING +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) +# define CATCH_CONFIG_CPP17_OPTIONAL +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) +# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) +# define CATCH_CONFIG_CPP17_STRING_VIEW +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) +# define CATCH_CONFIG_CPP17_VARIANT +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) +# define CATCH_CONFIG_CPP17_BYTE +#endif + +#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) +# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE) +# define CATCH_CONFIG_NEW_CAPTURE +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +# define CATCH_CONFIG_DISABLE_EXCEPTIONS +#endif + +#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) +# define CATCH_CONFIG_POLYFILL_ISNAN +#endif + +#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) +# define CATCH_CONFIG_USE_ASYNC +#endif + +#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) +# define CATCH_CONFIG_ANDROID_LOGWRITE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) +# define CATCH_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Even if we do not think the compiler has that warning, we still have +// to provide a macro that can be used by the code. +#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS +#endif + +// The goal of this macro is to avoid evaluation of the arguments, but +// still have the compiler warn on problems inside... +#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) +#endif + +#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#elif defined(__clang__) && (__clang_major__ < 5) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +#define CATCH_TRY if ((true)) +#define CATCH_CATCH_ALL if ((false)) +#define CATCH_CATCH_ANON(type) if ((false)) +#else +#define CATCH_TRY try +#define CATCH_CATCH_ALL catch (...) +#define CATCH_CATCH_ANON(type) catch (type) +#endif + +#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) +#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#endif + +// end catch_compiler_capabilities.h +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#ifdef CATCH_CONFIG_COUNTER +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#else +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#endif + +#include +#include +#include + +// We need a dummy global operator<< so we can bring it into Catch namespace later +struct Catch_global_namespace_dummy {}; +std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); + +namespace Catch { + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + + class NonCopyable { + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; + + protected: + NonCopyable(); + virtual ~NonCopyable(); + }; + + struct SourceLineInfo { + + SourceLineInfo() = delete; + SourceLineInfo( char const* _file, std::size_t _line ) noexcept + : file( _file ), + line( _line ) + {} + + SourceLineInfo( SourceLineInfo const& other ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo( SourceLineInfo&& ) noexcept = default; + SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; + + bool empty() const noexcept { return file[0] == '\0'; } + bool operator == ( SourceLineInfo const& other ) const noexcept; + bool operator < ( SourceLineInfo const& other ) const noexcept; + + char const* file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // Bring in operator<< from global namespace into Catch namespace + // This is necessary because the overload of operator<< above makes + // lookup stop at namespace Catch + using ::operator<<; + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() const; + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO \ + ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) + +// end catch_common.h +namespace Catch { + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION + +// end catch_tag_alias_autoregistrar.h +// start catch_test_registry.h + +// start catch_interfaces_testcase.h + +#include + +namespace Catch { + + class TestSpec; + + struct ITestInvoker { + virtual void invoke () const = 0; + virtual ~ITestInvoker(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; + }; + + bool isThrowSafe( TestCase const& testCase, IConfig const& config ); + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + +} + +// end catch_interfaces_testcase.h +// start catch_stringref.h + +#include +#include +#include +#include + +namespace Catch { + + /// A non-owning string class (similar to the forthcoming std::string_view) + /// Note that, because a StringRef may be a substring of another string, + /// it may not be null terminated. + class StringRef { + public: + using size_type = std::size_t; + using const_iterator = const char*; + + private: + static constexpr char const* const s_empty = ""; + + char const* m_start = s_empty; + size_type m_size = 0; + + public: // construction + constexpr StringRef() noexcept = default; + + StringRef( char const* rawChars ) noexcept; + + constexpr StringRef( char const* rawChars, size_type size ) noexcept + : m_start( rawChars ), + m_size( size ) + {} + + StringRef( std::string const& stdString ) noexcept + : m_start( stdString.c_str() ), + m_size( stdString.size() ) + {} + + explicit operator std::string() const { + return std::string(m_start, m_size); + } + + public: // operators + auto operator == ( StringRef const& other ) const noexcept -> bool; + auto operator != (StringRef const& other) const noexcept -> bool { + return !(*this == other); + } + + auto operator[] ( size_type index ) const noexcept -> char { + assert(index < m_size); + return m_start[index]; + } + + public: // named queries + constexpr auto empty() const noexcept -> bool { + return m_size == 0; + } + constexpr auto size() const noexcept -> size_type { + return m_size; + } + + // Returns the current start pointer. If the StringRef is not + // null-terminated, throws std::domain_exception + auto c_str() const -> char const*; + + public: // substrings and searches + // Returns a substring of [start, start + length). + // If start + length > size(), then the substring is [start, size()). + // If start > size(), then the substring is empty. + auto substr( size_type start, size_type length ) const noexcept -> StringRef; + + // Returns the current start pointer. May not be null-terminated. + auto data() const noexcept -> char const*; + + constexpr auto isNullTerminated() const noexcept -> bool { + return m_start[m_size] == '\0'; + } + + public: // iterators + constexpr const_iterator begin() const { return m_start; } + constexpr const_iterator end() const { return m_start + m_size; } + }; + + auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; + auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; + + constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { + return StringRef( rawChars, size ); + } +} // namespace Catch + +constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { + return Catch::StringRef( rawChars, size ); +} + +// end catch_stringref.h +// start catch_preprocessor.hpp + + +#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ +#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) + +#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ +// MSVC needs more evaluations +#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) +#else +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) +#endif + +#define CATCH_REC_END(...) +#define CATCH_REC_OUT + +#define CATCH_EMPTY() +#define CATCH_DEFER(id) id CATCH_EMPTY() + +#define CATCH_REC_GET_END2() 0, CATCH_REC_END +#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 +#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 +#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT +#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) +#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) + +#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) + +#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) + +// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, +// and passes userdata as the first parameter to each invocation, +// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) +#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) +#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ +#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ +#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) +#else +// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) +#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) +#endif + +#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ +#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) + +#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) + +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper()) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) +#else +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper())) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) +#endif + +#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ + CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) + +#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) +#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) +#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) +#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) +#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) +#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) +#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _4, _5, _6) +#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) +#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) +#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) +#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) + +#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N + +#define INTERNAL_CATCH_TYPE_GEN\ + template struct TypeList {};\ + template\ + constexpr auto get_wrapper() noexcept -> TypeList { return {}; }\ + template class...> struct TemplateTypeList{};\ + template class...Cs>\ + constexpr auto get_wrapper() noexcept -> TemplateTypeList { return {}; }\ + template\ + struct append;\ + template\ + struct rewrap;\ + template class, typename...>\ + struct create;\ + template class, typename>\ + struct convert;\ + \ + template \ + struct append { using type = T; };\ + template< template class L1, typename...E1, template class L2, typename...E2, typename...Rest>\ + struct append, L2, Rest...> { using type = typename append, Rest...>::type; };\ + template< template class L1, typename...E1, typename...Rest>\ + struct append, TypeList, Rest...> { using type = L1; };\ + \ + template< template class Container, template class List, typename...elems>\ + struct rewrap, List> { using type = TypeList>; };\ + template< template class Container, template class List, class...Elems, typename...Elements>\ + struct rewrap, List, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\ + \ + template