Merge remote-tracking branch 'eive/mueller/added-missing-devicehandlers' into mueller/master

This commit is contained in:
2021-09-26 22:28:26 +02:00
25 changed files with 2046 additions and 169 deletions

View File

@ -17,7 +17,15 @@
#cmakedefine FSFW_ADD_SGP4_PROPAGATOR
#ifndef FSFW_HAL_L3GD20_GYRO_DEBUG
#define FSFW_HAL_L3GD20_GYRO_DEBUG 0
#define FSFW_HAL_L3GD20_GYRO_DEBUG 0
#endif /* FSFW_HAL_L3GD20_GYRO_DEBUG */
#ifndef FSFW_HAL_RM3100_MGM_DEBUG
#define FSFW_HAL_RM3100_MGM_DEBUG 0
#endif /* FSFW_HAL_RM3100_MGM_DEBUG */
#ifndef FSFW_HAL_LIS3MDL_MGM_DEBUG
#define FSFW_HAL_LIS3MDL_MGM_DEBUG 0
#endif /* FSFW_HAL_LIS3MDL_MGM_DEBUG */
#endif /* FSFW_FSFW_H_ */

View File

@ -4,7 +4,7 @@
const char* const FSFW_VERSION_NAME = "ASTP";
#define FSFW_VERSION 1
#define FSFW_SUBVERSION 3
#define FSFW_SUBVERSION 2
#define FSFW_REVISION 0
#endif /* FSFW_VERSION_H_ */

View File

