Merge pull request 'FSFW Update - Parameter Service (PUS 20)' (#365) from mueller/fsfw-update into development

Reviewed-on: fsfw/fsfw#365
This commit is contained in:
Steffen Gaisser 2021-02-09 14:55:54 +01:00
commit 0416aaf3fe
37 changed files with 583 additions and 142 deletions

View File

@ -1286,18 +1286,17 @@ 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) {
result = buildNormalDeviceCommand(&deviceCommandId);
if (result == BUSY) {
// so we can track misconfigurations
printWarningOrError(sif::OutputTypes::OUT_WARNING,
"buildInternalCommand",
HasReturnvaluesIF::RETURN_FAILED,
"Busy.");
result = NOTHING_TO_SEND; //no need to report this
/* So we can track misconfigurations */
printWarningOrError(sif::OutputTypes::OUT_WARNING, "buildInternalCommand",
HasReturnvaluesIF::RETURN_FAILED, "Busy.");
/* No need to report this */
result = NOTHING_TO_SEND;
}
}
else if (mode == MODE_RAW) {
@ -1319,7 +1318,8 @@ void DeviceHandlerBase::buildInternalCommand(void) {
deviceCommandId);
if (iter == deviceCommandMap.end()) {
result = COMMAND_NOT_SUPPORTED;
} else if (iter->second.isExecuting) {
}
else if (iter->second.isExecuting) {
#if FSFW_DISABLE_PRINTOUT == 0
char output[36];
sprintf(output, "Command 0x%08x is executing",
@ -1380,10 +1380,10 @@ void DeviceHandlerBase::doOffActivity() {
}
ReturnValue_t DeviceHandlerBase::getParameter(uint8_t domainId,
uint16_t parameterId, ParameterWrapper* parameterWrapper,
uint8_t uniqueId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) {
ReturnValue_t result = fdirInstance->getParameter(domainId, parameterId,
parameterWrapper, newValues, startAtIndex);
ReturnValue_t result = fdirInstance->getParameter(domainId, uniqueId, parameterWrapper,
newValues, startAtIndex);
if (result != INVALID_DOMAIN_ID) {
return result;
}

View File

@ -216,7 +216,7 @@ public:
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,
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex) override;

View File

@ -209,20 +209,20 @@ void DeviceHandlerFailureIsolation::startRecovery(Event reason) {
}
ReturnValue_t DeviceHandlerFailureIsolation::getParameter(uint8_t domainId,
uint16_t parameterId, ParameterWrapper* parameterWrapper,
uint8_t uniqueId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) {
ReturnValue_t result = strangeReplyCount.getParameter(domainId, parameterId,
ReturnValue_t result = strangeReplyCount.getParameter(domainId, uniqueId,
parameterWrapper, newValues, startAtIndex);
if (result != INVALID_DOMAIN_ID) {
return result;
}
result = missedReplyCount.getParameter(domainId, parameterId,
parameterWrapper, newValues, startAtIndex);
result = missedReplyCount.getParameter(domainId, uniqueId, parameterWrapper, newValues,
startAtIndex);
if (result != INVALID_DOMAIN_ID) {
return result;
}
result = recoveryCounter.getParameter(domainId, parameterId,
parameterWrapper, newValues, startAtIndex);
result = recoveryCounter.getParameter(domainId, uniqueId, parameterWrapper, newValues,
startAtIndex);
if (result != INVALID_DOMAIN_ID) {
return result;
}

View File

@ -17,9 +17,9 @@ public:
ReturnValue_t initialize();
void triggerEvent(Event event, uint32_t parameter1 = 0,
uint32_t parameter2 = 0);bool isFdirActionInProgress();
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
uint16_t startAtIndex);
protected:
FaultCounter strangeReplyCount;

View File

@ -58,14 +58,14 @@ FaultCounter::FaultCounter() :
parameterDomain(0), timer(), faultCount(0), failureThreshold(0) {
}
ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint16_t parameterId,
ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
uint16_t startAtIndex) {
if (domainId != parameterDomain) {
return INVALID_DOMAIN_ID;
}
switch (parameterId) {
switch (uniqueId) {
case 0:
parameterWrapper->set(failureThreshold);
break;

View File

@ -23,7 +23,7 @@ public:
void setFailureThreshold(uint32_t failureThreshold);
void setFaultDecrementTimeMs(uint32_t timeMs);
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);

View File

@ -37,16 +37,16 @@ public:
}
}
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex) {
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
uint16_t startAtIndex) {
ReturnValue_t result = this->MonitorBase<T>::getParameter(domainId,
parameterId, parameterWrapper, newValues, startAtIndex);
uniqueId, parameterWrapper, newValues, startAtIndex);
//We'll reuse the DOMAIN_ID of MonitorReporter, as we know the parameterIds used there.
if (result != this->INVALID_IDENTIFIER_ID) {
return result;
}
switch (parameterId) {
switch (uniqueId) {
case 10:
parameterWrapper->set(this->lowerLimit);
break;

View File

@ -51,13 +51,13 @@ public:
return state;
}
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex) {
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
uint16_t startAtIndex) {
if (domainId != monitorId) {
return INVALID_DOMAIN_ID;
}
switch (parameterId) {
switch (uniqueId) {
case 0:
parameterWrapper->set(this->confirmationLimit);
break;

View File

@ -71,13 +71,13 @@ public:
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex) {
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
uint16_t startAtIndex) {
if (domainId != this->domainId) {
return INVALID_DOMAIN_ID;
}
switch (parameterId) {
switch (uniqueId) {
case 0:
parameterWrapper->set(limit);
break;

View File

@ -14,6 +14,7 @@ enum framework_objects: object_id_t {
PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008,
PUS_SERVICE_9_TIME_MGMT = 0x53000009,
PUS_SERVICE_17_TEST = 0x53000017,
PUS_SERVICE_20_PARAMETERS = 0x53000020,
PUS_SERVICE_200_MODE_MGMT = 0x53000200,
//Generic IDs for IPC, modes, health, events

View File

@ -25,7 +25,8 @@
#else
#ifdef WIN32
#include <Windows.h>
#include <winsock2.h>
#include <windows.h>
#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
#define BYTE_ORDER_SYSTEM LITTLE_ENDIAN
#else

View File

@ -3,7 +3,7 @@
#include <chrono>
#if defined(WIN32)
#include <windows.h>
#include <sysinfoapi.h>
#elif defined(LINUX)
#include <fstream>
#endif
@ -15,35 +15,34 @@ using SystemClock = std::chrono::system_clock;
uint32_t Clock::getTicksPerSecond(void){
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::getTicksPerSecond: not implemented yet" << std::endl;
sif::warning << "Clock::getTicksPerSecond: Not implemented for host OSAL" << std::endl;
#else
sif::printWarning("Clock::getTicksPerSecond: Not implemented for host OSAL\n");
#endif
return 0;
//return CLOCKS_PER_SEC;
//uint32_t ticks = sysconf(_SC_CLK_TCK);
//return ticks;
/* To avoid division by zero */
return 1;
}
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
// do some magic with chrono
/* I don't know why someone would need to set a clock which is probably perfectly fine on a
host system with internet access so this is not implemented for now. */
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::setClock: not implemented yet" << std::endl;
sif::warning << "Clock::setClock: Not implemented for host OSAL" << std::endl;
#else
sif::printWarning("Clock::setClock: Not implemented for host OSAL\n");
#endif
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
/* I don't know why someone would need to set a clock which is probably perfectly fine on a
host system with internet access so this is not implemented for now. */
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl;
sif::warning << "Clock::setClock: Not implemented for host OSAL" << std::endl;
#else
sif::printWarning("Clock::setClock: Not implemented for host OSAL\n");
#endif
return HasReturnvaluesIF::RETURN_FAILED;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::getClock_timeval(timeval* time) {
@ -76,10 +75,11 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
}
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
// do some magic with chrono
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::gerClock_usecs: not implemented yet" << std::endl;
#endif
if(time == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
using namespace std::chrono;
*time = duration_cast<microseconds>(system_clock::now().time_since_epoch()).count();
return HasReturnvaluesIF::RETURN_OK;
}
@ -121,9 +121,9 @@ ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
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.
/* Do some magic with chrono (C++20!) */
/* Right now, the library doesn't have the new features to get the required values yet.
so we work around that for now. */
auto now = SystemClock::now();
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
auto fraction = now - seconds;
@ -138,10 +138,6 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
time->second = timeInfo->tm_sec;
auto usecond = std::chrono::duration_cast<std::chrono::microseconds>(fraction);
time->usecond = usecond.count();
#if FSFW_CPP_OSTREAM_ENABLED == 1
//sif::warning << "Clock::getDateAndTime: not implemented yet" << std::endl;
#endif
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -9,7 +9,7 @@
#include <chrono>
#if defined(WIN32)
#include <windows.h>
#include <processthreadsapi.h>
#elif defined(LINUX)
#include <pthread.h>
#endif

View File

@ -52,9 +52,8 @@ public:
return id;
}
static uint32_t getFullParameterId(uint8_t domainId,
uint8_t uniqueIdentifier, uint16_t linearIndex) {
return (domainId << 24) + (uniqueIdentifier << 16) + linearIndex;
static uint32_t getFullParameterId(uint8_t domainId, uint8_t uniqueId, uint16_t linearIndex) {
return (domainId << 24) + (uniqueId << 16) + linearIndex;
}
virtual ~HasParametersIF() {}
@ -74,9 +73,9 @@ public:
* matrix indexes.
* @return
*/
virtual ReturnValue_t getParameter(uint8_t domainId,
uint16_t uniqueIdentifier, ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex) = 0;
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
uint16_t startAtIndex) = 0;
};
#endif /* FSFW_PARAMETERS_HASPARAMETERSIF_H_ */

View File

@ -90,7 +90,7 @@ ReturnValue_t ParameterHelper::sendParameter(MessageQueueId_t to, uint32_t id,
const ParameterWrapper* description) {
size_t serializedSize = description->getSerializedSize();
uint8_t *storeElement;
uint8_t *storeElement = nullptr;
store_address_t address;
ReturnValue_t result = storage->getFreeElement(&address, serializedSize,

View File

@ -38,7 +38,7 @@ void ParameterMessage::setParameterLoadCommand(CommandMessage* message,
store_address_t ParameterMessage::getParameterLoadCommand(
const CommandMessage *message, ParameterId_t* parameterId, uint8_t *ptc,
uint8_t *pfc, uint8_t *rows, uint8_t *columns) {
*parameterId = message->getParameter2();
*parameterId = message->getParameter();
uint32_t packedParamSettings = message->getParameter3();
*ptc = packedParamSettings >> 24 & 0xff;
*pfc = packedParamSettings >> 16 & 0xff;

View File

@ -1,17 +1,19 @@
#include "ParameterWrapper.h"
#include <FSFWConfig.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
ParameterWrapper::ParameterWrapper() :
pointsToStream(false), type(Type::UNKNOWN_TYPE) {
}
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(nullptr), readonlyData(data) {
}
@ -40,8 +42,8 @@ ReturnValue_t ParameterWrapper::serialize(uint8_t **buffer, size_t *size,
return result;
}
//serialize uses readonlyData, as it is always valid
if (readonlyData == NULL) {
/* serialize uses readonlyData, as it is always valid */
if (readonlyData == nullptr) {
return NOT_SET;
}
switch (type) {
@ -75,7 +77,7 @@ ReturnValue_t ParameterWrapper::serialize(uint8_t **buffer, size_t *size,
result = serializeData<double>(buffer, size, maxSize, streamEndianness);
break;
default:
result = UNKNOW_DATATYPE;
result = UNKNOWN_DATATYPE;
break;
}
return result;
@ -220,22 +222,48 @@ ReturnValue_t ParameterWrapper::set(const uint8_t *stream, size_t streamSize,
ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
uint16_t startWritingAtIndex) {
// TODO: Optional diagnostic output (which can be disabled in FSFWConfig)
// to determined faulty implementations and configuration errors quickly.
if (data == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Called on read-only variable!" << std::endl;
#else
sif::printWarning("ParameterWrapper::copyFrom: Called on read-only variable!\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return READONLY;
}
if (from->readonlyData == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Source not set!" << std::endl;
#else
sif::printWarning("ParameterWrapper::copyFrom: Source not set!\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return SOURCE_NOT_SET;
}
if (type != from->type) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Datatype missmatch!" << std::endl;
#else
sif::printWarning("ParameterWrapper::copyFrom: Datatype missmatch!\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return DATATYPE_MISSMATCH;
}
// The smallest allowed value for rows and columns is one.
if(rows == 0 or columns == 0) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Columns or rows zero!" << std::endl;
#else
sif::printWarning("ParameterWrapper::copyFrom: Columns or rows zero!\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return COLUMN_OR_ROWS_ZERO;
}
@ -289,7 +317,7 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
from->readonlyData, from->rows, from->columns);
break;
default:
result = UNKNOW_DATATYPE;
result = UNKNOWN_DATATYPE;
break;
}
}

View File

@ -8,14 +8,23 @@
#include <cstddef>
/**
* @brief
* @brief This wrapper encapsulates the access to parameters provided by HasParametersIF.
* @details
* This wrapper is used by the ParameterHelper to interface with the on-board parameters
* exposed by the software via the HasParametersIF. A handle of this wrapper is passed
* to the user which then can be used to set or dump the parameters.
*
* The wrapper provides a set of setter functions. The user should call those setter functions,
* supplying an address to the local parameters. The user can also deserialize or
* serialize the parameter data. Please note that this will also serialize and deserialize
* the parameter information field (4 bytes) containing the ECSS PTC, PFC and rows and columns
* number.
*/
class ParameterWrapper: public SerializeIF {
friend class DataPoolParameterWrapper;
public:
static const uint8_t INTERFACE_ID = CLASS_ID::PARAMETER_WRAPPER;
static const ReturnValue_t UNKNOW_DATATYPE = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t UNKNOWN_DATATYPE = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t DATATYPE_MISSMATCH = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t READONLY = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t TOO_BIG = MAKE_RETURN_CODE(0x04);
@ -26,8 +35,7 @@ public:
ParameterWrapper();
ParameterWrapper(Type type, uint8_t rows, uint8_t columns, void *data);
ParameterWrapper(Type type, uint8_t rows, uint8_t columns,
const void *data);
ParameterWrapper(Type type, uint8_t rows, uint8_t columns, const void *data);
virtual ~ParameterWrapper();
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
@ -77,11 +85,23 @@ public:
this->pointsToStream = false;
}
/**
* Setter function for scalar non-const entries
* @tparam T
* @param member
*/
template<typename T>
void set(T& member) {
this->set(&member, 1, 1);
}
/**
* Setter function for scalar const entries.
* TODO: This is confusing, it should not be called set. Maybe we should call all functions
* assign instead?
* @tparam T
* @param readonlyMember
*/
template<typename T>
void set(const T& readonlyMember) {
this->set(&readonlyMember, 1, 1);
@ -89,12 +109,16 @@ public:
template<typename T>
void setVector(T& member) {
this->set(member, sizeof(member)/sizeof(member[0]), 1);
/* For a vector entry, the number of rows will be one
(left to right, top to bottom indexing) */
this->set(member, 1, sizeof(member) / sizeof(member[0]));
}
template<typename T>
void setVector(const T& member) {
this->set(member, 1, sizeof(member)/sizeof(member[0]));
/* For a vector entry, the number of rows will be one
(left to right, top to bottom indexing) */
this->set(member, 1, sizeof(member) / sizeof(member[0]));
}
template<typename T>
void setMatrix(T& member) {

View File

@ -210,15 +210,15 @@ void Fuse::setDataPoolEntriesInvalid() {
set.commit();
}
ReturnValue_t Fuse::getParameter(uint8_t domainId, uint16_t parameterId,
ReturnValue_t Fuse::getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
uint16_t startAtIndex) {
ReturnValue_t result = currentLimit.getParameter(domainId, parameterId,
ReturnValue_t result = currentLimit.getParameter(domainId, uniqueId,
parameterWrapper, newValues, startAtIndex);
if (result != INVALID_DOMAIN_ID) {
return result;
}
result = powerMonitor.getParameter(domainId, parameterId, parameterWrapper,
result = powerMonitor.getParameter(domainId, uniqueId, parameterWrapper,
newValues, startAtIndex);
return result;
}

View File

@ -62,9 +62,9 @@ public:
ReturnValue_t setHealth(HealthState health);
HasHealthIF::HealthState getHealth();
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
uint16_t startAtIndex);
private:
uint8_t oldFuseState;

View File

@ -61,13 +61,13 @@ ReturnValue_t PowerComponent::deSerialize(const uint8_t** buffer, size_t* size,
return SerializeAdapter::deSerialize(&max, buffer, size, streamEndianness);
}
ReturnValue_t PowerComponent::getParameter(uint8_t domainId,
uint16_t parameterId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) {
ReturnValue_t PowerComponent::getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
uint16_t startAtIndex) {
if (domainId != moduleId) {
return INVALID_DOMAIN_ID;
}
switch (parameterId) {
switch (uniqueId) {
case 0:
parameterWrapper->set<>(min);
break;

View File

@ -31,9 +31,9 @@ public:
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
uint16_t startAtIndex);
private:
const object_id_t deviceObjectId = objects::NO_OBJECT;
const uint8_t switchId1;

View File

@ -119,15 +119,15 @@ HasHealthIF::HealthState PowerSensor::getHealth() {
return healthHelper.getHealth();
}
ReturnValue_t PowerSensor::getParameter(uint8_t domainId, uint16_t parameterId,
ReturnValue_t PowerSensor::getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
uint16_t startAtIndex) {
ReturnValue_t result = currentLimit.getParameter(domainId, parameterId,
ReturnValue_t result = currentLimit.getParameter(domainId, uniqueId,
parameterWrapper, newValues, startAtIndex);
if (result != INVALID_DOMAIN_ID) {
return result;
}
result = voltageLimit.getParameter(domainId, parameterId, parameterWrapper,
result = voltageLimit.getParameter(domainId, uniqueId, parameterWrapper,
newValues, startAtIndex);
return result;
}

View File

@ -48,7 +48,7 @@ public:
float getPower();
ReturnValue_t setHealth(HealthState health);
HasHealthIF::HealthState getHealth();
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);
private:

View File

@ -1,12 +1,12 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
CService200ModeCommanding.cpp
CService201HealthCommanding.cpp
Service17Test.cpp
Service1TelecommandVerification.cpp
Service2DeviceAccess.cpp
Service3Housekeeping.cpp
Service5EventReporting.cpp
Service8FunctionManagement.cpp
Service9TimeManagement.cpp
target_sources(${LIB_FSFW_NAME} PRIVATE
Service1TelecommandVerification.cpp
Service2DeviceAccess.cpp
Service3Housekeeping.cpp
Service5EventReporting.cpp
Service8FunctionManagement.cpp
Service9TimeManagement.cpp
Service17Test.cpp
Service20ParameterManagement.cpp
CService200ModeCommanding.cpp
CService201HealthCommanding.cpp
)

View File

@ -15,7 +15,7 @@ Service17Test::~Service17Test() {
}
ReturnValue_t Service17Test::handleRequest(uint8_t subservice) {
switch(subservice){
switch(subservice) {
case Subservice::CONNECTION_TEST: {
TmPacketStored connectionPacket(apid, serviceId,
Subservice::CONNECTION_TEST_REPORT, packetSubCounter++);

View File

@ -0,0 +1,186 @@
#include "Service20ParameterManagement.h"
#include "servicepackets/Service20Packets.h"
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <fsfw/parameters/HasParametersIF.h>
#include <fsfw/parameters/ParameterMessage.h>
#include <fsfw/parameters/ReceivesParameterMessagesIF.h>
#include <tmtc/pusIds.h>
Service20ParameterManagement::Service20ParameterManagement(object_id_t objectId, uint16_t apid,
uint8_t serviceId, uint8_t numberOfParallelCommands, uint16_t commandTimeoutSeconds) :
CommandingServiceBase(objectId, apid, serviceId,
numberOfParallelCommands,commandTimeoutSeconds) {}
Service20ParameterManagement::~Service20ParameterManagement() {}
ReturnValue_t Service20ParameterManagement::isValidSubservice(
uint8_t subservice) {
switch(static_cast<Subservice>(subservice)) {
case Subservice::PARAMETER_LOAD:
case Subservice::PARAMETER_DUMP:
return HasReturnvaluesIF::RETURN_OK;
default:
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Invalid Subservice for Service 20" << std::endl;
#else
sif::printError("Invalid Subservice for Service 20\n");
#endif
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
}
}
ReturnValue_t Service20ParameterManagement::getMessageQueueAndObject(
uint8_t subservice, const uint8_t* tcData, size_t tcDataLen,
MessageQueueId_t* id, object_id_t* objectId) {
ReturnValue_t result = checkAndAcquireTargetID(objectId,tcData,tcDataLen);
if(result != RETURN_OK) {
return result;
}
return checkInterfaceAndAcquireMessageQueue(id,objectId);
}
ReturnValue_t Service20ParameterManagement::checkAndAcquireTargetID(
object_id_t* objectIdToSet, const uint8_t* tcData, size_t tcDataLen) {
if(SerializeAdapter::deSerialize(objectIdToSet, &tcData, &tcDataLen,
SerializeIF::Endianness::BIG) != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Service20ParameterManagement::checkAndAcquireTargetID: "
<< "Invalid data." << std::endl;
#else
sif::printError("Service20ParameterManagement::"
"checkAndAcquireTargetID: Invalid data.\n");
#endif
return CommandingServiceBase::INVALID_TC;
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Service20ParameterManagement::checkInterfaceAndAcquireMessageQueue(
MessageQueueId_t* messageQueueToSet, object_id_t* objectId) {
// check ReceivesParameterMessagesIF property of target
ReceivesParameterMessagesIF* possibleTarget =
objectManager->get<ReceivesParameterMessagesIF>(*objectId);
if(possibleTarget == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Service20ParameterManagement::checkInterfaceAndAcquire"
<<"MessageQueue: Can't access object" << std::endl;
sif::error << "Object ID: " << std::hex << objectId << std::dec << std::endl;
sif::error << "Make sure it implements ReceivesParameterMessagesIF!" << std::endl;
#else
sif::printError("Service20ParameterManagement::checkInterfaceAndAcquire"
"MessageQueue: Can't access object\n");
sif::printError("Object ID: 0x%08x\n", objectId);
sif::printError("Make sure it implements "
"ReceivesParameterMessagesIF!\n");
#endif
return CommandingServiceBase::INVALID_OBJECT;
}
*messageQueueToSet = possibleTarget->getCommandQueue();
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Service20ParameterManagement::prepareCommand(
CommandMessage* message, uint8_t subservice, const uint8_t* tcData,
size_t tcDataLen, uint32_t* state, object_id_t objectId) {
switch(static_cast<Subservice>(subservice)){
case Subservice::PARAMETER_DUMP: {
return prepareDumpCommand(message, tcData, tcDataLen);
}
break;
case Subservice::PARAMETER_LOAD: {
return prepareLoadCommand(message, tcData, tcDataLen);
}
break;
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t Service20ParameterManagement::prepareDumpCommand(
CommandMessage* message, const uint8_t* tcData, size_t tcDataLen) {
/* the first part is the objectId, but we have extracted that earlier
and only need the parameterId */
tcData += sizeof(object_id_t);
tcDataLen -= sizeof(object_id_t);
ParameterId_t parameterId;
if(SerializeAdapter::deSerialize(&parameterId, &tcData, &tcDataLen,
SerializeIF::Endianness::BIG) != HasReturnvaluesIF::RETURN_OK) {
return CommandingServiceBase::INVALID_TC;
}
/* The length should have been decremented to 0 by this point */
if(tcDataLen != 0) {
return CommandingServiceBase::INVALID_TC;
}
ParameterMessage::setParameterDumpCommand(message, parameterId);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Service20ParameterManagement::prepareLoadCommand(
CommandMessage* message, const uint8_t* tcData, size_t tcDataLen) {
if(tcDataLen < sizeof(object_id_t) + sizeof(ParameterId_t) +
sizeof(uint32_t)) {
return CommandingServiceBase::INVALID_TC;
}
uint8_t* storePointer = nullptr;
store_address_t storeAddress;
size_t parameterDataLen = tcDataLen - sizeof(object_id_t) - sizeof(ParameterId_t) -
sizeof(uint32_t);
ReturnValue_t result = IPCStore->getFreeElement(&storeAddress,
parameterDataLen, &storePointer);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
/* Following format is expected: The first 4 bytes in the TC data are the 4 byte
parameter ID (ParameterId_t). The second 4 bytes are the parameter information field,
containing the following 1 byte fields:
1. ECSS PTC field
2. ECSS PFC field
3. Number of rows
4. Number of columns */
ParameterLoadCommand command(storePointer, parameterDataLen);
result = command.deSerialize(&tcData, &tcDataLen,
SerializeIF::Endianness::BIG);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
ParameterMessage::setParameterLoadCommand(message, command.getParameterId(), storeAddress,
command.getPtc(), command.getPfc(), command.getRows(), command.getColumns());
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Service20ParameterManagement::handleReply(
const CommandMessage* reply, Command_t previousCommand, uint32_t* state,
CommandMessage* optionalNextCommand, object_id_t objectId,
bool* isStep) {
Command_t replyId = reply->getCommand();
switch(replyId) {
case ParameterMessage::REPLY_PARAMETER_DUMP: {
ConstAccessorPair parameterData = IPCStore->getData(
ParameterMessage::getStoreId(reply));
if(parameterData.first != HasReturnvaluesIF::RETURN_OK) {
return HasReturnvaluesIF::RETURN_FAILED;
}
ParameterId_t parameterId = ParameterMessage::getParameterId(reply);
ParameterDumpReply parameterReply(objectId, parameterId,
parameterData.second.data(), parameterData.second.size());
sendTmPacket(static_cast<uint8_t>(
Subservice::PARAMETER_DUMP_REPLY), &parameterReply);
return HasReturnvaluesIF::RETURN_OK;
}
default:
return CommandingServiceBase::INVALID_REPLY;
}
}

View File

@ -0,0 +1,60 @@
#ifndef FSFW_PUS_SERVICE20PARAMETERMANAGEMENT_H_
#define FSFW_PUS_SERVICE20PARAMETERMANAGEMENT_H_
#include <fsfw/tmtcservices/CommandingServiceBase.h>
/**
* @brief PUS Service 20 Parameter Service implementation
* @details
* This service handles PUS service requests related to parameter management and forwards
* them to the internal software bus.
* @author J. Gerhards
*
*/
class Service20ParameterManagement : public CommandingServiceBase
{
public:
Service20ParameterManagement(object_id_t objectId, uint16_t apid, uint8_t serviceId,
uint8_t numberOfParallelCommands = 4, uint16_t commandTimeoutSeconds = 60);
virtual ~Service20ParameterManagement();
static constexpr uint8_t NUM_OF_PARALLEL_COMMANDS = 4;
static constexpr uint16_t COMMAND_TIMEOUT_SECONDS = 60;
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, size_t tcDataLen);
ReturnValue_t checkInterfaceAndAcquireMessageQueue(
MessageQueueId_t* messageQueueToSet, object_id_t* objectId);
ReturnValue_t prepareDirectCommand(CommandMessage* message,
const uint8_t* tcData, size_t tcDataLen);
ReturnValue_t prepareDumpCommand(CommandMessage* message,
const uint8_t* tcData, size_t tcDataLen);
ReturnValue_t prepareLoadCommand(CommandMessage* message,
const uint8_t* tcData, size_t tcDataLen);
enum class Subservice {
PARAMETER_LOAD = 128, //!< [EXPORT] : Load a Parameter
PARAMETER_DUMP = 129, //!< [EXPORT] : Dump a Parameter
PARAMETER_DUMP_REPLY = 130, //!< [EXPORT] : Dump a Parameter
};
};
#endif /* FSFW_PUS_SERVICE20PARAMETERMANAGEMENT_H_ */

View File

@ -0,0 +1,142 @@
#ifndef FSFW_PUS_SERVICEPACKETS_SERVICE20PACKETS_H_
#define FSFW_PUS_SERVICEPACKETS_SERVICE20PACKETS_H_
#include <FSFWConfig.h>
#include <fsfw/parameters/HasParametersIF.h>
#include <fsfw/serialize/SerialBufferAdapter.h>
#include <fsfw/serialize/SerializeElement.h>
#include <fsfw/serialize/SerialLinkedListAdapter.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
/**
* @brief This class encapsulates the packets sent to the PUS service 20 or sent by the
* PUS service 20
* @details
* This command can be used to handle both load and dump commands as well.
* @author
*/
class ParameterCommand: public SerialLinkedListAdapter<SerializeIF> { //!< [EXPORT] : [SUBSERVICE] 128, 129, 130
public:
/**
* This constructor is used for load replies. The data is expected in the correct formast
* in the store pointer.
* @param storePointer
* @param parameterDataLen
*/
ParameterCommand(uint8_t* storePointer, size_t parameterDataLen):
parameterBuffer(storePointer, parameterDataLen) {
#if FSFW_VERBOSE_LEVEL >= 1
if(parameterDataLen < sizeof(object_id_t) + sizeof(ParameterId_t) + 4) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterCommand: Parameter data length is less than 12!"
<< std::endl;
#else
sif::printWarning("ParameterCommand: Parameter data length is less than 12!\n");
#endif
}
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
setLoadLinks();
}
/**
* This constructor is used for dump replies. It is assumed the 4 byte parameter
* information field is located inside the parameter buffer.
* @param objectId
* @param parameterId
* @param parameterBuffer
* @param parameterBufferSize
*/
ParameterCommand(object_id_t objectId, ParameterId_t parameterId,
const uint8_t* parameterBuffer, size_t parameterBufferSize):
objectId(objectId), parameterId(parameterId),
parameterBuffer(parameterBuffer, parameterBufferSize) {
setDumpReplyLinks();
}
ParameterId_t getParameterId() const {
return parameterId.entry;
}
const uint8_t* getParameterBuffer() {
return parameterBuffer.entry.getConstBuffer();
}
size_t getParameterBufferLen() const {
return parameterBuffer.getSerializedSize();
}
uint8_t getDomainId() const {
return (parameterId.entry >> 24) & 0xff;
}
uint8_t getUniqueId() const {
return (parameterId.entry >> 16) & 0xff;
}
uint16_t getLinearIndex() const {
return parameterId.entry & 0xffff;
}
uint8_t getPtc() const {
return ccsdsType.entry >> 8 & 0xff;
}
uint8_t getPfc() const {
return ccsdsType.entry & 0xff;
}
uint8_t getRows() const {
return rows.entry;
}
uint8_t getColumns() const {
return columns.entry;
}
private:
void setLoadLinks() {
setStart(&objectId);
objectId.setNext(&parameterId);
parameterId.setNext(&ccsdsType);
ccsdsType.setNext(&rows);
rows.setNext(&columns);
columns.setNext(&parameterBuffer);
}
void setDumpReplyLinks() {
/* For a dump reply, the parameter information is contained in the parameter buffer
with the actual parameters */
setStart(&objectId);
objectId.setNext(&parameterId);
parameterId.setNext(&parameterBuffer);
}
void setDumpRequestLinks() {
setStart(&objectId);
objectId.setNext(&parameterId);
}
SerializeElement<object_id_t> objectId = 0;
SerializeElement<ParameterId_t> parameterId = 0;
//! [EXPORT] : [COMMENT] Type consisting of one byte PTC and one byte PFC.
SerializeElement<uint16_t> ccsdsType = 0;
SerializeElement<uint8_t> rows = 0;
SerializeElement<uint8_t> columns = 0;
SerializeElement<SerialBufferAdapter<uint8_t>> parameterBuffer;
};
class ParameterLoadCommand: public ParameterCommand {
public:
ParameterLoadCommand(uint8_t* parameterPacket, size_t parameterDataLen):
ParameterCommand(parameterPacket, parameterDataLen) {}
};
class ParameterDumpReply: public ParameterCommand {
public:
ParameterDumpReply(object_id_t objectId, ParameterId_t parameterId,
const uint8_t* parameterBuffer, size_t parameterBufferSize):
ParameterCommand(objectId, parameterId, parameterBuffer, parameterBufferSize) {}
};
#endif /* FSFW_PUS_SERVICEPACKETS_SERVICE20PACKETS_H_ */

View File

@ -290,13 +290,13 @@ void Heater::handleQueue() {
}
}
ReturnValue_t Heater::getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
ReturnValue_t Heater::getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
uint16_t startAtIndex) {
if (domainId != DOMAIN_ID_BASE) {
return INVALID_DOMAIN_ID;
}
switch (parameterId) {
switch (uniqueId) {
case 0:
parameterWrapper->set(heaterOnCountdown.timeout);
break;

View File

@ -34,8 +34,8 @@ public:
MessageQueueId_t getCommandQueue() const;
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper,
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);
protected:

View File

@ -183,10 +183,10 @@ public:
static const uint8_t DOMAIN_ID_SENSOR = 1;
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex) {
ReturnValue_t result = sensorMonitor.getParameter(domainId, parameterId,
ReturnValue_t result = sensorMonitor.getParameter(domainId, uniqueId,
parameterWrapper, newValues, startAtIndex);
if (result != INVALID_DOMAIN_ID) {
return result;
@ -194,7 +194,7 @@ public:
if (domainId != this->DOMAIN_ID_BASE) {
return INVALID_DOMAIN_ID;
}
switch (parameterId) {
switch (uniqueId) {
case ADDRESS_A:
parameterWrapper->set(parameters.a);
break;

View File

@ -148,14 +148,14 @@ ThermalComponentIF::State ThermalComponent::getIgnoredState(int8_t state) {
}
ReturnValue_t ThermalComponent::getParameter(uint8_t domainId,
uint16_t parameterId, ParameterWrapper* parameterWrapper,
uint8_t uniqueId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) {
ReturnValue_t result = ThermalComponentCore::getParameter(domainId, parameterId,
ReturnValue_t result = ThermalComponentCore::getParameter(domainId, uniqueId,
parameterWrapper, newValues, startAtIndex);
if (result != INVALID_IDENTIFIER_ID) {
return result;
}
switch (parameterId) {
switch (uniqueId) {
case 12:
parameterWrapper->set(nopParameters.lowerNopLimit);
break;

View File

@ -58,7 +58,7 @@ public:
virtual ReturnValue_t setLimits( const uint8_t* data, size_t size);
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);

View File

@ -247,17 +247,17 @@ ThermalComponentCore::Parameters ThermalComponentCore::getParameters() {
}
ReturnValue_t ThermalComponentCore::getParameter(uint8_t domainId,
uint16_t parameterId, ParameterWrapper* parameterWrapper,
uint8_t uniqueId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) {
ReturnValue_t result = temperatureMonitor.getParameter(domainId,
parameterId, parameterWrapper, newValues, startAtIndex);
uniqueId, parameterWrapper, newValues, startAtIndex);
if (result != INVALID_DOMAIN_ID) {
return result;
}
if (domainId != this->domainId) {
return INVALID_DOMAIN_ID;
}
switch (parameterId) {
switch (uniqueId) {
case 0:
parameterWrapper->set(parameters.heaterOn);
break;

View File

@ -68,7 +68,7 @@ public:
virtual void setOutputInvalid();
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);

View File

@ -1,7 +1,7 @@
#include "TmTcBridge.h"
#include "../ipc/QueueFactory.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../serviceinterface/ServiceInterface.h"
#include "../globalfunctions/arrayprinter.h"
TmTcBridge::TmTcBridge(object_id_t objectId, object_id_t tcDestination,
@ -109,9 +109,8 @@ ReturnValue_t TmTcBridge::handleTm() {
ReturnValue_t result = handleTmQueue();
if(result != RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmTcBridge::handleTm: Error handling TM queue with "
<< "error code 0x" << std::hex << result << std::dec
<< "!" << std::endl;
sif::error << "TmTcBridge::handleTm: Error handling TM queue with error code 0x" <<
std::hex << result << std::dec << "!" << std::endl;
#endif
status = result;
}
@ -121,8 +120,7 @@ ReturnValue_t TmTcBridge::handleTm() {
result = handleStoredTm();
if(result != RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmTcBridge::handleTm: Error handling stored TMs!"
<< std::endl;
sif::error << "TmTcBridge::handleTm: Error handling stored TMs!" << std::endl;
#endif
status = result;
}
@ -140,9 +138,15 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
result == HasReturnvaluesIF::RETURN_OK;
result = tmTcReceptionQueue->receiveMessage(&message))
{
#if FSFW_VERBOSE_LEVEL >= 3
#if FSFW_CPP_OSTREAM_ENABLED == 1
//sif::info << (int) packetSentCounter << std::endl;
sif::info << "Sent packet counter: " << static_cast<int>(packetSentCounter) << std::endl;
#else
sif::printInfo("Sent packet counter: %d\n", packetSentCounter);
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 3 */
if(communicationLinkUp == false or
packetSentCounter >= sentPacketsPerCycle) {
storeDownlinkData(&message);