Compare commits
7 Commits
cac9a0eecd
...
ASTP_1.0.0
Author | SHA1 | Date | |
---|---|---|---|
2f511523cb | |||
9f83739771 | |||
054de9781b | |||
20e7fe6cb1 | |||
f8cd8e1e7d | |||
818634755d | |||
87fee9bd0e |
@@ -17,8 +17,6 @@
|
||||
#define FSFW_DISABLE_PRINTOUT 0
|
||||
#endif
|
||||
|
||||
#define FSFW_USE_PUS_C_TELEMETRY 1
|
||||
|
||||
//! Can be used to disable the ANSI color sequences for C stdio.
|
||||
#define FSFW_COLORED_OUTPUT 1
|
||||
|
||||
@@ -50,9 +48,9 @@
|
||||
#define FSFW_USE_REALTIME_FOR_LINUX 1
|
||||
|
||||
namespace fsfwconfig {
|
||||
|
||||
//! Default timestamp size. The default timestamp will be an seven byte CDC short timestamp.
|
||||
static constexpr uint8_t FSFW_MISSION_TIMESTAMP_SIZE = 7;
|
||||
//! Default timestamp size. The default timestamp will be an eight byte CDC
|
||||
//! short timestamp.
|
||||
static constexpr uint8_t FSFW_MISSION_TIMESTAMP_SIZE = 8;
|
||||
|
||||
//! Configure the allocated pool sizes for the event manager.
|
||||
static constexpr size_t FSFW_EVENTMGMR_MATCHTREE_NODES = 240;
|
||||
|
@@ -308,11 +308,11 @@ void DeviceHandlerBase::doStateMachine() {
|
||||
uint32_t currentUptime;
|
||||
Clock::getUptime(¤tUptime);
|
||||
if (currentUptime - timeoutStart >= childTransitionDelay) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_VERBOSE_LEVEL >= 1 && FSFW_OBJ_EVENT_TRANSLATION == 0
|
||||
char printout[60];
|
||||
sprintf(printout, "Transition timeout (%lu) occured !",
|
||||
static_cast<unsigned long>(childTransitionDelay));
|
||||
/* Very common configuration error, so print it */
|
||||
/* Common configuration error for development, so print it */
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "doStateMachine",
|
||||
RETURN_FAILED, printout);
|
||||
#endif
|
||||
@@ -456,6 +456,15 @@ ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceComm
|
||||
}
|
||||
}
|
||||
|
||||
size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId){
|
||||
DeviceReplyIter iter = deviceReplyMap.find(commandId);
|
||||
if(iter != deviceReplyMap.end()) {
|
||||
return iter->second.replyLen;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply,
|
||||
uint16_t delayCycles, uint16_t maxDelayCycles, bool periodic) {
|
||||
auto replyIter = deviceReplyMap.find(deviceReply);
|
||||
@@ -646,16 +655,12 @@ void DeviceHandlerBase::doGetWrite() {
|
||||
void DeviceHandlerBase::doSendRead() {
|
||||
ReturnValue_t result;
|
||||
|
||||
size_t requestLen = 0;
|
||||
size_t replyLen = 0;
|
||||
if(cookieInfo.pendingCommand != deviceCommandMap.end()) {
|
||||
DeviceReplyIter iter = deviceReplyMap.find(
|
||||
cookieInfo.pendingCommand->first);
|
||||
if(iter != deviceReplyMap.end()) {
|
||||
requestLen = iter->second.replyLen;
|
||||
}
|
||||
replyLen = getNextReplyLength(cookieInfo.pendingCommand->first);
|
||||
}
|
||||
|
||||
result = communicationInterface->requestReceiveMessage(comCookie, requestLen);
|
||||
result = communicationInterface->requestReceiveMessage(comCookie, replyLen);
|
||||
|
||||
if (result == RETURN_OK) {
|
||||
cookieInfo.state = COOKIE_READ_SENT;
|
||||
|
@@ -471,13 +471,27 @@ protected:
|
||||
ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand,
|
||||
uint16_t maxDelayCycles, LocalPoolDataSetBase* dataSet = nullptr,
|
||||
size_t replyLen = 0, bool periodic = false);
|
||||
|
||||
/**
|
||||
* @brief A simple command to add a command to the commandList.
|
||||
* @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 function returns the reply length of the next reply to read.
|
||||
*
|
||||
* @param deviceCommand The command which triggered the device reply.
|
||||
*
|
||||
* @details The default implementation assumes only one reply is triggered by the command. In
|
||||
* case the command triggers multiple replies (e.g. one acknowledgment, one data,
|
||||
* and one execution status reply), this function can be overwritten to get the
|
||||
* reply length of the next reply to read.
|
||||
*/
|
||||
virtual size_t getNextReplyLength(DeviceCommandId_t deviceCommand);
|
||||
|
||||
/**
|
||||
* @brief This is a helper method to facilitate updating entries
|
||||
* in the reply map.
|
||||
@@ -953,7 +967,7 @@ protected:
|
||||
* - 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,
|
||||
virtual ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator command,
|
||||
uint8_t expectedReplies = 1, bool useAlternateId = false,
|
||||
DeviceCommandId_t alternateReplyID = 0);
|
||||
|
||||
|
@@ -5,15 +5,6 @@
|
||||
|
||||
void arrayprinter::print(const uint8_t *data, size_t size, OutputType type,
|
||||
bool printInfo, size_t maxCharPerLine) {
|
||||
if(size == 0) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "Size is zero, nothing to print" << std::endl;
|
||||
#else
|
||||
sif::printInfo("Size is zero, nothing to print\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
if(printInfo) {
|
||||
sif::info << "Printing data with size " << size << ": " << std::endl;
|
||||
|
@@ -108,9 +108,9 @@ void ObjectManager::initialize() {
|
||||
result = it.second->checkObjectConnections();
|
||||
if ( result != RETURN_OK ) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "ObjectManager::ObjectManager: Object 0x" << std::hex <<
|
||||
(int) it.first << " connection check failed with code 0x" << result <<
|
||||
std::dec << std::endl;
|
||||
sif::error << "ObjectManager::ObjectManager: Object " << std::hex <<
|
||||
(int) it.first << " connection check failed with code 0x"
|
||||
<< result << std::dec << std::endl;
|
||||
#endif
|
||||
errorCount++;
|
||||
}
|
||||
|
@@ -12,54 +12,56 @@ PosixThread::PosixThread(const char* name_, int priority_, size_t stackSize_):
|
||||
}
|
||||
|
||||
PosixThread::~PosixThread() {
|
||||
//No deletion and no free of Stack Pointer
|
||||
//No deletion and no free of Stack Pointer
|
||||
}
|
||||
|
||||
ReturnValue_t PosixThread::sleep(uint64_t ns) {
|
||||
//TODO sleep might be better with timer instead of sleep()
|
||||
timespec time;
|
||||
time.tv_sec = ns/1000000000;
|
||||
time.tv_nsec = ns - time.tv_sec*1e9;
|
||||
//TODO sleep might be better with timer instead of sleep()
|
||||
timespec time;
|
||||
time.tv_sec = ns/1000000000;
|
||||
time.tv_nsec = ns - time.tv_sec*1e9;
|
||||
|
||||
//Remaining Time is not set here
|
||||
int status = nanosleep(&time,NULL);
|
||||
if(status != 0){
|
||||
switch(errno){
|
||||
case EINTR:
|
||||
//The nanosleep() function was interrupted by a signal.
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case EINVAL:
|
||||
//The rqtp argument specified a nanosecond value less than zero or
|
||||
// greater than or equal to 1000 million.
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
//Remaining Time is not set here
|
||||
int status = nanosleep(&time,NULL);
|
||||
if(status != 0){
|
||||
switch(errno){
|
||||
case EINTR:
|
||||
//The nanosleep() function was interrupted by a signal.
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case EINVAL:
|
||||
//The rqtp argument specified a nanosecond value less than zero or
|
||||
// greater than or equal to 1000 million.
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void PosixThread::suspend() {
|
||||
//Wait for SIGUSR1
|
||||
int caughtSig = 0;
|
||||
sigset_t waitSignal;
|
||||
sigemptyset(&waitSignal);
|
||||
sigaddset(&waitSignal, SIGUSR1);
|
||||
sigwait(&waitSignal, &caughtSig);
|
||||
if (caughtSig != SIGUSR1) {
|
||||
//Wait for SIGUSR1
|
||||
int caughtSig = 0;
|
||||
sigset_t waitSignal;
|
||||
sigemptyset(&waitSignal);
|
||||
sigaddset(&waitSignal, SIGUSR1);
|
||||
sigwait(&waitSignal, &caughtSig);
|
||||
if (caughtSig != SIGUSR1) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "FixedTimeslotTask: Unknown Signal received: " <<
|
||||
caughtSig << std::endl;
|
||||
sif::error << "FixedTimeslotTask: Unknown Signal received: " <<
|
||||
caughtSig << std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PosixThread::resume(){
|
||||
/* Signal the thread to start. Makes sense to call kill to start or? ;)
|
||||
According to POSIX raise(signal) will call pthread_kill(pthread_self(), sig),
|
||||
but as the call must be done from the thread itself this is not possible here */
|
||||
pthread_kill(thread,SIGUSR1);
|
||||
/* Signal the thread to start. Makes sense to call kill to start or? ;)
|
||||
*
|
||||
* According to Posix raise(signal) will call pthread_kill(pthread_self(), sig),
|
||||
* but as the call must be done from the thread itsself this is not possible here
|
||||
*/
|
||||
pthread_kill(thread,SIGUSR1);
|
||||
}
|
||||
|
||||
bool PosixThread::delayUntil(uint64_t* const prevoiusWakeTime_ms,
|
||||
@@ -91,95 +93,95 @@ bool PosixThread::delayUntil(uint64_t* const prevoiusWakeTime_ms,
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the wake time ready for the next call. */
|
||||
/* Update the wake time ready for the next call. */
|
||||
|
||||
(*prevoiusWakeTime_ms) = nextTimeToWake_ms;
|
||||
(*prevoiusWakeTime_ms) = nextTimeToWake_ms;
|
||||
|
||||
if (shouldDelay) {
|
||||
uint64_t sleepTime = nextTimeToWake_ms - currentTime_ms;
|
||||
PosixThread::sleep(sleepTime * 1000000ull);
|
||||
return true;
|
||||
}
|
||||
/* We are shifting the time in case the deadline was missed like RTEMS */
|
||||
(*prevoiusWakeTime_ms) = currentTime_ms;
|
||||
return false;
|
||||
if (shouldDelay) {
|
||||
uint64_t sleepTime = nextTimeToWake_ms - currentTime_ms;
|
||||
PosixThread::sleep(sleepTime * 1000000ull);
|
||||
return true;
|
||||
}
|
||||
//We are shifting the time in case the deadline was missed like rtems
|
||||
(*prevoiusWakeTime_ms) = currentTime_ms;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
uint64_t PosixThread::getCurrentMonotonicTimeMs(){
|
||||
timespec timeNow;
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &timeNow);
|
||||
uint64_t currentTime_ms = (uint64_t) timeNow.tv_sec * 1000
|
||||
+ timeNow.tv_nsec / 1000000;
|
||||
timespec timeNow;
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &timeNow);
|
||||
uint64_t currentTime_ms = (uint64_t) timeNow.tv_sec * 1000
|
||||
+ timeNow.tv_nsec / 1000000;
|
||||
|
||||
return currentTime_ms;
|
||||
return currentTime_ms;
|
||||
}
|
||||
|
||||
|
||||
void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
//sif::debug << "PosixThread::createTask" << std::endl;
|
||||
//sif::debug << "PosixThread::createTask" << std::endl;
|
||||
#endif
|
||||
/*
|
||||
* The attr argument points to a pthread_attr_t structure whose contents
|
||||
* are used at thread creation time to determine attributes for the new
|
||||
* thread; this structure is initialized using pthread_attr_init(3) and
|
||||
* related functions. If attr is NULL, then the thread is created with
|
||||
* default attributes.
|
||||
*/
|
||||
pthread_attr_t attributes;
|
||||
int status = pthread_attr_init(&attributes);
|
||||
if(status != 0){
|
||||
/*
|
||||
* The attr argument points to a pthread_attr_t structure whose contents
|
||||
are used at thread creation time to determine attributes for the new
|
||||
thread; this structure is initialized using pthread_attr_init(3) and
|
||||
related functions. If attr is NULL, then the thread is created with
|
||||
default attributes.
|
||||
*/
|
||||
pthread_attr_t attributes;
|
||||
int status = pthread_attr_init(&attributes);
|
||||
if(status != 0){
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Posix Thread attribute init failed with: " <<
|
||||
strerror(status) << std::endl;
|
||||
sif::error << "Posix Thread attribute init failed with: " <<
|
||||
strerror(status) << std::endl;
|
||||
#endif
|
||||
}
|
||||
void* stackPointer;
|
||||
status = posix_memalign(&stackPointer, sysconf(_SC_PAGESIZE), stackSize);
|
||||
if(status != 0){
|
||||
}
|
||||
void* stackPointer;
|
||||
status = posix_memalign(&stackPointer, sysconf(_SC_PAGESIZE), stackSize);
|
||||
if(status != 0){
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PosixThread::createTask: Stack init failed with: " <<
|
||||
strerror(status) << std::endl;
|
||||
sif::error << "PosixThread::createTask: Stack init failed with: " <<
|
||||
strerror(status) << std::endl;
|
||||
#endif
|
||||
if(errno == ENOMEM) {
|
||||
size_t stackMb = stackSize/10e6;
|
||||
if(errno == ENOMEM) {
|
||||
size_t stackMb = stackSize/10e6;
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PosixThread::createTask: Insufficient memory for"
|
||||
" the requested " << stackMb << " MB" << std::endl;
|
||||
sif::error << "PosixThread::createTask: Insufficient memory for"
|
||||
" the requested " << stackMb << " MB" << std::endl;
|
||||
#else
|
||||
sif::printError("PosixThread::createTask: Insufficient memory for "
|
||||
"the requested %lu MB\n", static_cast<unsigned long>(stackMb));
|
||||
sif::printError("PosixThread::createTask: Insufficient memory for "
|
||||
"the requested %lu MB\n", static_cast<unsigned long>(stackMb));
|
||||
#endif
|
||||
}
|
||||
else if(errno == EINVAL) {
|
||||
}
|
||||
else if(errno == EINVAL) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PosixThread::createTask: Wrong alignment argument!"
|
||||
<< std::endl;
|
||||
sif::error << "PosixThread::createTask: Wrong alignment argument!"
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printError("PosixThread::createTask: "
|
||||
"Wrong alignment argument!\n");
|
||||
sif::printError("PosixThread::createTask: "
|
||||
"Wrong alignment argument!\n");
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
status = pthread_attr_setstack(&attributes, stackPointer, stackSize);
|
||||
if(status != 0){
|
||||
status = pthread_attr_setstack(&attributes, stackPointer, stackSize);
|
||||
if(status != 0){
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PosixThread::createTask: pthread_attr_setstack "
|
||||
" failed with: " << strerror(status) << std::endl;
|
||||
sif::error << "Make sure the specified stack size is valid and is "
|
||||
"larger than the minimum allowed stack size." << std::endl;
|
||||
sif::error << "PosixThread::createTask: pthread_attr_setstack "
|
||||
" failed with: " << strerror(status) << std::endl;
|
||||
sif::error << "Make sure the specified stack size is valid and is "
|
||||
"larger than the minimum allowed stack size." << std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
status = pthread_attr_setinheritsched(&attributes, PTHREAD_EXPLICIT_SCHED);
|
||||
if(status != 0){
|
||||
status = pthread_attr_setinheritsched(&attributes, PTHREAD_EXPLICIT_SCHED);
|
||||
if(status != 0){
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Posix Thread attribute setinheritsched failed with: " <<
|
||||
strerror(status) << std::endl;
|
||||
sif::error << "Posix Thread attribute setinheritsched failed with: " <<
|
||||
strerror(status) << std::endl;
|
||||
#endif
|
||||
}
|
||||
#ifndef FSFW_USE_REALTIME_FOR_LINUX
|
||||
@@ -190,18 +192,18 @@ void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) {
|
||||
status = pthread_attr_setschedpolicy(&attributes,SCHED_FIFO);
|
||||
if(status != 0){
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Posix Thread attribute schedule policy failed with: " <<
|
||||
strerror(status) << std::endl;
|
||||
sif::error << "Posix Thread attribute schedule policy failed with: " <<
|
||||
strerror(status) << std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
sched_param scheduleParams;
|
||||
scheduleParams.__sched_priority = priority;
|
||||
status = pthread_attr_setschedparam(&attributes, &scheduleParams);
|
||||
if(status != 0){
|
||||
sched_param scheduleParams;
|
||||
scheduleParams.__sched_priority = priority;
|
||||
status = pthread_attr_setschedparam(&attributes, &scheduleParams);
|
||||
if(status != 0){
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Posix Thread attribute schedule params failed with: " <<
|
||||
strerror(status) << std::endl;
|
||||
sif::error << "Posix Thread attribute schedule params failed with: " <<
|
||||
strerror(status) << std::endl;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -212,14 +214,14 @@ void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) {
|
||||
status = pthread_sigmask(SIG_BLOCK, &waitSignal, NULL);
|
||||
if(status != 0){
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Posix Thread sigmask failed failed with: " <<
|
||||
strerror(status) << " errno: " << strerror(errno) << std::endl;
|
||||
sif::error << "Posix Thread sigmask failed failed with: " <<
|
||||
strerror(status) << " errno: " << strerror(errno) << std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status = pthread_create(&thread,&attributes,fnc_,arg_);
|
||||
if(status != 0){
|
||||
status = pthread_create(&thread,&attributes,fnc_,arg_);
|
||||
if(status != 0){
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PosixThread::createTask: Failed with: " <<
|
||||
strerror(status) << std::endl;
|
||||
@@ -232,35 +234,35 @@ void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) {
|
||||
"\"all sudo setcap 'cap_sys_nice=eip'\" on the application or set "
|
||||
"/etc/security/limit.conf\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
status = pthread_setname_np(thread,name);
|
||||
if(status != 0){
|
||||
status = pthread_setname_np(thread,name);
|
||||
if(status != 0){
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PosixThread::createTask: setname failed with: " <<
|
||||
strerror(status) << std::endl;
|
||||
sif::error << "PosixThread::createTask: setname failed with: " <<
|
||||
strerror(status) << std::endl;
|
||||
#endif
|
||||
if(status == ERANGE) {
|
||||
if(status == ERANGE) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PosixThread::createTask: Task name length longer"
|
||||
" than 16 chars. Truncating.." << std::endl;
|
||||
sif::error << "PosixThread::createTask: Task name length longer"
|
||||
" than 16 chars. Truncating.." << std::endl;
|
||||
#endif
|
||||
name[15] = '\0';
|
||||
status = pthread_setname_np(thread,name);
|
||||
if(status != 0){
|
||||
name[15] = '\0';
|
||||
status = pthread_setname_np(thread,name);
|
||||
if(status != 0){
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PosixThread::createTask: Setting name"
|
||||
" did not work.." << std::endl;
|
||||
sif::error << "PosixThread::createTask: Setting name"
|
||||
" did not work.." << std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
status = pthread_attr_destroy(&attributes);
|
||||
if(status!=0){
|
||||
status = pthread_attr_destroy(&attributes);
|
||||
if(status!=0){
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Posix Thread attribute destroy failed with: " <<
|
||||
strerror(status) << std::endl;
|
||||
sif::error << "Posix Thread attribute destroy failed with: " <<
|
||||
strerror(status) << std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,157 +0,0 @@
|
||||
#include "TmTcUnixUdpBridge.h"
|
||||
#include "tcpipHelpers.h"
|
||||
#include "../../serviceinterface/ServiceInterface.h"
|
||||
#include "../../ipc/MutexGuard.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
//! Debugging preprocessor define.
|
||||
#define FSFW_UDP_SEND_WIRETAPPING_ENABLED 0
|
||||
|
||||
const std::string TmTcUnixUdpBridge::DEFAULT_UDP_SERVER_PORT = tcpip::DEFAULT_UDP_SERVER_PORT;
|
||||
|
||||
TmTcUnixUdpBridge::TmTcUnixUdpBridge(object_id_t objectId, object_id_t tcDestination,
|
||||
object_id_t tmStoreId, object_id_t tcStoreId, std::string udpServerPort):
|
||||
TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) {
|
||||
if(udpServerPort == "") {
|
||||
this->udpServerPort = DEFAULT_UDP_SERVER_PORT;
|
||||
}
|
||||
else {
|
||||
this->udpServerPort = udpServerPort;
|
||||
}
|
||||
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
communicationLinkUp = false;
|
||||
}
|
||||
|
||||
ReturnValue_t TmTcUnixUdpBridge::initialize() {
|
||||
using namespace tcpip;
|
||||
|
||||
ReturnValue_t result = TmTcBridge::initialize();
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "TmTcUnixUdpBridge::initialize: TmTcBridge initialization failed!"
|
||||
<< std::endl;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
struct addrinfo *addrResult = nullptr;
|
||||
struct addrinfo hints;
|
||||
|
||||
std::memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_protocol = IPPROTO_UDP;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
|
||||
/* Set up UDP socket:
|
||||
https://man7.org/linux/man-pages/man3/getaddrinfo.3.html
|
||||
Passing nullptr as the first parameter and specifying AI_PASSIVE in hints will cause
|
||||
getaddrinfo to assign the address 0.0.0.0 (any address) */
|
||||
int retval = getaddrinfo(nullptr, udpServerPort.c_str(), &hints, &addrResult);
|
||||
if (retval != 0) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "TmTcWinUdpBridge::TmTcWinUdpBridge: Retrieving address info failed!" <<
|
||||
std::endl;
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
/* Set up UDP socket: https://man7.org/linux/man-pages/man7/ip.7.html */
|
||||
serverSocket = socket(addrResult->ai_family, addrResult->ai_socktype, addrResult->ai_protocol);
|
||||
if(serverSocket < 0) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not open UDP socket!" <<
|
||||
std::endl;
|
||||
#else
|
||||
sif::printError("TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not open UDP socket!\n");
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
freeaddrinfo(addrResult);
|
||||
handleError(Protocol::UDP, ErrorSources::SOCKET_CALL);
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
retval = bind(serverSocket, addrResult->ai_addr, static_cast<int>(addrResult->ai_addrlen));
|
||||
if(retval != 0) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "TmTcWinUdpBridge::TmTcWinUdpBridge: Could not bind "
|
||||
"local port (" << udpServerPort << ") to server socket!" << std::endl;
|
||||
#endif
|
||||
freeaddrinfo(addrResult);
|
||||
handleError(Protocol::UDP, ErrorSources::BIND_CALL);
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
TmTcUnixUdpBridge::~TmTcUnixUdpBridge() {
|
||||
if(mutex != nullptr) {
|
||||
MutexFactory::instance()->deleteMutex(mutex);
|
||||
}
|
||||
close(serverSocket);
|
||||
}
|
||||
|
||||
ReturnValue_t TmTcUnixUdpBridge::sendTm(const uint8_t *data, size_t dataLen) {
|
||||
int flags = 0;
|
||||
|
||||
/* The target address can be set by different threads so this lock ensures thread-safety */
|
||||
MutexGuard lock(mutex, timeoutType, mutexTimeoutMs);
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
|
||||
char ipAddress [15];
|
||||
sif::debug << "IP Address Sender: "<<
|
||||
inet_ntop(AF_INET,&clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl;
|
||||
#endif
|
||||
|
||||
ssize_t bytesSent = sendto(
|
||||
serverSocket,
|
||||
data,
|
||||
dataLen,
|
||||
flags,
|
||||
reinterpret_cast<sockaddr*>(&clientAddress),
|
||||
clientAddressLen
|
||||
);
|
||||
if(bytesSent < 0) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "TmTcUnixUdpBridge::sendTm: Send operation failed." << std::endl;
|
||||
#endif
|
||||
tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::SENDTO_CALL);
|
||||
}
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
|
||||
sif::debug << "TmTcUnixUdpBridge::sendTm: " << bytesSent << " bytes were"
|
||||
" sent." << std::endl;
|
||||
#endif
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void TmTcUnixUdpBridge::checkAndSetClientAddress(sockaddr_in& newAddress) {
|
||||
/* The target address can be set by different threads so this lock ensures thread-safety */
|
||||
MutexGuard lock(mutex, timeoutType, mutexTimeoutMs);
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1
|
||||
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;
|
||||
#endif
|
||||
registerCommConnect();
|
||||
|
||||
/* Set new IP address to reply to. */
|
||||
clientAddress = newAddress;
|
||||
clientAddressLen = sizeof(clientAddress);
|
||||
}
|
||||
|
||||
void TmTcUnixUdpBridge::setMutexProperties(MutexIF::TimeoutType timeoutType,
|
||||
dur_millis_t timeoutMs) {
|
||||
this->timeoutType = timeoutType;
|
||||
this->mutexTimeoutMs = timeoutMs;
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
#ifndef FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_
|
||||
#define FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_
|
||||
|
||||
#include "../../tmtcservices/AcceptsTelecommandsIF.h"
|
||||
#include "../../tmtcservices/TmTcBridge.h"
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
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 const std::string DEFAULT_UDP_SERVER_PORT;
|
||||
|
||||
TmTcUnixUdpBridge(object_id_t objectId, object_id_t tcDestination,
|
||||
object_id_t tmStoreId, object_id_t tcStoreId,
|
||||
std::string serverPort = "");
|
||||
virtual~ TmTcUnixUdpBridge();
|
||||
|
||||
/**
|
||||
* Set properties of internal mutex.
|
||||
*/
|
||||
void setMutexProperties(MutexIF::TimeoutType timeoutType, dur_millis_t timeoutMs);
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
void checkAndSetClientAddress(sockaddr_in& clientAddress);
|
||||
|
||||
protected:
|
||||
virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override;
|
||||
|
||||
private:
|
||||
int serverSocket = 0;
|
||||
std::string udpServerPort;
|
||||
|
||||
struct sockaddr_in clientAddress;
|
||||
socklen_t clientAddressLen = 0;
|
||||
|
||||
//! Access to the client address is mutex protected as it is set by another task.
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
||||
dur_millis_t mutexTimeoutMs = 20;
|
||||
MutexIF* mutex;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ */
|
@@ -65,6 +65,9 @@ ReturnValue_t ParameterHelper::handleParameterMessage(CommandMessage *message) {
|
||||
ParameterWrapper ownerWrapper;
|
||||
result = owner->getParameter(domain, uniqueIdentifier, &ownerWrapper,
|
||||
&streamWrapper, linearIndex);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = ownerWrapper.copyFrom(&streamWrapper, linearIndex);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
|
@@ -1,7 +1,6 @@
|
||||
#include "Service17Test.h"
|
||||
#include <FSFWConfig.h>
|
||||
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../objectmanager/SystemObject.h"
|
||||
#include "../tmtcpacket/pus/TmPacketStored.h"
|
||||
|
||||
@@ -18,25 +17,15 @@ Service17Test::~Service17Test() {
|
||||
ReturnValue_t Service17Test::handleRequest(uint8_t subservice) {
|
||||
switch(subservice) {
|
||||
case Subservice::CONNECTION_TEST: {
|
||||
#if FSFW_USE_PUS_C_TELEMETRY == 0
|
||||
TmPacketStoredPusA connectionPacket(apid, serviceId,
|
||||
TmPacketStored connectionPacket(apid, serviceId,
|
||||
Subservice::CONNECTION_TEST_REPORT, packetSubCounter++);
|
||||
#else
|
||||
TmPacketStoredPusC connectionPacket(apid, serviceId,
|
||||
Subservice::CONNECTION_TEST_REPORT, packetSubCounter++);
|
||||
#endif
|
||||
connectionPacket.sendPacket(requestQueue->getDefaultDestination(),
|
||||
requestQueue->getId());
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
case Subservice::EVENT_TRIGGER_TEST: {
|
||||
#if FSFW_USE_PUS_C_TELEMETRY == 0
|
||||
TmPacketStoredPusA connectionPacket(apid, serviceId,
|
||||
TmPacketStored connectionPacket(apid, serviceId,
|
||||
Subservice::CONNECTION_TEST_REPORT, packetSubCounter++);
|
||||
#else
|
||||
TmPacketStoredPusC connectionPacket(apid, serviceId,
|
||||
Subservice::CONNECTION_TEST_REPORT, packetSubCounter++);
|
||||
#endif
|
||||
connectionPacket.sendPacket(requestQueue->getDefaultDestination(),
|
||||
requestQueue->getId());
|
||||
triggerEvent(TEST, 1234, 5678);
|
||||
|
@@ -68,13 +68,8 @@ ReturnValue_t Service1TelecommandVerification::generateFailureReport(
|
||||
message->getTcSequenceControl(), message->getStep(),
|
||||
message->getErrorCode(), message->getParameter1(),
|
||||
message->getParameter2());
|
||||
#if FSFW_USE_PUS_C_TELEMETRY == 0
|
||||
TmPacketStoredPusA tmPacket(apid, serviceId, message->getReportId(),
|
||||
TmPacketStored tmPacket(apid, serviceId, message->getReportId(),
|
||||
packetSubCounter++, &report);
|
||||
#else
|
||||
TmPacketStoredPusC tmPacket(apid, serviceId, message->getReportId(),
|
||||
packetSubCounter++, &report);
|
||||
#endif
|
||||
ReturnValue_t result = tmPacket.sendPacket(tmQueue->getDefaultDestination(),
|
||||
tmQueue->getId());
|
||||
return result;
|
||||
@@ -84,13 +79,8 @@ ReturnValue_t Service1TelecommandVerification::generateSuccessReport(
|
||||
PusVerificationMessage *message) {
|
||||
SuccessReport report(message->getReportId(),message->getTcPacketId(),
|
||||
message->getTcSequenceControl(),message->getStep());
|
||||
#if FSFW_USE_PUS_C_TELEMETRY == 0
|
||||
TmPacketStoredPusA tmPacket(apid, serviceId, message->getReportId(),
|
||||
TmPacketStored tmPacket(apid, serviceId, message->getReportId(),
|
||||
packetSubCounter++, &report);
|
||||
#else
|
||||
TmPacketStoredPusC tmPacket(apid, serviceId, message->getReportId(),
|
||||
packetSubCounter++, &report);
|
||||
#endif
|
||||
ReturnValue_t result = tmPacket.sendPacket(tmQueue->getDefaultDestination(),
|
||||
tmQueue->getId());
|
||||
return result;
|
||||
|
@@ -52,13 +52,8 @@ ReturnValue_t Service5EventReporting::generateEventReport(
|
||||
{
|
||||
EventReport report(message.getEventId(),message.getReporter(),
|
||||
message.getParameter1(),message.getParameter2());
|
||||
#if FSFW_USE_PUS_C_TELEMETRY == 0
|
||||
TmPacketStoredPusA tmPacket(PusServiceBase::apid, PusServiceBase::serviceId,
|
||||
TmPacketStored tmPacket(PusServiceBase::apid, PusServiceBase::serviceId,
|
||||
message.getSeverity(), packetSubCounter++, &report);
|
||||
#else
|
||||
TmPacketStoredPusC tmPacket(PusServiceBase::apid, PusServiceBase::serviceId,
|
||||
message.getSeverity(), packetSubCounter++, &report);
|
||||
#endif
|
||||
ReturnValue_t result = tmPacket.sendPacket(
|
||||
requestQueue->getDefaultDestination(),requestQueue->getId());
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
|
@@ -1,7 +1,6 @@
|
||||
#ifndef FSFW_TIMEMANAGER_TIMESTAMPERIF_H_
|
||||
#define FSFW_TIMEMANAGER_TIMESTAMPERIF_H_
|
||||
|
||||
#include <FSFWConfig.h>
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
/**
|
||||
@@ -17,8 +16,8 @@ public:
|
||||
|
||||
//! This is a mission-specific constant and determines the total
|
||||
//! size reserved for timestamps.
|
||||
static const uint8_t MISSION_TIMESTAMP_SIZE = fsfwconfig::FSFW_MISSION_TIMESTAMP_SIZE;
|
||||
|
||||
//! TODO: Default define in FSFWConfig ?
|
||||
static const uint8_t MISSION_TIMESTAMP_SIZE = 8;
|
||||
virtual ReturnValue_t addTimeStamp(uint8_t* buffer,
|
||||
const uint8_t maxSize) = 0;
|
||||
virtual ~TimeStamperIF() {}
|
||||
|
@@ -4,9 +4,5 @@ target_sources(${LIB_FSFW_NAME}
|
||||
TcPacketStored.cpp
|
||||
TmPacketBase.cpp
|
||||
TmPacketMinimal.cpp
|
||||
TmPacketStoredPusA.cpp
|
||||
TmPacketStoredPusC.cpp
|
||||
TmPacketPusA.cpp
|
||||
TmPacketPusC.cpp
|
||||
TmPacketStoredBase.cpp
|
||||
TmPacketStored.cpp
|
||||
)
|
||||
|
@@ -3,66 +3,119 @@
|
||||
#include "../../globalfunctions/CRC.h"
|
||||
#include "../../globalfunctions/arrayprinter.h"
|
||||
#include "../../objectmanager/ObjectManagerIF.h"
|
||||
#include "../../serviceinterface/ServiceInterface.h"
|
||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../../timemanager/CCSDSTime.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
TimeStamperIF* TmPacketBase::timeStamper = nullptr;
|
||||
object_id_t TmPacketBase::timeStamperId = objects::NO_OBJECT;
|
||||
object_id_t TmPacketBase::timeStamperId = 0;
|
||||
|
||||
TmPacketBase::TmPacketBase(uint8_t* setData):
|
||||
SpacePacketBase(setData) {
|
||||
TmPacketBase::TmPacketBase(uint8_t* setData) :
|
||||
SpacePacketBase(setData) {
|
||||
tmData = reinterpret_cast<TmPacketPointer*>(setData);
|
||||
}
|
||||
|
||||
TmPacketBase::~TmPacketBase() {
|
||||
//Nothing to do.
|
||||
//Nothing to do.
|
||||
}
|
||||
|
||||
uint8_t TmPacketBase::getService() {
|
||||
return tmData->data_field.service_type;
|
||||
}
|
||||
|
||||
uint8_t TmPacketBase::getSubService() {
|
||||
return tmData->data_field.service_subtype;
|
||||
}
|
||||
|
||||
uint8_t* TmPacketBase::getSourceData() {
|
||||
return &tmData->data;
|
||||
}
|
||||
|
||||
uint16_t TmPacketBase::getSourceDataSize() {
|
||||
return getPacketDataLength() - getDataFieldSize() - CRC_SIZE + 1;
|
||||
return getPacketDataLength() - sizeof(tmData->data_field)
|
||||
- CRC_SIZE + 1;
|
||||
}
|
||||
|
||||
uint16_t TmPacketBase::getErrorControl() {
|
||||
uint32_t size = getSourceDataSize() + CRC_SIZE;
|
||||
uint8_t* p_to_buffer = getSourceData();
|
||||
return (p_to_buffer[size - 2] << 8) + p_to_buffer[size - 1];
|
||||
uint32_t size = getSourceDataSize() + CRC_SIZE;
|
||||
uint8_t* p_to_buffer = &tmData->data;
|
||||
return (p_to_buffer[size - 2] << 8) + p_to_buffer[size - 1];
|
||||
}
|
||||
|
||||
void TmPacketBase::setErrorControl() {
|
||||
uint32_t full_size = getFullSize();
|
||||
uint16_t crc = CRC::crc16ccitt(getWholeData(), full_size - CRC_SIZE);
|
||||
uint32_t size = getSourceDataSize();
|
||||
getSourceData()[size] = (crc & 0XFF00) >> 8; // CRCH
|
||||
getSourceData()[size + 1] = (crc) & 0X00FF; // CRCL
|
||||
uint32_t full_size = getFullSize();
|
||||
uint16_t crc = CRC::crc16ccitt(getWholeData(), full_size - CRC_SIZE);
|
||||
uint32_t size = getSourceDataSize();
|
||||
getSourceData()[size] = (crc & 0XFF00) >> 8; // CRCH
|
||||
getSourceData()[size + 1] = (crc) & 0X00FF; // CRCL
|
||||
}
|
||||
|
||||
ReturnValue_t TmPacketBase::getPacketTime(timeval* timestamp) const {
|
||||
size_t tempSize = 0;
|
||||
return CCSDSTime::convertFromCcsds(timestamp, getPacketTimeRaw(),
|
||||
&tempSize, getTimestampSize());
|
||||
void TmPacketBase::setData(const uint8_t* p_Data) {
|
||||
SpacePacketBase::setData(p_Data);
|
||||
tmData = (TmPacketPointer*) p_Data;
|
||||
}
|
||||
|
||||
void TmPacketBase::print() {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "TmPacketBase::print: " << std::endl;
|
||||
sif::debug << "TmPacketBase::print: " << std::endl;
|
||||
#endif
|
||||
arrayprinter::print(getWholeData(), getFullSize());
|
||||
arrayprinter::print(getWholeData(), getFullSize());
|
||||
}
|
||||
|
||||
bool TmPacketBase::checkAndSetStamper() {
|
||||
if (timeStamper == NULL) {
|
||||
timeStamper = objectManager->get<TimeStamperIF>(timeStamperId);
|
||||
if (timeStamper == NULL) {
|
||||
if (timeStamper == NULL) {
|
||||
timeStamper = objectManager->get<TimeStamperIF>(timeStamperId);
|
||||
if (timeStamper == NULL) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "TmPacketBase::checkAndSetStamper: Stamper not found!" << std::endl;
|
||||
#else
|
||||
sif::printWarning("TmPacketBase::checkAndSetStamper: Stamper not found!\n");
|
||||
sif::error << "TmPacketBase::checkAndSetStamper: Stamper not found!"
|
||||
<< std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ReturnValue_t TmPacketBase::getPacketTime(timeval* timestamp) const {
|
||||
size_t tempSize = 0;
|
||||
return CCSDSTime::convertFromCcsds(timestamp, tmData->data_field.time,
|
||||
&tempSize, sizeof(tmData->data_field.time));
|
||||
}
|
||||
|
||||
uint8_t* TmPacketBase::getPacketTimeRaw() const{
|
||||
return tmData->data_field.time;
|
||||
|
||||
}
|
||||
|
||||
void TmPacketBase::initializeTmPacket(uint16_t apid, uint8_t service,
|
||||
uint8_t subservice, uint8_t packetSubcounter) {
|
||||
//Set primary header:
|
||||
initSpacePacketHeader(false, true, apid);
|
||||
//Set data Field Header:
|
||||
//First, set to zero.
|
||||
memset(&tmData->data_field, 0, sizeof(tmData->data_field));
|
||||
|
||||
// NOTE: In PUS-C, the PUS Version is 2 and specified for the first 4 bits.
|
||||
// The other 4 bits of the first byte are the spacecraft time reference
|
||||
// status. To change to PUS-C, set 0b00100000.
|
||||
// Set CCSDS_secondary header flag to 0, version number to 001 and ack
|
||||
// to 0000
|
||||
tmData->data_field.version_type_ack = 0b00010000;
|
||||
tmData->data_field.service_type = service;
|
||||
tmData->data_field.service_subtype = subservice;
|
||||
tmData->data_field.subcounter = packetSubcounter;
|
||||
//Timestamp packet
|
||||
if (checkAndSetStamper()) {
|
||||
timeStamper->addTimeStamp(tmData->data_field.time,
|
||||
sizeof(tmData->data_field.time));
|
||||
}
|
||||
}
|
||||
|
||||
void TmPacketBase::setSourceDataSize(uint16_t size) {
|
||||
setPacketDataLength(size + sizeof(PUSTmDataFieldHeader) + CRC_SIZE - 1);
|
||||
}
|
||||
|
||||
size_t TmPacketBase::getTimestampSize() const {
|
||||
return sizeof(tmData->data_field.time);
|
||||
}
|
||||
|
@@ -10,6 +10,32 @@ namespace Factory{
|
||||
void setStaticFrameworkObjectIds();
|
||||
}
|
||||
|
||||
/**
|
||||
* This struct defines a byte-wise structured PUS TM Data Field Header.
|
||||
* Any optional fields in the header must be added or removed here.
|
||||
* Currently, no Destination field is present, but an eigth-byte representation
|
||||
* for a time tag.
|
||||
* @ingroup tmtcpackets
|
||||
*/
|
||||
struct PUSTmDataFieldHeader {
|
||||
uint8_t version_type_ack;
|
||||
uint8_t service_type;
|
||||
uint8_t service_subtype;
|
||||
uint8_t subcounter;
|
||||
// uint8_t destination;
|
||||
uint8_t time[TimeStamperIF::MISSION_TIMESTAMP_SIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
* This struct defines the data structure of a PUS Telecommand Packet when
|
||||
* accessed via a pointer.
|
||||
* @ingroup tmtcpackets
|
||||
*/
|
||||
struct TmPacketPointer {
|
||||
CCSDSPrimaryHeader primary;
|
||||
PUSTmDataFieldHeader data_field;
|
||||
uint8_t data;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class is the basic data handler for any ECSS PUS Telemetry packet.
|
||||
@@ -23,83 +49,61 @@ void setStaticFrameworkObjectIds();
|
||||
* @ingroup tmtcpackets
|
||||
*/
|
||||
class TmPacketBase : public SpacePacketBase {
|
||||
friend void (Factory::setStaticFrameworkObjectIds)();
|
||||
friend void (Factory::setStaticFrameworkObjectIds)();
|
||||
public:
|
||||
/**
|
||||
* This constant defines the minimum size of a valid PUS Telemetry Packet.
|
||||
*/
|
||||
static const uint32_t TM_PACKET_MIN_SIZE = (sizeof(CCSDSPrimaryHeader) +
|
||||
sizeof(PUSTmDataFieldHeader) + 2);
|
||||
//! Maximum size of a TM Packet in this mission.
|
||||
//! TODO: Make this dependant on a config variable.
|
||||
static const uint32_t MISSION_TM_PACKET_MAX_SIZE = 2048;
|
||||
//! First byte of secondary header for PUS-A packets.
|
||||
//! TODO: Maybe also support PUS-C via config?
|
||||
static const uint8_t VERSION_NUMBER_BYTE_PUS_A = 0b00010000;
|
||||
|
||||
//! Maximum size of a TM Packet in this mission.
|
||||
//! TODO: Make this dependant on a config variable.
|
||||
static const uint32_t MISSION_TM_PACKET_MAX_SIZE = 2048;
|
||||
//! First four bits of first byte of secondary header
|
||||
static const uint8_t VERSION_NUMBER_BYTE = 0b00010000;
|
||||
/**
|
||||
* This is the default constructor.
|
||||
* It sets its internal data pointer to the address passed and also
|
||||
* forwards the data pointer to the parent SpacePacketBase class.
|
||||
* @param set_address The position where the packet data lies.
|
||||
*/
|
||||
TmPacketBase( uint8_t* setData );
|
||||
/**
|
||||
* This is the empty default destructor.
|
||||
*/
|
||||
virtual ~TmPacketBase();
|
||||
|
||||
/**
|
||||
* This is the default constructor.
|
||||
* It sets its internal data pointer to the address passed and also
|
||||
* forwards the data pointer to the parent SpacePacketBase class.
|
||||
* @param set_address The position where the packet data lies.
|
||||
*/
|
||||
TmPacketBase( uint8_t* setData );
|
||||
/**
|
||||
* This is the empty default destructor.
|
||||
*/
|
||||
virtual ~TmPacketBase();
|
||||
/**
|
||||
* This is a getter for the packet's PUS Service ID, which is the second
|
||||
* byte of the Data Field Header.
|
||||
* @return The packet's PUS Service ID.
|
||||
*/
|
||||
uint8_t getService();
|
||||
/**
|
||||
* This is a getter for the packet's PUS Service Subtype, which is the
|
||||
* third byte of the Data Field Header.
|
||||
* @return The packet's PUS Service Subtype.
|
||||
*/
|
||||
uint8_t getSubService();
|
||||
/**
|
||||
* This is a getter for a pointer to the packet's Source data.
|
||||
*
|
||||
* These are the bytes that follow after the Data Field Header. They form
|
||||
* the packet's source data.
|
||||
* @return A pointer to the PUS Source Data.
|
||||
*/
|
||||
uint8_t* getSourceData();
|
||||
/**
|
||||
* This method calculates the size of the PUS Source data field.
|
||||
*
|
||||
* It takes the information stored in the CCSDS Packet Data Length field
|
||||
* and subtracts the Data Field Header size and the CRC size.
|
||||
* @return The size of the PUS Source Data (without Error Control field)
|
||||
*/
|
||||
uint16_t getSourceDataSize();
|
||||
|
||||
/**
|
||||
* This is a getter for the packet's PUS Service ID, which is the second
|
||||
* byte of the Data Field Header.
|
||||
* @return The packet's PUS Service ID.
|
||||
*/
|
||||
virtual uint8_t getService() = 0;
|
||||
/**
|
||||
* This is a getter for the packet's PUS Service Subtype, which is the
|
||||
* third byte of the Data Field Header.
|
||||
* @return The packet's PUS Service Subtype.
|
||||
*/
|
||||
virtual uint8_t getSubService() = 0;
|
||||
/**
|
||||
* This is a getter for a pointer to the packet's Source data.
|
||||
*
|
||||
* These are the bytes that follow after the Data Field Header. They form
|
||||
* the packet's source data.
|
||||
* @return A pointer to the PUS Source Data.
|
||||
*/
|
||||
virtual uint8_t* getSourceData() = 0;
|
||||
/**
|
||||
* This method calculates the size of the PUS Source data field.
|
||||
*
|
||||
* It takes the information stored in the CCSDS Packet Data Length field
|
||||
* and subtracts the Data Field Header size and the CRC size.
|
||||
* @return The size of the PUS Source Data (without Error Control field)
|
||||
*/
|
||||
virtual uint16_t getSourceDataSize() = 0;
|
||||
|
||||
/**
|
||||
* Get size of data field which can differ based on implementation
|
||||
* @return
|
||||
*/
|
||||
virtual uint16_t getDataFieldSize() = 0;
|
||||
|
||||
virtual size_t getPacketMinimumSize() const = 0;
|
||||
|
||||
/**
|
||||
* Interprets the "time"-field in the secondary header and returns it in
|
||||
* timeval format.
|
||||
* @return Converted timestamp of packet.
|
||||
*/
|
||||
virtual ReturnValue_t getPacketTime(timeval* timestamp) const;
|
||||
/**
|
||||
* Returns a raw pointer to the beginning of the time field.
|
||||
* @return Raw pointer to time field.
|
||||
*/
|
||||
virtual uint8_t* getPacketTimeRaw() const = 0;
|
||||
|
||||
virtual size_t getTimestampSize() const = 0;
|
||||
|
||||
/**
|
||||
* This is a debugging helper method that prints the whole packet content
|
||||
* to the screen.
|
||||
*/
|
||||
void print();
|
||||
/**
|
||||
* With this method, the Error Control Field is updated to match the
|
||||
* current content of the packet. This method is not protected because
|
||||
@@ -107,24 +111,79 @@ public:
|
||||
* like the sequence count.
|
||||
*/
|
||||
void setErrorControl();
|
||||
/**
|
||||
* This getter returns the Error Control Field of the packet.
|
||||
*
|
||||
* The field is placed after any possible Source Data. If no
|
||||
* Source Data is present there's still an Error Control field. It is
|
||||
* supposed to be a 16bit-CRC.
|
||||
* @return The PUS Error Control
|
||||
*/
|
||||
uint16_t getErrorControl();
|
||||
|
||||
/**
|
||||
* This getter returns the Error Control Field of the packet.
|
||||
*
|
||||
* The field is placed after any possible Source Data. If no
|
||||
* Source Data is present there's still an Error Control field. It is
|
||||
* supposed to be a 16bit-CRC.
|
||||
* @return The PUS Error Control
|
||||
*/
|
||||
uint16_t getErrorControl();
|
||||
|
||||
/**
|
||||
* This is a debugging helper method that prints the whole packet content
|
||||
* to the screen.
|
||||
*/
|
||||
void print();
|
||||
/**
|
||||
* Interprets the "time"-field in the secondary header and returns it in
|
||||
* timeval format.
|
||||
* @return Converted timestamp of packet.
|
||||
*/
|
||||
ReturnValue_t getPacketTime(timeval* timestamp) const;
|
||||
/**
|
||||
* Returns a raw pointer to the beginning of the time field.
|
||||
* @return Raw pointer to time field.
|
||||
*/
|
||||
uint8_t* getPacketTimeRaw() const;
|
||||
|
||||
size_t getTimestampSize() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* A pointer to a structure which defines the data structure of
|
||||
* the packet's data.
|
||||
*
|
||||
* To be hardware-safe, all elements are of byte size.
|
||||
*/
|
||||
TmPacketPointer* tmData;
|
||||
/**
|
||||
* The timeStamper is responsible for adding a timestamp to the packet.
|
||||
* It is initialized lazy.
|
||||
*/
|
||||
static TimeStamperIF* timeStamper;
|
||||
//! The ID to use when looking for a time stamper.
|
||||
static object_id_t timeStamperId;
|
||||
|
||||
/**
|
||||
* The timeStamper is responsible for adding a timestamp to the packet.
|
||||
* It is initialized lazy.
|
||||
* Initializes the Tm Packet header.
|
||||
* Does set the timestamp (to now), but not the error control field.
|
||||
* @param apid APID used.
|
||||
* @param service PUS Service
|
||||
* @param subservice PUS Subservice
|
||||
* @param packetSubcounter Additional subcounter used.
|
||||
*/
|
||||
static TimeStamperIF* timeStamper;
|
||||
//! The ID to use when looking for a time stamper.
|
||||
static object_id_t timeStamperId;
|
||||
void initializeTmPacket(uint16_t apid, uint8_t service, uint8_t subservice,
|
||||
uint8_t packetSubcounter);
|
||||
|
||||
/**
|
||||
* With this method, the packet data pointer can be redirected to another
|
||||
* location.
|
||||
*
|
||||
* This call overwrites the parent's setData method to set both its
|
||||
* @c tc_data pointer and the parent's @c data pointer.
|
||||
*
|
||||
* @param p_data A pointer to another PUS Telemetry Packet.
|
||||
*/
|
||||
void setData( const uint8_t* pData );
|
||||
|
||||
/**
|
||||
* In case data was filled manually (almost never the case).
|
||||
* @param size Size of source data (without CRC and data filed header!).
|
||||
*/
|
||||
void setSourceDataSize(uint16_t size);
|
||||
|
||||
/**
|
||||
* Checks if a time stamper is available and tries to set it if not.
|
||||
|
@@ -1,87 +0,0 @@
|
||||
#include "TmPacketPusA.h"
|
||||
#include "TmPacketBase.h"
|
||||
|
||||
#include "../../globalfunctions/CRC.h"
|
||||
#include "../../globalfunctions/arrayprinter.h"
|
||||
#include "../../objectmanager/ObjectManagerIF.h"
|
||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../../timemanager/CCSDSTime.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
||||
TmPacketPusA::TmPacketPusA(uint8_t* setData) : TmPacketBase(setData) {
|
||||
tmData = reinterpret_cast<TmPacketPointerPusA*>(setData);
|
||||
}
|
||||
|
||||
TmPacketPusA::~TmPacketPusA() {
|
||||
//Nothing to do.
|
||||
}
|
||||
|
||||
uint8_t TmPacketPusA::getService() {
|
||||
return tmData->data_field.service_type;
|
||||
}
|
||||
|
||||
uint8_t TmPacketPusA::getSubService() {
|
||||
return tmData->data_field.service_subtype;
|
||||
}
|
||||
|
||||
uint8_t* TmPacketPusA::getSourceData() {
|
||||
return &tmData->data;
|
||||
}
|
||||
|
||||
uint16_t TmPacketPusA::getSourceDataSize() {
|
||||
return getPacketDataLength() - sizeof(tmData->data_field)
|
||||
- CRC_SIZE + 1;
|
||||
}
|
||||
|
||||
void TmPacketPusA::setData(const uint8_t* p_Data) {
|
||||
SpacePacketBase::setData(p_Data);
|
||||
tmData = (TmPacketPointerPusA*) p_Data;
|
||||
}
|
||||
|
||||
|
||||
size_t TmPacketPusA::getPacketMinimumSize() const {
|
||||
return TM_PACKET_MIN_SIZE;
|
||||
}
|
||||
|
||||
uint16_t TmPacketPusA::getDataFieldSize() {
|
||||
return sizeof(PUSTmDataFieldHeaderPusA);
|
||||
}
|
||||
|
||||
uint8_t* TmPacketPusA::getPacketTimeRaw() const {
|
||||
return tmData->data_field.time;
|
||||
|
||||
}
|
||||
|
||||
void TmPacketPusA::initializeTmPacket(uint16_t apid, uint8_t service,
|
||||
uint8_t subservice, uint8_t packetSubcounter) {
|
||||
//Set primary header:
|
||||
initSpacePacketHeader(false, true, apid);
|
||||
//Set data Field Header:
|
||||
//First, set to zero.
|
||||
memset(&tmData->data_field, 0, sizeof(tmData->data_field));
|
||||
|
||||
// NOTE: In PUS-C, the PUS Version is 2 and specified for the first 4 bits.
|
||||
// The other 4 bits of the first byte are the spacecraft time reference
|
||||
// status. To change to PUS-C, set 0b00100000.
|
||||
// Set CCSDS_secondary header flag to 0, version number to 001 and ack
|
||||
// to 0000
|
||||
tmData->data_field.version_type_ack = 0b00010000;
|
||||
tmData->data_field.service_type = service;
|
||||
tmData->data_field.service_subtype = subservice;
|
||||
tmData->data_field.subcounter = packetSubcounter;
|
||||
//Timestamp packet
|
||||
if (TmPacketBase::checkAndSetStamper()) {
|
||||
timeStamper->addTimeStamp(tmData->data_field.time,
|
||||
sizeof(tmData->data_field.time));
|
||||
}
|
||||
}
|
||||
|
||||
void TmPacketPusA::setSourceDataSize(uint16_t size) {
|
||||
setPacketDataLength(size + sizeof(PUSTmDataFieldHeaderPusA) + CRC_SIZE - 1);
|
||||
}
|
||||
|
||||
size_t TmPacketPusA::getTimestampSize() const {
|
||||
return sizeof(tmData->data_field.time);
|
||||
}
|
@@ -1,129 +0,0 @@
|
||||
#ifndef FSFW_TMTCPACKET_PUS_TMPACKETPUSA_H_
|
||||
#define FSFW_TMTCPACKET_PUS_TMPACKETPUSA_H_
|
||||
|
||||
#include "TmPacketBase.h"
|
||||
#include "../SpacePacketBase.h"
|
||||
#include "../../timemanager/TimeStamperIF.h"
|
||||
#include "../../timemanager/Clock.h"
|
||||
#include "../../objectmanager/SystemObjectIF.h"
|
||||
|
||||
namespace Factory{
|
||||
void setStaticFrameworkObjectIds();
|
||||
}
|
||||
|
||||
/**
|
||||
* This struct defines a byte-wise structured PUS TM Data Field Header.
|
||||
* Any optional fields in the header must be added or removed here.
|
||||
* Currently, no Destination field is present, but an eigth-byte representation
|
||||
* for a time tag.
|
||||
* @ingroup tmtcpackets
|
||||
*/
|
||||
struct PUSTmDataFieldHeaderPusA {
|
||||
uint8_t version_type_ack;
|
||||
uint8_t service_type;
|
||||
uint8_t service_subtype;
|
||||
uint8_t subcounter;
|
||||
// uint8_t destination;
|
||||
uint8_t time[TimeStamperIF::MISSION_TIMESTAMP_SIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
* This struct defines the data structure of a PUS Telecommand Packet when
|
||||
* accessed via a pointer.
|
||||
* @ingroup tmtcpackets
|
||||
*/
|
||||
struct TmPacketPointerPusA {
|
||||
CCSDSPrimaryHeader primary;
|
||||
PUSTmDataFieldHeaderPusA data_field;
|
||||
uint8_t data;
|
||||
};
|
||||
|
||||
/**
|
||||
* PUS A packet implementation
|
||||
* @ingroup tmtcpackets
|
||||
*/
|
||||
class TmPacketPusA: public TmPacketBase {
|
||||
friend void (Factory::setStaticFrameworkObjectIds)();
|
||||
public:
|
||||
/**
|
||||
* This constant defines the minimum size of a valid PUS Telemetry Packet.
|
||||
*/
|
||||
static const uint32_t TM_PACKET_MIN_SIZE = (sizeof(CCSDSPrimaryHeader) +
|
||||
sizeof(PUSTmDataFieldHeaderPusA) + 2);
|
||||
//! Maximum size of a TM Packet in this mission.
|
||||
//! TODO: Make this dependant on a config variable.
|
||||
static const uint32_t MISSION_TM_PACKET_MAX_SIZE = 2048;
|
||||
|
||||
/**
|
||||
* This is the default constructor.
|
||||
* It sets its internal data pointer to the address passed and also
|
||||
* forwards the data pointer to the parent SpacePacketBase class.
|
||||
* @param set_address The position where the packet data lies.
|
||||
*/
|
||||
TmPacketPusA( uint8_t* setData );
|
||||
/**
|
||||
* This is the empty default destructor.
|
||||
*/
|
||||
virtual ~TmPacketPusA();
|
||||
|
||||
/* TmPacketBase implementations */
|
||||
uint8_t getService() override;
|
||||
uint8_t getSubService() override;
|
||||
uint8_t* getSourceData() override;
|
||||
uint16_t getSourceDataSize() override;
|
||||
uint16_t getDataFieldSize() override;
|
||||
|
||||
/**
|
||||
* Returns a raw pointer to the beginning of the time field.
|
||||
* @return Raw pointer to time field.
|
||||
*/
|
||||
uint8_t* getPacketTimeRaw() const override;
|
||||
size_t getTimestampSize() const override;
|
||||
|
||||
size_t getPacketMinimumSize() const override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* A pointer to a structure which defines the data structure of
|
||||
* the packet's data.
|
||||
*
|
||||
* To be hardware-safe, all elements are of byte size.
|
||||
*/
|
||||
TmPacketPointerPusA* tmData;
|
||||
|
||||
/**
|
||||
* Initializes the Tm Packet header.
|
||||
* Does set the timestamp (to now), but not the error control field.
|
||||
* @param apid APID used.
|
||||
* @param service PUS Service
|
||||
* @param subservice PUS Subservice
|
||||
* @param packetSubcounter Additional subcounter used.
|
||||
*/
|
||||
void initializeTmPacket(uint16_t apid, uint8_t service, uint8_t subservice,
|
||||
uint8_t packetSubcounter);
|
||||
|
||||
/**
|
||||
* With this method, the packet data pointer can be redirected to another
|
||||
* location.
|
||||
*
|
||||
* This call overwrites the parent's setData method to set both its
|
||||
* @c tc_data pointer and the parent's @c data pointer.
|
||||
*
|
||||
* @param p_data A pointer to another PUS Telemetry Packet.
|
||||
*/
|
||||
void setData( const uint8_t* pData );
|
||||
|
||||
/**
|
||||
* In case data was filled manually (almost never the case).
|
||||
* @param size Size of source data (without CRC and data filed header!).
|
||||
*/
|
||||
void setSourceDataSize(uint16_t size);
|
||||
|
||||
/**
|
||||
* Checks if a time stamper is available and tries to set it if not.
|
||||
* @return Returns false if setting failed.
|
||||
*/
|
||||
bool checkAndSetStamper();
|
||||
};
|
||||
|
||||
#endif /* FSFW_TMTCPACKET_PUS_TMPACKETPUSA_H_ */
|
@@ -1,87 +0,0 @@
|
||||
#include "TmPacketPusC.h"
|
||||
#include "TmPacketBase.h"
|
||||
|
||||
#include "../../globalfunctions/CRC.h"
|
||||
#include "../../globalfunctions/arrayprinter.h"
|
||||
#include "../../objectmanager/ObjectManagerIF.h"
|
||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../../timemanager/CCSDSTime.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
||||
TmPacketPusC::TmPacketPusC(uint8_t* setData) : TmPacketBase(setData) {
|
||||
tmData = reinterpret_cast<TmPacketPointerPusC*>(setData);
|
||||
}
|
||||
|
||||
TmPacketPusC::~TmPacketPusC() {
|
||||
//Nothing to do.
|
||||
}
|
||||
|
||||
uint8_t TmPacketPusC::getService() {
|
||||
return tmData->dataField.serviceType;
|
||||
}
|
||||
|
||||
uint8_t TmPacketPusC::getSubService() {
|
||||
return tmData->dataField.serviceSubtype;
|
||||
}
|
||||
|
||||
uint8_t* TmPacketPusC::getSourceData() {
|
||||
return &tmData->data;
|
||||
}
|
||||
|
||||
uint16_t TmPacketPusC::getSourceDataSize() {
|
||||
return getPacketDataLength() - sizeof(tmData->dataField) - CRC_SIZE + 1;
|
||||
}
|
||||
|
||||
void TmPacketPusC::setData(const uint8_t* p_Data) {
|
||||
SpacePacketBase::setData(p_Data);
|
||||
tmData = (TmPacketPointerPusC*) p_Data;
|
||||
}
|
||||
|
||||
|
||||
size_t TmPacketPusC::getPacketMinimumSize() const {
|
||||
return TM_PACKET_MIN_SIZE;
|
||||
}
|
||||
|
||||
uint16_t TmPacketPusC::getDataFieldSize() {
|
||||
return sizeof(PUSTmDataFieldHeaderPusC);
|
||||
}
|
||||
|
||||
uint8_t* TmPacketPusC::getPacketTimeRaw() const{
|
||||
return tmData->dataField.time;
|
||||
|
||||
}
|
||||
|
||||
void TmPacketPusC::initializeTmPacket(uint16_t apid, uint8_t service,
|
||||
uint8_t subservice, uint16_t packetSubcounter, uint16_t destinationId,
|
||||
uint8_t timeRefField) {
|
||||
//Set primary header:
|
||||
initSpacePacketHeader(false, true, apid);
|
||||
//Set data Field Header:
|
||||
//First, set to zero.
|
||||
memset(&tmData->dataField, 0, sizeof(tmData->dataField));
|
||||
|
||||
/* Only account for last 4 bytes for time reference field */
|
||||
timeRefField &= 0b1111;
|
||||
tmData->dataField.versionTimeReferenceField = VERSION_NUMBER_BYTE | timeRefField;
|
||||
tmData->dataField.serviceType = service;
|
||||
tmData->dataField.serviceSubtype = subservice;
|
||||
tmData->dataField.subcounterMsb = packetSubcounter << 8 & 0xff;
|
||||
tmData->dataField.subcounterLsb = packetSubcounter & 0xff;
|
||||
tmData->dataField.destinationIdMsb = destinationId << 8 & 0xff;
|
||||
tmData->dataField.destinationIdLsb = destinationId & 0xff;
|
||||
//Timestamp packet
|
||||
if (TmPacketBase::checkAndSetStamper()) {
|
||||
timeStamper->addTimeStamp(tmData->dataField.time,
|
||||
sizeof(tmData->dataField.time));
|
||||
}
|
||||
}
|
||||
|
||||
void TmPacketPusC::setSourceDataSize(uint16_t size) {
|
||||
setPacketDataLength(size + sizeof(PUSTmDataFieldHeaderPusC) + CRC_SIZE - 1);
|
||||
}
|
||||
|
||||
size_t TmPacketPusC::getTimestampSize() const {
|
||||
return sizeof(tmData->dataField.time);
|
||||
}
|
@@ -1,126 +0,0 @@
|
||||
#ifndef FSFW_TMTCPACKET_PUS_TMPACKETPUSC_H_
|
||||
#define FSFW_TMTCPACKET_PUS_TMPACKETPUSC_H_
|
||||
|
||||
#include "TmPacketBase.h"
|
||||
#include "../SpacePacketBase.h"
|
||||
#include "../../timemanager/TimeStamperIF.h"
|
||||
#include "../../timemanager/Clock.h"
|
||||
#include "../../objectmanager/SystemObjectIF.h"
|
||||
|
||||
namespace Factory{
|
||||
void setStaticFrameworkObjectIds();
|
||||
}
|
||||
|
||||
/**
|
||||
* This struct defines a byte-wise structured PUS TM Data Field Header.
|
||||
* Any optional fields in the header must be added or removed here.
|
||||
* Currently, no Destination field is present, but an eigth-byte representation
|
||||
* for a time tag.
|
||||
* @ingroup tmtcpackets
|
||||
*/
|
||||
struct PUSTmDataFieldHeaderPusC {
|
||||
uint8_t versionTimeReferenceField;
|
||||
uint8_t serviceType;
|
||||
uint8_t serviceSubtype;
|
||||
uint8_t subcounterMsb;
|
||||
uint8_t subcounterLsb;
|
||||
uint8_t destinationIdMsb;
|
||||
uint8_t destinationIdLsb;
|
||||
uint8_t time[TimeStamperIF::MISSION_TIMESTAMP_SIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
* This struct defines the data structure of a PUS Telecommand Packet when
|
||||
* accessed via a pointer.
|
||||
* @ingroup tmtcpackets
|
||||
*/
|
||||
struct TmPacketPointerPusC {
|
||||
CCSDSPrimaryHeader primary;
|
||||
PUSTmDataFieldHeaderPusC dataField;
|
||||
uint8_t data;
|
||||
};
|
||||
|
||||
/**
|
||||
* PUS A packet implementation
|
||||
* @ingroup tmtcpackets
|
||||
*/
|
||||
class TmPacketPusC: public TmPacketBase {
|
||||
friend void (Factory::setStaticFrameworkObjectIds)();
|
||||
public:
|
||||
/**
|
||||
* This constant defines the minimum size of a valid PUS Telemetry Packet.
|
||||
*/
|
||||
static const uint32_t TM_PACKET_MIN_SIZE = (sizeof(CCSDSPrimaryHeader) +
|
||||
sizeof(PUSTmDataFieldHeaderPusC) + 2);
|
||||
//! Maximum size of a TM Packet in this mission.
|
||||
//! TODO: Make this dependant on a config variable.
|
||||
static const uint32_t MISSION_TM_PACKET_MAX_SIZE = 2048;
|
||||
|
||||
/**
|
||||
* This is the default constructor.
|
||||
* It sets its internal data pointer to the address passed and also
|
||||
* forwards the data pointer to the parent SpacePacketBase class.
|
||||
* @param set_address The position where the packet data lies.
|
||||
*/
|
||||
TmPacketPusC( uint8_t* setData );
|
||||
/**
|
||||
* This is the empty default destructor.
|
||||
*/
|
||||
virtual ~TmPacketPusC();
|
||||
|
||||
/* TmPacketBase implementations */
|
||||
uint8_t getService() override;
|
||||
uint8_t getSubService() override;
|
||||
uint8_t* getSourceData() override;
|
||||
uint16_t getSourceDataSize() override;
|
||||
uint16_t getDataFieldSize() override;
|
||||
|
||||
/**
|
||||
* Returns a raw pointer to the beginning of the time field.
|
||||
* @return Raw pointer to time field.
|
||||
*/
|
||||
uint8_t* getPacketTimeRaw() const override;
|
||||
size_t getTimestampSize() const override;
|
||||
|
||||
size_t getPacketMinimumSize() const override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* A pointer to a structure which defines the data structure of
|
||||
* the packet's data.
|
||||
*
|
||||
* To be hardware-safe, all elements are of byte size.
|
||||
*/
|
||||
TmPacketPointerPusC* tmData;
|
||||
|
||||
/**
|
||||
* Initializes the Tm Packet header.
|
||||
* Does set the timestamp (to now), but not the error control field.
|
||||
* @param apid APID used.
|
||||
* @param service PUS Service
|
||||
* @param subservice PUS Subservice
|
||||
* @param packetSubcounter Additional subcounter used.
|
||||
*/
|
||||
void initializeTmPacket(uint16_t apid, uint8_t service, uint8_t subservice,
|
||||
uint16_t packetSubcounter, uint16_t destinationId = 0, uint8_t timeRefField = 0);
|
||||
|
||||
/**
|
||||
* With this method, the packet data pointer can be redirected to another
|
||||
* location.
|
||||
*
|
||||
* This call overwrites the parent's setData method to set both its
|
||||
* @c tc_data pointer and the parent's @c data pointer.
|
||||
*
|
||||
* @param p_data A pointer to another PUS Telemetry Packet.
|
||||
*/
|
||||
void setData( const uint8_t* pData );
|
||||
|
||||
/**
|
||||
* In case data was filled manually (almost never the case).
|
||||
* @param size Size of source data (without CRC and data filed header!).
|
||||
*/
|
||||
void setSourceDataSize(uint16_t size);
|
||||
|
||||
};
|
||||
|
||||
#endif /* FSFW_TMTCPACKET_PUS_TMPACKETPUSC_H_ */
|
147
tmtcpacket/pus/TmPacketStored.cpp
Normal file
147
tmtcpacket/pus/TmPacketStored.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
#include "TmPacketStored.h"
|
||||
|
||||
#include "../../objectmanager/ObjectManagerIF.h"
|
||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../../tmtcservices/TmTcMessage.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
StorageManagerIF *TmPacketStored::store = nullptr;
|
||||
InternalErrorReporterIF *TmPacketStored::internalErrorReporter = nullptr;
|
||||
|
||||
TmPacketStored::TmPacketStored(store_address_t setAddress) :
|
||||
TmPacketBase(nullptr), storeAddress(setAddress) {
|
||||
setStoreAddress(storeAddress);
|
||||
}
|
||||
|
||||
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) :
|
||||
TmPacketBase(NULL) {
|
||||
storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
|
||||
if (not checkAndSetStore()) {
|
||||
return;
|
||||
}
|
||||
uint8_t *pData = nullptr;
|
||||
ReturnValue_t returnValue = store->getFreeElement(&storeAddress,
|
||||
(TmPacketBase::TM_PACKET_MIN_SIZE + size + headerSize), &pData);
|
||||
|
||||
if (returnValue != store->RETURN_OK) {
|
||||
checkAndReportLostTm();
|
||||
return;
|
||||
}
|
||||
setData(pData);
|
||||
initializeTmPacket(apid, service, subservice, packetSubcounter);
|
||||
memcpy(getSourceData(), headerData, headerSize);
|
||||
memcpy(getSourceData() + headerSize, data, size);
|
||||
setPacketDataLength(
|
||||
size + headerSize + sizeof(PUSTmDataFieldHeader) + CRC_SIZE - 1);
|
||||
}
|
||||
|
||||
TmPacketStored::TmPacketStored(uint16_t apid, uint8_t service,
|
||||
uint8_t subservice, uint8_t packetSubcounter, SerializeIF *content,
|
||||
SerializeIF *header) :
|
||||
TmPacketBase(NULL) {
|
||||
storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
|
||||
if (not checkAndSetStore()) {
|
||||
return;
|
||||
}
|
||||
size_t sourceDataSize = 0;
|
||||
if (content != NULL) {
|
||||
sourceDataSize += content->getSerializedSize();
|
||||
}
|
||||
if (header != NULL) {
|
||||
sourceDataSize += header->getSerializedSize();
|
||||
}
|
||||
uint8_t *p_data = NULL;
|
||||
ReturnValue_t returnValue = store->getFreeElement(&storeAddress,
|
||||
(TmPacketBase::TM_PACKET_MIN_SIZE + sourceDataSize), &p_data);
|
||||
if (returnValue != store->RETURN_OK) {
|
||||
checkAndReportLostTm();
|
||||
}
|
||||
setData(p_data);
|
||||
initializeTmPacket(apid, service, subservice, packetSubcounter);
|
||||
uint8_t *putDataHere = getSourceData();
|
||||
size_t size = 0;
|
||||
if (header != NULL) {
|
||||
header->serialize(&putDataHere, &size, sourceDataSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
}
|
||||
if (content != NULL) {
|
||||
content->serialize(&putDataHere, &size, sourceDataSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
}
|
||||
setPacketDataLength(
|
||||
sourceDataSize + sizeof(PUSTmDataFieldHeader) + CRC_SIZE - 1);
|
||||
}
|
||||
|
||||
store_address_t TmPacketStored::getStoreAddress() {
|
||||
return storeAddress;
|
||||
}
|
||||
|
||||
void TmPacketStored::deletePacket() {
|
||||
store->deleteData(storeAddress);
|
||||
storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
|
||||
setData(nullptr);
|
||||
}
|
||||
|
||||
void TmPacketStored::setStoreAddress(store_address_t setAddress) {
|
||||
storeAddress = setAddress;
|
||||
const uint8_t* tempData = nullptr;
|
||||
size_t tempSize;
|
||||
if (not checkAndSetStore()) {
|
||||
return;
|
||||
}
|
||||
ReturnValue_t status = store->getData(storeAddress, &tempData, &tempSize);
|
||||
if (status == StorageManagerIF::RETURN_OK) {
|
||||
setData(tempData);
|
||||
} else {
|
||||
setData(nullptr);
|
||||
storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
|
||||
}
|
||||
}
|
||||
|
||||
bool TmPacketStored::checkAndSetStore() {
|
||||
if (store == nullptr) {
|
||||
store = objectManager->get<StorageManagerIF>(objects::TM_STORE);
|
||||
if (store == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "TmPacketStored::TmPacketStored: TM Store not found!"
|
||||
<< std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ReturnValue_t TmPacketStored::sendPacket(MessageQueueId_t destination,
|
||||
MessageQueueId_t sentFrom, bool doErrorReporting) {
|
||||
if (getWholeData() == nullptr) {
|
||||
//SHOULDDO: More decent code.
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
TmTcMessage tmMessage(getStoreAddress());
|
||||
ReturnValue_t result = MessageQueueSenderIF::sendMessage(destination,
|
||||
&tmMessage, sentFrom);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
deletePacket();
|
||||
if (doErrorReporting) {
|
||||
checkAndReportLostTm();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
//SHOULDDO: In many cases, some counter is incremented for successfully sent packets. The check is often not done, but just incremented.
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
|
||||
}
|
||||
|
||||
void TmPacketStored::checkAndReportLostTm() {
|
||||
if (internalErrorReporter == nullptr) {
|
||||
internalErrorReporter = objectManager->get<InternalErrorReporterIF>(
|
||||
objects::INTERNAL_ERROR_REPORTER);
|
||||
}
|
||||
if (internalErrorReporter != nullptr) {
|
||||
internalErrorReporter->lostTm();
|
||||
}
|
||||
}
|
@@ -1,13 +1,108 @@
|
||||
#ifndef FSFW_TMTCPACKET_PUS_TMPACKETSTORED_H_
|
||||
#define FSFW_TMTCPACKET_PUS_TMPACKETSTORED_H_
|
||||
|
||||
#include <FSFWConfig.h>
|
||||
#include "TmPacketBase.h"
|
||||
|
||||
#if FSFW_USE_PUS_C_TELEMETRY == 1
|
||||
#include "TmPacketStoredPusC.h"
|
||||
#else
|
||||
#include "TmPacketStoredPusA.h"
|
||||
#endif
|
||||
#include "../../serialize/SerializeIF.h"
|
||||
#include "../../storagemanager/StorageManagerIF.h"
|
||||
#include "../../internalError/InternalErrorReporterIF.h"
|
||||
#include "../../ipc/MessageQueueSenderIF.h"
|
||||
|
||||
/**
|
||||
* This class generates a ECSS PUS Telemetry packet within a given
|
||||
* intermediate storage.
|
||||
* As most packets are passed between tasks with the help of a storage
|
||||
* anyway, it seems logical to create a Packet-In-Storage access class
|
||||
* which saves the user almost all storage handling operation.
|
||||
* Packets can both be newly created with the class and be "linked" to
|
||||
* packets in a store with the help of a storeAddress.
|
||||
* @ingroup tmtcpackets
|
||||
*/
|
||||
class TmPacketStored : public TmPacketBase {
|
||||
public:
|
||||
/**
|
||||
* This is a default constructor which does not set the data pointer.
|
||||
* However, it does try to set the packet store.
|
||||
*/
|
||||
TmPacketStored( store_address_t setAddress );
|
||||
/**
|
||||
* With this constructor, new space is allocated in the packet store and
|
||||
* a new PUS Telemetry Packet is created there.
|
||||
* Packet Application Data passed in data is copied into the packet.
|
||||
* The Application data is passed in two parts, first a header, then a
|
||||
* data field. This allows building a Telemetry Packet from two separate
|
||||
* data sources.
|
||||
* @param apid Sets the packet's APID field.
|
||||
* @param service Sets the packet's Service ID field.
|
||||
* This specifies the source service.
|
||||
* @param subservice Sets the packet's Service Subtype field.
|
||||
* This specifies the source sub-service.
|
||||
* @param packet_counter Sets the Packet counter field of this packet
|
||||
* @param data The payload data to be copied to the
|
||||
* Application Data Field
|
||||
* @param size The amount of data to be copied.
|
||||
* @param headerData The header Data of the Application field,
|
||||
* will be copied in front of data
|
||||
* @param headerSize The size of the headerDataF
|
||||
*/
|
||||
TmPacketStored( uint16_t apid, uint8_t service, uint8_t subservice,
|
||||
uint8_t packet_counter = 0, const uint8_t* data = nullptr,
|
||||
uint32_t size = 0, const uint8_t* headerData = nullptr,
|
||||
uint32_t headerSize = 0);
|
||||
/**
|
||||
* Another ctor to directly pass structured content and header data to the
|
||||
* packet to avoid additional buffers.
|
||||
*/
|
||||
TmPacketStored( uint16_t apid, uint8_t service, uint8_t subservice,
|
||||
uint8_t packet_counter, SerializeIF* content,
|
||||
SerializeIF* header = nullptr);
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
store_address_t getStoreAddress();
|
||||
/**
|
||||
* With this call, the packet is deleted.
|
||||
* It removes itself from the store and sets its data pointer to NULL.
|
||||
*/
|
||||
void deletePacket();
|
||||
/**
|
||||
* With this call, a packet can be linked to another store. This is useful
|
||||
* if the packet is a class member and used for more than one packet.
|
||||
* @param setAddress The new packet id to link to.
|
||||
*/
|
||||
void setStoreAddress( store_address_t setAddress );
|
||||
|
||||
ReturnValue_t sendPacket( MessageQueueId_t destination,
|
||||
MessageQueueId_t sentFrom, bool doErrorReporting = true );
|
||||
private:
|
||||
/**
|
||||
* This is a pointer to the store all instances of the class use.
|
||||
* If the store is not yet set (i.e. @c store is NULL), every constructor
|
||||
* call tries to set it and throws an error message in case of failures.
|
||||
* The default store is objects::TM_STORE.
|
||||
*/
|
||||
static StorageManagerIF* store;
|
||||
|
||||
static InternalErrorReporterIF *internalErrorReporter;
|
||||
|
||||
/**
|
||||
* The address where the packet data of the object instance is stored.
|
||||
*/
|
||||
store_address_t storeAddress;
|
||||
/**
|
||||
* A helper method to check if a store is assigned to the class.
|
||||
* If not, the method tries to retrieve the store from the global
|
||||
* ObjectManager.
|
||||
* @return @li @c true if the store is linked or could be created.
|
||||
* @li @c false otherwise.
|
||||
*/
|
||||
bool checkAndSetStore();
|
||||
|
||||
void checkAndReportLostTm();
|
||||
};
|
||||
|
||||
|
||||
#endif /* FSFW_TMTCPACKET_PUS_TMPACKETSTORED_H_ */
|
||||
|
@@ -1,94 +0,0 @@
|
||||
#include "TmPacketStoredBase.h"
|
||||
|
||||
#include "../../objectmanager/ObjectManagerIF.h"
|
||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../../tmtcservices/TmTcMessage.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
StorageManagerIF *TmPacketStoredBase::store = nullptr;
|
||||
InternalErrorReporterIF *TmPacketStoredBase::internalErrorReporter = nullptr;
|
||||
|
||||
TmPacketStoredBase::TmPacketStoredBase(store_address_t setAddress): storeAddress(setAddress) {
|
||||
setStoreAddress(storeAddress);
|
||||
}
|
||||
|
||||
TmPacketStoredBase::TmPacketStoredBase() {
|
||||
}
|
||||
|
||||
|
||||
TmPacketStoredBase::~TmPacketStoredBase() {
|
||||
}
|
||||
|
||||
store_address_t TmPacketStoredBase::getStoreAddress() {
|
||||
return storeAddress;
|
||||
}
|
||||
|
||||
void TmPacketStoredBase::deletePacket() {
|
||||
store->deleteData(storeAddress);
|
||||
storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
|
||||
setDataPointer(nullptr);
|
||||
}
|
||||
|
||||
void TmPacketStoredBase::setStoreAddress(store_address_t setAddress) {
|
||||
storeAddress = setAddress;
|
||||
const uint8_t* tempData = nullptr;
|
||||
size_t tempSize;
|
||||
if (not checkAndSetStore()) {
|
||||
return;
|
||||
}
|
||||
ReturnValue_t status = store->getData(storeAddress, &tempData, &tempSize);
|
||||
if (status == StorageManagerIF::RETURN_OK) {
|
||||
setDataPointer(tempData);
|
||||
} else {
|
||||
setDataPointer(nullptr);
|
||||
storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
|
||||
}
|
||||
}
|
||||
|
||||
bool TmPacketStoredBase::checkAndSetStore() {
|
||||
if (store == nullptr) {
|
||||
store = objectManager->get<StorageManagerIF>(objects::TM_STORE);
|
||||
if (store == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "TmPacketStored::TmPacketStored: TM Store not found!"
|
||||
<< std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ReturnValue_t TmPacketStoredBase::sendPacket(MessageQueueId_t destination,
|
||||
MessageQueueId_t sentFrom, bool doErrorReporting) {
|
||||
if (getAllTmData() == nullptr) {
|
||||
//SHOULDDO: More decent code.
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
TmTcMessage tmMessage(getStoreAddress());
|
||||
ReturnValue_t result = MessageQueueSenderIF::sendMessage(destination,
|
||||
&tmMessage, sentFrom);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
deletePacket();
|
||||
if (doErrorReporting) {
|
||||
checkAndReportLostTm();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
//SHOULDDO: In many cases, some counter is incremented for successfully sent packets. The check is often not done, but just incremented.
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
|
||||
}
|
||||
|
||||
void TmPacketStoredBase::checkAndReportLostTm() {
|
||||
if (internalErrorReporter == nullptr) {
|
||||
internalErrorReporter = objectManager->get<InternalErrorReporterIF>(
|
||||
objects::INTERNAL_ERROR_REPORTER);
|
||||
}
|
||||
if (internalErrorReporter != nullptr) {
|
||||
internalErrorReporter->lostTm();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,89 +0,0 @@
|
||||
#ifndef FSFW_TMTCPACKET_PUS_TMPACKETSTOREDBASE_H_
|
||||
#define FSFW_TMTCPACKET_PUS_TMPACKETSTOREDBASE_H_
|
||||
|
||||
#include "TmPacketBase.h"
|
||||
#include "TmPacketStoredBase.h"
|
||||
#include <FSFWConfig.h>
|
||||
|
||||
#include "../../tmtcpacket/pus/TmPacketPusA.h"
|
||||
#include "../../serialize/SerializeIF.h"
|
||||
#include "../../storagemanager/StorageManagerIF.h"
|
||||
#include "../../internalError/InternalErrorReporterIF.h"
|
||||
#include "../../ipc/MessageQueueSenderIF.h"
|
||||
|
||||
/**
|
||||
* This class generates a ECSS PUS Telemetry packet within a given
|
||||
* intermediate storage.
|
||||
* As most packets are passed between tasks with the help of a storage
|
||||
* anyway, it seems logical to create a Packet-In-Storage access class
|
||||
* which saves the user almost all storage handling operation.
|
||||
* Packets can both be newly created with the class and be "linked" to
|
||||
* packets in a store with the help of a storeAddress.
|
||||
* @ingroup tmtcpackets
|
||||
*/
|
||||
class TmPacketStoredBase {
|
||||
public:
|
||||
/**
|
||||
* This is a default constructor which does not set the data pointer.
|
||||
* However, it does try to set the packet store.
|
||||
*/
|
||||
TmPacketStoredBase( store_address_t setAddress );
|
||||
TmPacketStoredBase();
|
||||
|
||||
virtual ~TmPacketStoredBase();
|
||||
|
||||
virtual uint8_t* getAllTmData() = 0;
|
||||
virtual void setDataPointer(const uint8_t* newPointer) = 0;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
store_address_t getStoreAddress();
|
||||
/**
|
||||
* With this call, the packet is deleted.
|
||||
* It removes itself from the store and sets its data pointer to NULL.
|
||||
*/
|
||||
void deletePacket();
|
||||
/**
|
||||
* With this call, a packet can be linked to another store. This is useful
|
||||
* if the packet is a class member and used for more than one packet.
|
||||
* @param setAddress The new packet id to link to.
|
||||
*/
|
||||
void setStoreAddress(store_address_t setAddress);
|
||||
|
||||
ReturnValue_t sendPacket(MessageQueueId_t destination, MessageQueueId_t sentFrom,
|
||||
bool doErrorReporting = true);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* This is a pointer to the store all instances of the class use.
|
||||
* If the store is not yet set (i.e. @c store is NULL), every constructor
|
||||
* call tries to set it and throws an error message in case of failures.
|
||||
* The default store is objects::TM_STORE.
|
||||
*/
|
||||
static StorageManagerIF* store;
|
||||
|
||||
static InternalErrorReporterIF *internalErrorReporter;
|
||||
|
||||
/**
|
||||
* The address where the packet data of the object instance is stored.
|
||||
*/
|
||||
store_address_t storeAddress;
|
||||
/**
|
||||
* A helper method to check if a store is assigned to the class.
|
||||
* If not, the method tries to retrieve the store from the global
|
||||
* ObjectManager.
|
||||
* @return @li @c true if the store is linked or could be created.
|
||||
* @li @c false otherwise.
|
||||
*/
|
||||
bool checkAndSetStore();
|
||||
|
||||
void checkAndReportLostTm();
|
||||
};
|
||||
|
||||
|
||||
#endif /* FSFW_TMTCPACKET_PUS_TMPACKETSTOREDBASE_H_ */
|
||||
|
@@ -1,79 +0,0 @@
|
||||
#include "TmPacketStoredPusA.h"
|
||||
|
||||
#include "../../serviceinterface/ServiceInterface.h"
|
||||
#include "../../tmtcservices/TmTcMessage.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
TmPacketStoredPusA::TmPacketStoredPusA(store_address_t setAddress) :
|
||||
TmPacketStoredBase(setAddress), TmPacketPusA(nullptr){
|
||||
}
|
||||
|
||||
TmPacketStoredPusA::TmPacketStoredPusA(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) :
|
||||
TmPacketPusA(nullptr) {
|
||||
storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
|
||||
if (not TmPacketStoredBase::checkAndSetStore()) {
|
||||
return;
|
||||
}
|
||||
uint8_t *pData = nullptr;
|
||||
ReturnValue_t returnValue = store->getFreeElement(&storeAddress,
|
||||
(getPacketMinimumSize() + size + headerSize), &pData);
|
||||
|
||||
if (returnValue != store->RETURN_OK) {
|
||||
TmPacketStoredBase::checkAndReportLostTm();
|
||||
return;
|
||||
}
|
||||
setData(pData);
|
||||
initializeTmPacket(apid, service, subservice, packetSubcounter);
|
||||
memcpy(getSourceData(), headerData, headerSize);
|
||||
memcpy(getSourceData() + headerSize, data, size);
|
||||
setPacketDataLength(
|
||||
size + headerSize + sizeof(PUSTmDataFieldHeaderPusA) + CRC_SIZE - 1);
|
||||
}
|
||||
|
||||
TmPacketStoredPusA::TmPacketStoredPusA(uint16_t apid, uint8_t service,
|
||||
uint8_t subservice, uint8_t packetSubcounter, SerializeIF *content,
|
||||
SerializeIF *header) :
|
||||
TmPacketPusA(nullptr) {
|
||||
storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
|
||||
if (not TmPacketStoredBase::checkAndSetStore()) {
|
||||
return;
|
||||
}
|
||||
size_t sourceDataSize = 0;
|
||||
if (content != NULL) {
|
||||
sourceDataSize += content->getSerializedSize();
|
||||
}
|
||||
if (header != NULL) {
|
||||
sourceDataSize += header->getSerializedSize();
|
||||
}
|
||||
uint8_t *p_data = NULL;
|
||||
ReturnValue_t returnValue = store->getFreeElement(&storeAddress,
|
||||
(getPacketMinimumSize() + sourceDataSize), &p_data);
|
||||
if (returnValue != store->RETURN_OK) {
|
||||
TmPacketStoredBase::checkAndReportLostTm();
|
||||
}
|
||||
setData(p_data);
|
||||
initializeTmPacket(apid, service, subservice, packetSubcounter);
|
||||
uint8_t *putDataHere = getSourceData();
|
||||
size_t size = 0;
|
||||
if (header != NULL) {
|
||||
header->serialize(&putDataHere, &size, sourceDataSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
}
|
||||
if (content != NULL) {
|
||||
content->serialize(&putDataHere, &size, sourceDataSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
}
|
||||
setPacketDataLength(
|
||||
sourceDataSize + sizeof(PUSTmDataFieldHeaderPusA) + CRC_SIZE - 1);
|
||||
}
|
||||
|
||||
uint8_t* TmPacketStoredPusA::getAllTmData() {
|
||||
return getWholeData();
|
||||
}
|
||||
|
||||
void TmPacketStoredPusA::setDataPointer(const uint8_t *newPointer) {
|
||||
setData(newPointer);
|
||||
}
|
@@ -1,65 +0,0 @@
|
||||
#ifndef FSFW_TMTCPACKET_PUS_TMPACKETSTORED_PUSA_H_
|
||||
#define FSFW_TMTCPACKET_PUS_TMPACKETSTORED_PUSA_H_
|
||||
|
||||
#include "TmPacketStoredBase.h"
|
||||
#include "TmPacketPusA.h"
|
||||
#include <FSFWConfig.h>
|
||||
|
||||
/**
|
||||
* This class generates a ECSS PUS A Telemetry packet within a given
|
||||
* intermediate storage.
|
||||
* As most packets are passed between tasks with the help of a storage
|
||||
* anyway, it seems logical to create a Packet-In-Storage access class
|
||||
* which saves the user almost all storage handling operation.
|
||||
* Packets can both be newly created with the class and be "linked" to
|
||||
* packets in a store with the help of a storeAddress.
|
||||
* @ingroup tmtcpackets
|
||||
*/
|
||||
class TmPacketStoredPusA :
|
||||
public TmPacketStoredBase,
|
||||
public TmPacketPusA {
|
||||
public:
|
||||
/**
|
||||
* This is a default constructor which does not set the data pointer.
|
||||
* However, it does try to set the packet store.
|
||||
*/
|
||||
TmPacketStoredPusA( store_address_t setAddress );
|
||||
/**
|
||||
* With this constructor, new space is allocated in the packet store and
|
||||
* a new PUS Telemetry Packet is created there.
|
||||
* Packet Application Data passed in data is copied into the packet.
|
||||
* The Application data is passed in two parts, first a header, then a
|
||||
* data field. This allows building a Telemetry Packet from two separate
|
||||
* data sources.
|
||||
* @param apid Sets the packet's APID field.
|
||||
* @param service Sets the packet's Service ID field.
|
||||
* This specifies the source service.
|
||||
* @param subservice Sets the packet's Service Subtype field.
|
||||
* This specifies the source sub-service.
|
||||
* @param packet_counter Sets the Packet counter field of this packet
|
||||
* @param data The payload data to be copied to the
|
||||
* Application Data Field
|
||||
* @param size The amount of data to be copied.
|
||||
* @param headerData The header Data of the Application field,
|
||||
* will be copied in front of data
|
||||
* @param headerSize The size of the headerDataF
|
||||
*/
|
||||
TmPacketStoredPusA( uint16_t apid, uint8_t service, uint8_t subservice,
|
||||
uint8_t packet_counter = 0, const uint8_t* data = nullptr,
|
||||
uint32_t size = 0, const uint8_t* headerData = nullptr,
|
||||
uint32_t headerSize = 0);
|
||||
/**
|
||||
* Another ctor to directly pass structured content and header data to the
|
||||
* packet to avoid additional buffers.
|
||||
*/
|
||||
TmPacketStoredPusA( uint16_t apid, uint8_t service, uint8_t subservice,
|
||||
uint8_t packet_counter, SerializeIF* content,
|
||||
SerializeIF* header = nullptr);
|
||||
|
||||
uint8_t* getAllTmData() override;
|
||||
void setDataPointer(const uint8_t* newPointer) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* FSFW_TMTCPACKET_PUS_TMPACKETSTORED_PUSA_H_ */
|
@@ -1,80 +0,0 @@
|
||||
#include "TmPacketStoredPusC.h"
|
||||
|
||||
#include "../../serviceinterface/ServiceInterface.h"
|
||||
#include "../../tmtcservices/TmTcMessage.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
TmPacketStoredPusC::TmPacketStoredPusC(store_address_t setAddress) :
|
||||
TmPacketStoredBase(setAddress), TmPacketPusC(nullptr){
|
||||
}
|
||||
|
||||
TmPacketStoredPusC::TmPacketStoredPusC(uint16_t apid, uint8_t service,
|
||||
uint8_t subservice, uint16_t packetSubcounter, const uint8_t *data,
|
||||
uint32_t size, const uint8_t *headerData, uint32_t headerSize, uint16_t destinationId,
|
||||
uint8_t timeRefField) :
|
||||
TmPacketPusC(nullptr) {
|
||||
storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
|
||||
if (not TmPacketStoredBase::checkAndSetStore()) {
|
||||
return;
|
||||
}
|
||||
uint8_t *pData = nullptr;
|
||||
ReturnValue_t returnValue = store->getFreeElement(&storeAddress,
|
||||
(getPacketMinimumSize() + size + headerSize), &pData);
|
||||
|
||||
if (returnValue != store->RETURN_OK) {
|
||||
TmPacketStoredBase::checkAndReportLostTm();
|
||||
return;
|
||||
}
|
||||
setData(pData);
|
||||
initializeTmPacket(apid, service, subservice, packetSubcounter, destinationId, timeRefField);
|
||||
memcpy(getSourceData(), headerData, headerSize);
|
||||
memcpy(getSourceData() + headerSize, data, size);
|
||||
setPacketDataLength(
|
||||
size + headerSize + sizeof(PUSTmDataFieldHeaderPusC) + CRC_SIZE - 1);
|
||||
}
|
||||
|
||||
TmPacketStoredPusC::TmPacketStoredPusC(uint16_t apid, uint8_t service,
|
||||
uint8_t subservice, uint16_t packetSubcounter, SerializeIF *content,
|
||||
SerializeIF *header, uint16_t destinationId, uint8_t timeRefField) :
|
||||
TmPacketPusC(nullptr) {
|
||||
storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
|
||||
if (not TmPacketStoredBase::checkAndSetStore()) {
|
||||
return;
|
||||
}
|
||||
size_t sourceDataSize = 0;
|
||||
if (content != NULL) {
|
||||
sourceDataSize += content->getSerializedSize();
|
||||
}
|
||||
if (header != NULL) {
|
||||
sourceDataSize += header->getSerializedSize();
|
||||
}
|
||||
uint8_t *p_data = NULL;
|
||||
ReturnValue_t returnValue = store->getFreeElement(&storeAddress,
|
||||
(getPacketMinimumSize() + sourceDataSize), &p_data);
|
||||
if (returnValue != store->RETURN_OK) {
|
||||
TmPacketStoredBase::checkAndReportLostTm();
|
||||
}
|
||||
setData(p_data);
|
||||
initializeTmPacket(apid, service, subservice, packetSubcounter, destinationId, timeRefField);
|
||||
uint8_t *putDataHere = getSourceData();
|
||||
size_t size = 0;
|
||||
if (header != NULL) {
|
||||
header->serialize(&putDataHere, &size, sourceDataSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
}
|
||||
if (content != NULL) {
|
||||
content->serialize(&putDataHere, &size, sourceDataSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
}
|
||||
setPacketDataLength(
|
||||
sourceDataSize + sizeof(PUSTmDataFieldHeaderPusC) + CRC_SIZE - 1);
|
||||
}
|
||||
|
||||
uint8_t* TmPacketStoredPusC::getAllTmData() {
|
||||
return getWholeData();
|
||||
}
|
||||
|
||||
void TmPacketStoredPusC::setDataPointer(const uint8_t *newPointer) {
|
||||
setData(newPointer);
|
||||
}
|
@@ -1,68 +0,0 @@
|
||||
#ifndef FSFW_TMTCPACKET_PUS_TMPACKETSTOREDPUSC_H_
|
||||
#define FSFW_TMTCPACKET_PUS_TMPACKETSTOREDPUSC_H_
|
||||
|
||||
#include <fsfw/tmtcpacket/pus/TmPacketPusC.h>
|
||||
#include <fsfw/tmtcpacket/pus/TmPacketStoredBase.h>
|
||||
|
||||
/**
|
||||
* This class generates a ECSS PUS C Telemetry packet within a given
|
||||
* intermediate storage.
|
||||
* As most packets are passed between tasks with the help of a storage
|
||||
* anyway, it seems logical to create a Packet-In-Storage access class
|
||||
* which saves the user almost all storage handling operation.
|
||||
* Packets can both be newly created with the class and be "linked" to
|
||||
* packets in a store with the help of a storeAddress.
|
||||
* @ingroup tmtcpackets
|
||||
*/
|
||||
class TmPacketStoredPusC:
|
||||
public TmPacketStoredBase,
|
||||
public TmPacketPusC {
|
||||
public:
|
||||
/**
|
||||
* This is a default constructor which does not set the data pointer.
|
||||
* However, it does try to set the packet store.
|
||||
*/
|
||||
TmPacketStoredPusC( store_address_t setAddress );
|
||||
/**
|
||||
* With this constructor, new space is allocated in the packet store and
|
||||
* a new PUS Telemetry Packet is created there.
|
||||
* Packet Application Data passed in data is copied into the packet.
|
||||
* The Application data is passed in two parts, first a header, then a
|
||||
* data field. This allows building a Telemetry Packet from two separate
|
||||
* data sources.
|
||||
* @param apid Sets the packet's APID field.
|
||||
* @param service Sets the packet's Service ID field.
|
||||
* This specifies the source service.
|
||||
* @param subservice Sets the packet's Service Subtype field.
|
||||
* This specifies the source sub-service.
|
||||
* @param packet_counter Sets the Packet counter field of this packet
|
||||
* @param data The payload data to be copied to the
|
||||
* Application Data Field
|
||||
* @param size The amount of data to be copied.
|
||||
* @param headerData The header Data of the Application field,
|
||||
* will be copied in front of data
|
||||
* @param headerSize The size of the headerDataF
|
||||
* @param destinationId Destination ID containing the application process ID as specified
|
||||
* by PUS C
|
||||
* @param timeRefField 4 bit time reference field as specified by PUS C
|
||||
*/
|
||||
TmPacketStoredPusC( uint16_t apid, uint8_t service, uint8_t subservice,
|
||||
uint16_t packetCounter = 0, const uint8_t* data = nullptr,
|
||||
uint32_t size = 0, const uint8_t* headerData = nullptr,
|
||||
uint32_t headerSize = 0, uint16_t destinationId = 0, uint8_t timeRefField = 0);
|
||||
/**
|
||||
* Another ctor to directly pass structured content and header data to the
|
||||
* packet to avoid additional buffers.
|
||||
*/
|
||||
TmPacketStoredPusC( uint16_t apid, uint8_t service, uint8_t subservice,
|
||||
uint16_t packetCounter, SerializeIF* content,
|
||||
SerializeIF* header = nullptr, uint16_t destinationId = 0, uint8_t timeRefField = 0);
|
||||
|
||||
uint8_t* getAllTmData() override;
|
||||
void setDataPointer(const uint8_t* newPointer) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* FSFW_TMTCPACKET_PUS_TMPACKETSTOREDPUSC_H_ */
|
@@ -1,7 +1,6 @@
|
||||
#include "AcceptsTelemetryIF.h"
|
||||
#include "CommandingServiceBase.h"
|
||||
#include "TmTcMessage.h"
|
||||
#include <FSFWConfig.h>
|
||||
|
||||
#include "../tcdistribution/PUSDistributorIF.h"
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
@@ -294,13 +293,8 @@ void CommandingServiceBase::handleRequestQueue() {
|
||||
ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice,
|
||||
const uint8_t* data, size_t dataLen, const uint8_t* headerData,
|
||||
size_t headerSize) {
|
||||
#if FSFW_USE_PUS_C_TELEMETRY == 0
|
||||
TmPacketStoredPusA tmPacketStored(this->apid, this->service, subservice,
|
||||
TmPacketStored tmPacketStored(this->apid, this->service, subservice,
|
||||
this->tmPacketCounter, data, dataLen, headerData, headerSize);
|
||||
#else
|
||||
TmPacketStoredPusC tmPacketStored(this->apid, this->service, subservice,
|
||||
this->tmPacketCounter, data, dataLen, headerData, headerSize);
|
||||
#endif
|
||||
ReturnValue_t result = tmPacketStored.sendPacket(
|
||||
requestQueue->getDefaultDestination(), requestQueue->getId());
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
@@ -317,13 +311,8 @@ ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice,
|
||||
size_t size = 0;
|
||||
SerializeAdapter::serialize(&objectId, &pBuffer, &size,
|
||||
sizeof(object_id_t), SerializeIF::Endianness::BIG);
|
||||
#if FSFW_USE_PUS_C_TELEMETRY == 0
|
||||
TmPacketStoredPusA tmPacketStored(this->apid, this->service, subservice,
|
||||
TmPacketStored tmPacketStored(this->apid, this->service, subservice,
|
||||
this->tmPacketCounter, data, dataLen, buffer, size);
|
||||
#else
|
||||
TmPacketStoredPusC tmPacketStored(this->apid, this->service, subservice,
|
||||
this->tmPacketCounter, data, dataLen, buffer, size);
|
||||
#endif
|
||||
ReturnValue_t result = tmPacketStored.sendPacket(
|
||||
requestQueue->getDefaultDestination(), requestQueue->getId());
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
@@ -335,13 +324,8 @@ ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice,
|
||||
|
||||
ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice,
|
||||
SerializeIF* content, SerializeIF* header) {
|
||||
#if FSFW_USE_PUS_C_TELEMETRY == 0
|
||||
TmPacketStoredPusA tmPacketStored(this->apid, this->service, subservice,
|
||||
TmPacketStored tmPacketStored(this->apid, this->service, subservice,
|
||||
this->tmPacketCounter, content, header);
|
||||
#else
|
||||
TmPacketStoredPusC tmPacketStored(this->apid, this->service, subservice,
|
||||
this->tmPacketCounter, content, header);
|
||||
#endif
|
||||
ReturnValue_t result = tmPacketStored.sendPacket(
|
||||
requestQueue->getDefaultDestination(), requestQueue->getId());
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
|
@@ -21,7 +21,7 @@ TmTcMessage::TmTcMessage(store_address_t storeId) {
|
||||
this->setStorageId(storeId);
|
||||
}
|
||||
|
||||
size_t TmTcMessage::getMinimumMessageSize() const {
|
||||
size_t TmTcMessage::getMinimumMessageSize() {
|
||||
return this->HEADER_SIZE + sizeof(store_address_t);
|
||||
}
|
||||
|
||||
|
@@ -18,7 +18,7 @@ protected:
|
||||
* @brief This call always returns the same fixed size of the message.
|
||||
* @return Returns HEADER_SIZE + @c sizeof(store_address_t).
|
||||
*/
|
||||
size_t getMinimumMessageSize() const override;
|
||||
size_t getMinimumMessageSize();
|
||||
public:
|
||||
/**
|
||||
* @brief In the default constructor, only the message_size is set.
|
||||
|
@@ -1,3 +0,0 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
PusTmTest.cpp
|
||||
)
|
@@ -1,3 +0,0 @@
|
||||
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#include "CatchFactory.h"
|
||||
#include <fsfw/datapoollocal/LocalDataPoolManager.h>
|
||||
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||
#include "CatchFactory.h"
|
||||
|
||||
#include <fsfw/events/EventManager.h>
|
||||
#include <fsfw/health/HealthTable.h>
|
||||
@@ -74,7 +74,7 @@ void Factory::setStaticFrameworkObjectIds() {
|
||||
|
||||
DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT;
|
||||
|
||||
TmPacketBase::timeStamperId = objects::NO_OBJECT;
|
||||
TmPacketStored::timeStamperId = objects::NO_OBJECT;
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user