@ -32,6 +32,17 @@ ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) {
setQueueToUse(queueToUse_);
}
if(queueToUse == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ActionHelper::initialize: No queue set" << std::endl;
#else
sif::printWarning("ActionHelper::initialize: No queue set\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -461,7 +461,7 @@ size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId){
return iter->second.replyLen;
}else{
return 0;
}
}
}
ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply,
@ -469,7 +469,7 @@ ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceRep
auto replyIter = deviceReplyMap.find(deviceReply);
if (replyIter == deviceReplyMap.end()) {
triggerEvent(INVALID_DEVICE_COMMAND, deviceReply);
return RETURN_FAILED;
return COMMAND_NOT_SUPPORTED;
} else {
DeviceReplyInfo *info = &(replyIter->second);
if (maxDelayCycles != 0) {
@ -481,6 +481,25 @@ ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceRep
}
}
ReturnValue_t DeviceHandlerBase::updatePeriodicReply(bool enable, DeviceCommandId_t deviceReply) {
auto replyIter = deviceReplyMap.find(deviceReply);
if (replyIter == deviceReplyMap.end()) {
triggerEvent(INVALID_DEVICE_COMMAND, deviceReply);
return COMMAND_NOT_SUPPORTED;
} else {
DeviceReplyInfo *info = &(replyIter->second);
if(not info->periodic) {
return COMMAND_NOT_SUPPORTED;
}
if(enable) {
info->delayCycles = info->maxDelayCycles;
}
else {
info->delayCycles = 0;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t DeviceHandlerBase::setReplyDataset(DeviceCommandId_t replyId,
LocalPoolDataSetBase *dataSet) {
@ -593,15 +612,15 @@ void DeviceHandlerBase::replyToReply(const DeviceCommandId_t command, DeviceRepl
}
DeviceCommandInfo* info = &replyInfo.command->second;
if (info == nullptr){
printWarningOrError(sif::OutputTypes::OUT_ERROR,
"replyToReply", HasReturnvaluesIF::RETURN_FAILED,
"Command pointer not found");
return;
printWarningOrError(sif::OutputTypes::OUT_ERROR,
"replyToReply", HasReturnvaluesIF::RETURN_FAILED,
"Command pointer not found");
return;
}
if (info->expectedReplies > 0){
// Check before to avoid underflow
info->expectedReplies--;
// Check before to avoid underflow
info->expectedReplies--;
}
// Check if more replies are expected. If so, do nothing.
if (info->expectedReplies == 0) {
@ -1336,10 +1355,20 @@ void DeviceHandlerBase::buildInternalCommand(void) {
DeviceCommandMap::iterator iter = deviceCommandMap.find(
deviceCommandId);
if (iter == deviceCommandMap.end()) {
#if FSFW_VERBOSE_LEVEL >= 1
char output[36];
sprintf(output, "Command 0x%08x unknown",
static_cast<unsigned int>(deviceCommandId));
// so we can track misconfigurations
printWarningOrError(sif::OutputTypes::OUT_WARNING,
"buildInternalCommand",
COMMAND_NOT_SUPPORTED,
output);
#endif
result = COMMAND_NOT_SUPPORTED;
}
else if (iter->second.isExecuting) {
#if FSFW_DISABLE_PRINTOUT == 0
#if FSFW_VERBOSE_LEVEL >= 1
char output[36];
sprintf(output, "Command 0x%08x is executing",
static_cast<unsigned int>(deviceCommandId));
@ -1550,7 +1579,7 @@ LocalDataPoolManager* DeviceHandlerBase::getHkManagerHandle() {
return &poolManager;
}
MessageQueueId_t DeviceHandlerBase::getCommanderId(DeviceCommandId_t replyId) const {
MessageQueueId_t DeviceHandlerBase::getCommanderQueueId(DeviceCommandId_t replyId) const {
auto commandIter = deviceCommandMap.find(replyId);
if(commandIter == deviceCommandMap.end()) {
return MessageQueueIF::NO_QUEUE;

View File

@ -6,22 +6,22 @@
#include "DeviceHandlerFailureIsolation.h"
#include "DeviceHandlerThermalSet.h"
#include "../serviceinterface/ServiceInterface.h"
#include "../serviceinterface/serviceInterfaceDefintions.h"
#include "../objectmanager/SystemObject.h"
#include "../tasks/ExecutableObjectIF.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../action/HasActionsIF.h"
#include "../datapool/PoolVariableIF.h"
#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 "../datapoollocal/HasLocalDataPoolIF.h"
#include "../datapoollocal/LocalDataPoolManager.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/serviceinterface/serviceInterfaceDefintions.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "fsfw/action/HasActionsIF.h"
#include "fsfw/datapool/PoolVariableIF.h"
#include "fsfw/modes/HasModesIF.h"
#include "fsfw/power/PowerSwitchIF.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/tasks/PeriodicTaskIF.h"
#include "fsfw/action/ActionHelper.h"
#include "fsfw/health/HealthHelper.h"
#include "fsfw/parameters/ParameterHelper.h"
#include "fsfw/datapoollocal/HasLocalDataPoolIF.h"
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include <map>
@ -399,7 +399,7 @@ protected:
*/
virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) = 0;
MessageQueueId_t getCommanderId(DeviceCommandId_t replyId) const;
MessageQueueId_t getCommanderQueueId(DeviceCommandId_t replyId) const;
/**
* Helper function to get pending command. This is useful for devices
* like SPI sensors to identify the last sent command.
@ -449,7 +449,9 @@ protected:
* @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)
* by the device repeatedly without request) or not. Default is aperiodic (0).
* Please note that periodic replies are disabled by default. You can enable them with
* #updatePeriodicReply
* @return - @c RETURN_OK when the command was successfully inserted,
* - @c RETURN_FAILED else.
*/
@ -464,7 +466,9 @@ protected:
* @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)
* by the device repeatedly without request) or not. Default is aperiodic (0).
* Please note that periodic replies are disabled by default. You can enable them with
* #updatePeriodicReply
* @return - @c RETURN_OK when the command was successfully inserted,
* - @c RETURN_FAILED else.
*/
@ -480,6 +484,14 @@ protected:
*/
ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand);
/**
* Enables a periodic reply for a given command. It sets to delay cycles to the specified
* maximum delay cycles for a given reply ID if enabled or to 0 if disabled.
* @param enable Specify whether to enable or disable a given periodic reply
* @return
*/
ReturnValue_t updatePeriodicReply(bool enable, DeviceCommandId_t deviceReply);
/**
* @brief This function returns the reply length of the next reply to read.
*
@ -493,16 +505,14 @@ protected:
virtual size_t getNextReplyLength(DeviceCommandId_t deviceCommand);
/**
* @brief This is a helper method to facilitate updating entries
* in the reply map.
* @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 delayCycles The current number of delay cycles to wait. As stated in
* #fillCommandAndReplyMap, 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).
* 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.

View File

@ -1,32 +1,13 @@
#include "fsfw/globalfunctions/DleEncoder.h"
DleEncoder::DleEncoder(bool escapeStxEtx, bool escapeCr): escapeStxEtx(escapeStxEtx),
escapeCr(escapeCr) {}
DleEncoder::DleEncoder(bool escapeStxEtx, bool escapeCr):
escapeStxEtx(escapeStxEtx), escapeCr(escapeCr) {}
DleEncoder::~DleEncoder() {}
ReturnValue_t DleEncoder::encode(const uint8_t* sourceStream,
size_t sourceLen, uint8_t* destStream, size_t maxDestLen,
size_t* encodedLen, bool addStxEtx) {
size_t minAllowedLen = 0;
if(escapeStxEtx) {
minAllowedLen = 2;
}
else {
minAllowedLen = 1;
}
if(maxDestLen < minAllowedLen) {
return STREAM_TOO_SHORT;
}
if (addStxEtx) {
if(not escapeStxEtx) {
destStream[0] = DLE_CHAR;
}
destStream[0] = STX_CHAR;
}
size_t sourceLen, uint8_t* destStream, size_t maxDestLen,
size_t* encodedLen, bool addStxEtx) {
if(escapeStxEtx) {
return encodeStreamEscaped(sourceStream, sourceLen,
destStream, maxDestLen, encodedLen, addStxEtx);
@ -41,9 +22,15 @@ ReturnValue_t DleEncoder::encode(const uint8_t* sourceStream,
ReturnValue_t DleEncoder::encodeStreamEscaped(const uint8_t *sourceStream, size_t sourceLen,
uint8_t *destStream, size_t maxDestLen, size_t *encodedLen,
bool addStxEtx) {
size_t encodedIndex = 1;
size_t encodedIndex = 0;
size_t sourceIndex = 0;
uint8_t nextByte = 0;
if(addStxEtx) {
if(maxDestLen < 1) {
return STREAM_TOO_SHORT;
}
destStream[encodedIndex++] = STX_CHAR;
}
while (encodedIndex < maxDestLen and sourceIndex < sourceLen) {
nextByte = sourceStream[sourceIndex];
// STX, ETX and CR characters in the stream need to be escaped with DLE
@ -83,8 +70,11 @@ ReturnValue_t DleEncoder::encodeStreamEscaped(const uint8_t *sourceStream, size_
++sourceIndex;
}
if (sourceIndex == sourceLen and encodedIndex < maxDestLen) {
if (sourceIndex == sourceLen) {
if (addStxEtx) {
if(encodedIndex + 1 >= maxDestLen) {
return STREAM_TOO_SHORT;
}
destStream[encodedIndex] = ETX_CHAR;
++encodedIndex;
}
@ -99,9 +89,16 @@ ReturnValue_t DleEncoder::encodeStreamEscaped(const uint8_t *sourceStream, size_
ReturnValue_t DleEncoder::encodeStreamNonEscaped(const uint8_t *sourceStream, size_t sourceLen,
uint8_t *destStream, size_t maxDestLen, size_t *encodedLen,
bool addStxEtx) {
size_t encodedIndex = 1;
size_t encodedIndex = 0;
size_t sourceIndex = 0;
uint8_t nextByte = 0;
if(addStxEtx) {
if(maxDestLen < 2) {
return STREAM_TOO_SHORT;
}
destStream[encodedIndex++] = DLE_CHAR;
destStream[encodedIndex++] = STX_CHAR;
}
while (encodedIndex < maxDestLen and sourceIndex < sourceLen) {
nextByte = sourceStream[sourceIndex];
// DLE characters are simply escaped with DLE.
@ -122,10 +119,13 @@ ReturnValue_t DleEncoder::encodeStreamNonEscaped(const uint8_t *sourceStream, si
++sourceIndex;
}
if (sourceIndex == sourceLen and encodedIndex < maxDestLen) {
if (sourceIndex == sourceLen) {
if (addStxEtx) {
destStream[encodedIndex] = ETX_CHAR;
++encodedIndex;
if(encodedIndex + 2 >= maxDestLen) {
return STREAM_TOO_SHORT;
}
destStream[encodedIndex++] = DLE_CHAR;
destStream[encodedIndex++] = ETX_CHAR;
}
*encodedLen = encodedIndex;
return RETURN_OK;
@ -136,40 +136,45 @@ ReturnValue_t DleEncoder::encodeStreamNonEscaped(const uint8_t *sourceStream, si
}
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;
if(not escapeStxEtx) {
if (*sourceStream != DLE_CHAR) {
return DECODING_ERROR;
}
++encodedIndex;
}
if (sourceStream[encodedIndex] != STX_CHAR) {
return DECODING_ERROR;
}
if(escapeStxEtx) {
return decodeStreamEscaped(sourceStream, sourceStreamLen,
readLen, destStream, maxDestStreamlen, decodedLen);
}
else {
size_t sourceStreamLen, size_t *readLen, uint8_t *destStream,
size_t maxDestStreamlen, size_t *decodedLen) {
if(escapeStxEtx) {
return decodeStreamEscaped(sourceStream, sourceStreamLen,
readLen, destStream, maxDestStreamlen, decodedLen);
}
else {
return decodeStreamNonEscaped(sourceStream, sourceStreamLen,
readLen, destStream, maxDestStreamlen, decodedLen);
}
}
}
ReturnValue_t DleEncoder::decodeStreamEscaped(const uint8_t *sourceStream, size_t sourceStreamLen,
size_t *readLen, uint8_t *destStream,
size_t maxDestStreamlen, size_t *decodedLen) {
// Skip start marker, was already checked
size_t encodedIndex = 1;
size_t encodedIndex = 0;
size_t decodedIndex = 0;
uint8_t nextByte;
while ((encodedIndex < sourceStreamLen) && (decodedIndex < maxDestStreamlen)
&& (sourceStream[encodedIndex] != ETX_CHAR)
&& (sourceStream[encodedIndex] != STX_CHAR)) {
//init to 0 so that we can just return in the first checks (which do not consume anything from
//the source stream)
*readLen = 0;
if(maxDestStreamlen < 1) {
return STREAM_TOO_SHORT;
}
if (sourceStream[encodedIndex++] != STX_CHAR) {
return DECODING_ERROR;
}
while ((encodedIndex < sourceStreamLen)
and (decodedIndex < maxDestStreamlen)
and (sourceStream[encodedIndex] != ETX_CHAR)
and (sourceStream[encodedIndex] != STX_CHAR)) {
if (sourceStream[encodedIndex] == DLE_CHAR) {
if(encodedIndex + 1 >= sourceStreamLen) {
//reached the end of the sourceStream
*readLen = sourceStreamLen;
return DECODING_ERROR;
}
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.
@ -186,6 +191,8 @@ ReturnValue_t DleEncoder::decodeStreamEscaped(const uint8_t *sourceStream, size_
destStream[decodedIndex] = nextByte - 0x40;
}
else {
// Set readLen so user can resume parsing after incorrect data
*readLen = encodedIndex + 2;
return DECODING_ERROR;
}
}
@ -199,8 +206,15 @@ ReturnValue_t DleEncoder::decodeStreamEscaped(const uint8_t *sourceStream, size_
++decodedIndex;
}
if (sourceStream[encodedIndex] != ETX_CHAR) {
*readLen = ++encodedIndex;
return DECODING_ERROR;
if(decodedIndex == maxDestStreamlen) {
//so far we did not find anything wrong here, so let user try again
*readLen = 0;
return STREAM_TOO_SHORT;
}
else {
*readLen = ++encodedIndex;
return DECODING_ERROR;
}
}
else {
*readLen = ++encodedIndex;
@ -212,15 +226,35 @@ ReturnValue_t DleEncoder::decodeStreamEscaped(const uint8_t *sourceStream, size_
ReturnValue_t DleEncoder::decodeStreamNonEscaped(const uint8_t *sourceStream,
size_t sourceStreamLen, size_t *readLen, uint8_t *destStream,
size_t maxDestStreamlen, size_t *decodedLen) {
// Skip start marker, was already checked
size_t encodedIndex = 2;
size_t encodedIndex = 0;
size_t decodedIndex = 0;
uint8_t nextByte;
//init to 0 so that we can just return in the first checks (which do not consume anything from
//the source stream)
*readLen = 0;
if(maxDestStreamlen < 2) {
return STREAM_TOO_SHORT;
}
if (sourceStream[encodedIndex++] != DLE_CHAR) {
return DECODING_ERROR;
}
if (sourceStream[encodedIndex++] != STX_CHAR) {
*readLen = 1;
return DECODING_ERROR;
}
while ((encodedIndex < sourceStreamLen) && (decodedIndex < maxDestStreamlen)) {
if (sourceStream[encodedIndex] == DLE_CHAR) {
if(encodedIndex + 1 >= sourceStreamLen) {
*readLen = encodedIndex;
return DECODING_ERROR;
}
nextByte = sourceStream[encodedIndex + 1];
if(nextByte == STX_CHAR) {
*readLen = ++encodedIndex;
// Set readLen so the DLE/STX char combination is preserved. Could be start of
// another frame
*readLen = encodedIndex;
return DECODING_ERROR;
}
else if(nextByte == DLE_CHAR) {
@ -235,6 +269,10 @@ ReturnValue_t DleEncoder::decodeStreamNonEscaped(const uint8_t *sourceStream,
*decodedLen = decodedIndex;
return RETURN_OK;
}
else {
*readLen = encodedIndex;
return DECODING_ERROR;
}
}
else {
destStream[decodedIndex] = sourceStream[encodedIndex];
@ -242,6 +280,17 @@ ReturnValue_t DleEncoder::decodeStreamNonEscaped(const uint8_t *sourceStream,
++encodedIndex;
++decodedIndex;
}
return DECODING_ERROR;
if(decodedIndex == maxDestStreamlen) {
//so far we did not find anything wrong here, so let user try again
*readLen = 0;
return STREAM_TOO_SHORT;
} else {
*readLen = encodedIndex;
return DECODING_ERROR;
}
}
void DleEncoder::setEscapeMode(bool escapeStxEtx) {
this->escapeStxEtx = escapeStxEtx;
}

View File

@ -37,6 +37,9 @@ public:
* @param escapeCr In escaped mode, escape all CR occurrences as well
*/
DleEncoder(bool escapeStxEtx = true, bool escapeCr = false);
void setEscapeMode(bool escapeStxEtx);
virtual ~DleEncoder();
static constexpr uint8_t INTERFACE_ID = CLASS_ID::DLE_ENCODER;
@ -68,6 +71,8 @@ public:
* @param addStxEtx Adding STX start marker and ETX end marker can be omitted,
* if they are added manually
* @return
* - RETURN_OK for successful encoding operation
* - STREAM_TOO_SHORT if the destination stream is too short
*/
ReturnValue_t encode(const uint8_t *sourceStream, size_t sourceLen,
uint8_t *destStream, size_t maxDestLen, size_t *encodedLen,
@ -82,6 +87,9 @@ public:
* @param maxDestStreamlen
* @param decodedLen
* @return
* - RETURN_OK for successful decode operation
* - DECODE_ERROR if the source stream is invalid
* - STREAM_TOO_SHORT if the destination stream is too short
*/
ReturnValue_t decode(const uint8_t *sourceStream,
size_t sourceStreamLen, size_t *readLen, uint8_t *destStream,

View File

@ -13,10 +13,10 @@
/**
* @brief FailureReport class to serialize a failure report
* @brief Subservice 1, 3, 5, 7
* @brief Subservice 2, 4, 6, 8
* @ingroup spacepackets
*/
class FailureReport: public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 1, 3, 5, 7
class FailureReport: public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 2, 4, 6, 8
public:
FailureReport(uint8_t failureSubtype_, uint16_t packetId_,
uint16_t packetSequenceControl_, uint8_t stepNumber_,
@ -108,10 +108,10 @@ private:
};
/**
* @brief Subservices 2, 4, 6, 8
* @brief Subservices 1, 3, 5, 7
* @ingroup spacepackets
*/
class SuccessReport: public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 2, 4, 6, 8
class SuccessReport: public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 1, 3, 5, 7
public:
SuccessReport(uint8_t subtype_, uint16_t packetId_,
uint16_t packetSequenceControl_,uint8_t stepNumber_) :