Compare commits

..

7 Commits

34 changed files with 664 additions and 1460 deletions

View File

@@ -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;

View File

@@ -308,11 +308,11 @@ void DeviceHandlerBase::doStateMachine() {
uint32_t currentUptime;
Clock::getUptime(&currentUptime);
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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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++;
}

View File

@@ -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
}
}
}

View File

@@ -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;
}

View File

@@ -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_ */

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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() {}

View File

@@ -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
)

View File

@@ -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);
}

View File

@@ -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.

View File

@@ -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);
}

View File

@@ -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_ */

View File

@@ -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);
}

View File

@@ -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_ */

View 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();
}
}

View File

@@ -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_ */

View File

@@ -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();
}
}

View File

@@ -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_ */

View File

@@ -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);
}

View File

@@ -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_ */

View File

@@ -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);
}

View File

@@ -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_ */

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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.

View File

@@ -1,3 +0,0 @@
target_sources(${TARGET_NAME} PRIVATE
PusTmTest.cpp
)

View File

@@ -1,3 +0,0 @@

View File

@@ -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;
}