1
0
forked from fsfw/fsfw

Merge remote-tracking branch 'origin/development' into mueller/new-cfdp-update-with-handlers

This commit is contained in:
2023-01-13 10:56:16 +01:00
72 changed files with 965 additions and 997 deletions

View File

@ -4,6 +4,7 @@
#include "../returnvalues/returnvalue.h"
#include "../serialize/SerializeAdapter.h"
#include "../serialize/SerializeIF.h"
#include "definitions.h"
/**
* @brief A List that stores its values in an array.
@ -19,9 +20,6 @@ class ArrayList {
friend class SerialArrayListAdapter;
public:
static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST;
static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01);
/**
* This is the allocating constructor.
* It allocates an array of the specified size.
@ -187,7 +185,7 @@ class ArrayList {
*/
ReturnValue_t insert(T entry) {
if (size >= maxSize_) {
return FULL;
return containers::LIST_FULL;
}
entries[size] = entry;
++size;

View File

@ -20,15 +20,19 @@ class FixedArrayList : public ArrayList<T, count_t> {
FixedArrayList() : ArrayList<T, count_t>(data, MAX_SIZE) {}
FixedArrayList(const FixedArrayList& other) : ArrayList<T, count_t>(data, MAX_SIZE) {
memcpy(this->data, other.data, sizeof(this->data));
this->entries = data;
this->size = other.size;
for (size_t idx = 0; idx < this->size; idx++) {
data[idx] = other.data[idx];
}
}
FixedArrayList& operator=(FixedArrayList other) {
memcpy(this->data, other.data, sizeof(this->data));
this->entries = data;
this->size = other.size;
for (size_t idx = 0; idx < this->size; idx++) {
data[idx] = other.data[idx];
}
return *this;
}

View File

@ -4,8 +4,8 @@
#include <type_traits>
#include <utility>
#include "../returnvalues/returnvalue.h"
#include "ArrayList.h"
#include "definitions.h"
/**
* @brief Map implementation for maps with a pre-defined size.
@ -24,11 +24,6 @@ class FixedMap : public SerializeIF {
"derived class from SerializeIF to be serialize-able");
public:
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
private:
static const key_t EMPTY_SLOT = -1;
ArrayList<std::pair<key_t, T>, uint32_t> theMap;
@ -76,10 +71,10 @@ class FixedMap : public SerializeIF {
ReturnValue_t insert(key_t key, T value, Iterator* storedValue = nullptr) {
if (exists(key) == returnvalue::OK) {
return KEY_ALREADY_EXISTS;
return containers::KEY_ALREADY_EXISTS;
}
if (_size == theMap.maxSize()) {
return MAP_FULL;
return containers::MAP_FULL;
}
theMap[_size].first = key;
theMap[_size].second = value;
@ -93,7 +88,7 @@ class FixedMap : public SerializeIF {
ReturnValue_t insert(std::pair<key_t, T> pair) { return insert(pair.first, pair.second); }
ReturnValue_t exists(key_t key) const {
ReturnValue_t result = KEY_DOES_NOT_EXIST;
ReturnValue_t result = containers::KEY_DOES_NOT_EXIST;
if (findIndex(key) < _size) {
result = returnvalue::OK;
}
@ -103,7 +98,7 @@ class FixedMap : public SerializeIF {
ReturnValue_t erase(Iterator* iter) {
uint32_t i;
if ((i = findIndex((*iter).value->first)) >= _size) {
return KEY_DOES_NOT_EXIST;
return containers::KEY_DOES_NOT_EXIST;
}
theMap[i] = theMap[_size - 1];
--_size;
@ -114,7 +109,7 @@ class FixedMap : public SerializeIF {
ReturnValue_t erase(key_t key) {
uint32_t i;
if ((i = findIndex(key)) >= _size) {
return KEY_DOES_NOT_EXIST;
return containers::KEY_DOES_NOT_EXIST;
}
theMap[i] = theMap[_size - 1];
--_size;

View File

@ -0,0 +1,14 @@
#ifndef FSFW_CONTAINER_DEFINITIONS_H_
#define FSFW_CONTAINER_DEFINITIONS_H_
#include "fsfw/retval.h"
namespace containers {
static const ReturnValue_t KEY_ALREADY_EXISTS = returnvalue::makeCode(CLASS_ID::FIXED_MAP, 0x01);
static const ReturnValue_t MAP_FULL = returnvalue::makeCode(CLASS_ID::FIXED_MAP, 0x02);
static const ReturnValue_t KEY_DOES_NOT_EXIST = returnvalue::makeCode(CLASS_ID::FIXED_MAP, 0x03);
static const ReturnValue_t LIST_FULL = returnvalue::makeCode(CLASS_ID::ARRAY_LIST, 0x01);
} // namespace containers
#endif /* FSFW_CONTAINER_DEFINITIONS_H_ */

View File

@ -48,12 +48,12 @@ LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId,
if (hkOwner == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "LocalPoolVariable: The supplied pool owner 0x" << std::hex << poolOwner
<< std::dec << " did not implement the correct interface "
<< std::dec << " does not exist or does not implement the correct interface "
<< "HasLocalDataPoolIF" << std::endl;
#else
sif::printError(
"LocalPoolVariable: The supplied pool owner 0x%08x did not implement the correct "
"interface HasLocalDataPoolIF\n",
"LocalPoolVariable: The supplied pool owner 0x%08x does not exist or does not implement "
"the correct interface HasLocalDataPoolIF\n",
poolOwner);
#endif
return;

View File

@ -359,6 +359,8 @@ void DeviceHandlerBase::doStateMachine() {
if ((switchState == PowerSwitchIF::SWITCH_ON) || (switchState == NO_SWITCH)) {
// NOTE: TransitionSourceMode and -SubMode are set by handleCommandedModeTransition
childTransitionFailure = CHILD_TIMEOUT;
transitionSourceMode = _MODE_SHUT_DOWN;
transitionSourceSubMode = SUBMODE_NONE;
setMode(_MODE_START_UP);
callChildStatemachine();
}
@ -458,7 +460,7 @@ ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceComm
info.expectedReplies = 0;
info.isExecuting = false;
info.sendReplyTo = NO_COMMANDER;
info.useAlternativeReplyId = alternativeReplyId;
info.useAlternativeReplyId = useAlternativeReply;
info.alternativeReplyId = alternativeReplyId;
auto resultPair = deviceCommandMap.emplace(deviceCommand, info);
if (resultPair.second) {
@ -517,16 +519,16 @@ ReturnValue_t DeviceHandlerBase::updatePeriodicReply(bool enable, DeviceCommandI
if (enable) {
info->active = true;
if (info->countdown != nullptr) {
info->delayCycles = info->maxDelayCycles;
} else {
info->countdown->resetTimer();
} else {
info->delayCycles = info->maxDelayCycles;
}
} else {
info->active = false;
if (info->countdown != nullptr) {
info->delayCycles = 0;
} else {
info->countdown->timeOut();
} else {
info->delayCycles = 0;
}
}
}

View File

@ -4,6 +4,7 @@ target_sources(
AsciiConverter.cpp
CRC.cpp
DleEncoder.cpp
DleParser.cpp
PeriodicOperationDivider.cpp
timevalOperations.cpp
Type.cpp

View File

@ -0,0 +1,173 @@
#include "DleParser.h"
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <cstdio>
#include <fstream>
#include <iostream>
DleParser::DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf,
BufPair decodedBuf)
: decodeRingBuf(decodeRingBuf),
decoder(decoder),
encodedBuf(encodedBuf),
decodedBuf(decodedBuf) {}
ReturnValue_t DleParser::passData(const uint8_t* data, size_t len) {
if (data == nullptr or len == 0) {
return returnvalue::FAILED;
}
return decodeRingBuf.writeData(data, len);
}
ReturnValue_t DleParser::parseRingBuf(size_t& readSize) {
ctx.setType(DleParser::ContextType::NONE);
size_t availableData = decodeRingBuf.getAvailableReadData();
if (availableData == 0) {
return NO_PACKET_FOUND;
}
if (availableData > encodedBuf.second) {
ErrorInfo info;
info.len = decodeRingBuf.getAvailableReadData();
setErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
return returnvalue::FAILED;
}
ReturnValue_t result = decodeRingBuf.readData(encodedBuf.first, availableData);
if (result != returnvalue::OK) {
ErrorInfo info;
info.res = result;
setErrorContext(ErrorTypes::RING_BUF_ERROR, info);
return result;
}
bool stxFound = false;
size_t stxIdx = 0;
for (size_t vectorIdx = 0; vectorIdx < availableData; vectorIdx++) {
// handle STX char
if (encodedBuf.first[vectorIdx] == DleEncoder::STX_CHAR) {
if (not stxFound) {
stxFound = true;
stxIdx = vectorIdx;
} else {
// might be lost packet, so we should advance the read pointer
// without skipping the STX
readSize = vectorIdx;
ErrorInfo info;
setErrorContext(ErrorTypes::CONSECUTIVE_STX_CHARS, info);
return POSSIBLE_PACKET_LOSS;
}
}
// handle ETX char
if (encodedBuf.first[vectorIdx] == DleEncoder::ETX_CHAR) {
if (stxFound) {
// This is propably a packet, so we decode it.
size_t decodedLen = 0;
size_t dummy = 0;
ReturnValue_t result =
decoder.decode(&encodedBuf.first[stxIdx], availableData - stxIdx, &dummy,
decodedBuf.first, decodedBuf.second, &decodedLen);
if (result == returnvalue::OK) {
ctx.setType(ContextType::PACKET_FOUND);
ctx.decodedPacket.first = decodedBuf.first;
ctx.decodedPacket.second = decodedLen;
readSize = ++vectorIdx;
return returnvalue::OK;
} else {
// invalid packet, skip.
readSize = ++vectorIdx;
ErrorInfo info;
info.res = result;
setErrorContext(ErrorTypes::DECODE_ERROR, info);
return POSSIBLE_PACKET_LOSS;
}
} else {
// might be lost packet, so we should advance the read pointer
readSize = ++vectorIdx;
ErrorInfo info;
info.len = 0;
setErrorContext(ErrorTypes::CONSECUTIVE_ETX_CHARS, info);
return POSSIBLE_PACKET_LOSS;
}
}
}
return NO_PACKET_FOUND;
}
void DleParser::defaultFoundPacketHandler(uint8_t* packet, size_t len, void* args) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "DleParserBase::handleFoundPacket: Detected DLE packet with " << len << " bytes"
<< std::endl;
#else
sif::printInfo("DleParserBase::handleFoundPacket: Detected DLE packet with %d bytes\n", len);
#endif
#endif
}
void DleParser::defaultErrorHandler() {
if (ctx.getType() != DleParser::ContextType::ERROR) {
errorPrinter("No error");
return;
}
switch (ctx.error.first) {
case (ErrorTypes::NONE): {
errorPrinter("No error");
break;
}
case (ErrorTypes::DECODE_ERROR): {
errorPrinter("Decode Error");
break;
}
case (ErrorTypes::RING_BUF_ERROR): {
errorPrinter("Ring Buffer Error");
break;
}
case (ErrorTypes::ENCODED_BUF_TOO_SMALL):
case (ErrorTypes::DECODING_BUF_TOO_SMALL): {
char opt[64];
snprintf(opt, sizeof(opt), ": Too small for packet with length %zu",
ctx.decodedPacket.second);
if (ctx.error.first == ErrorTypes::ENCODED_BUF_TOO_SMALL) {
errorPrinter("Encoded buf too small", opt);
} else {
errorPrinter("Decoding buf too small", opt);
}
break;
}
case (ErrorTypes::CONSECUTIVE_STX_CHARS): {
errorPrinter("Consecutive STX chars detected");
break;
}
case (ErrorTypes::CONSECUTIVE_ETX_CHARS): {
errorPrinter("Consecutive ETX chars detected");
break;
}
}
}
void DleParser::errorPrinter(const char* str, const char* opt) {
if (opt == nullptr) {
opt = "";
}
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "DleParserBase::handleParseError: " << str << opt << std::endl;
#else
sif::printInfo("DleParserBase::handleParseError: %s%s\n", str, opt);
#endif
#endif
}
void DleParser::setErrorContext(ErrorTypes err, ErrorInfo info) {
ctx.setType(ContextType::ERROR);
ctx.error.first = err;
ctx.error.second = info;
}
ReturnValue_t DleParser::confirmBytesRead(size_t bytesRead) {
return decodeRingBuf.deleteData(bytesRead);
}
const DleParser::Context& DleParser::getContext() { return ctx; }
void DleParser::reset() { decodeRingBuf.clear(); }

View File

@ -0,0 +1,127 @@
#pragma once
#include <fsfw/container/SimpleRingBuffer.h>
#include <fsfw/globalfunctions/DleEncoder.h>
#include <fsfw/returnvalues/returnvalue.h>
#include <cstddef>
#include <utility>
/**
* @brief This base helper class can be used to extract DLE encoded packets from a data stream
* @details
* The core API of the parser takes received packets which can contains DLE packets. The parser
* can deal with DLE packets split across multiple packets. It does so by using a dedicated
* decoding ring buffer. The user can process received packets and detect errors by
* overriding two provided virtual methods. This also allows detecting multiple DLE packets
* inside one passed packet.
*/
class DleParser {
public:
static constexpr ReturnValue_t NO_PACKET_FOUND = returnvalue::makeCode(1, 1);
static constexpr ReturnValue_t POSSIBLE_PACKET_LOSS = returnvalue::makeCode(1, 2);
using BufPair = std::pair<uint8_t*, size_t>;
enum class ContextType { NONE, PACKET_FOUND, ERROR };
enum class ErrorTypes {
NONE,
ENCODED_BUF_TOO_SMALL,
DECODING_BUF_TOO_SMALL,
DECODE_ERROR,
RING_BUF_ERROR,
CONSECUTIVE_STX_CHARS,
CONSECUTIVE_ETX_CHARS
};
union ErrorInfo {
size_t len;
ReturnValue_t res;
};
using ErrorPair = std::pair<ErrorTypes, ErrorInfo>;
struct Context {
public:
Context() { setType(ContextType::PACKET_FOUND); }
void setType(ContextType type) {
this->type = type;
if (type == ContextType::PACKET_FOUND) {
error.first = ErrorTypes::NONE;
error.second.len = 0;
} else {
decodedPacket.first = nullptr;
decodedPacket.second = 0;
}
}
ContextType getType() const { return type; }
BufPair decodedPacket = {};
ErrorPair error;
private:
ContextType type;
};
/**
* Base class constructor
* @param decodeRingBuf Ring buffer used to store multiple packets to allow detecting DLE packets
* split across multiple packets
* @param decoder Decoder instance
* @param encodedBuf Buffer used to store encoded packets. It has to be large enough to hold
* the largest expected encoded DLE packet size
* @param decodedBuf Buffer used to store decoded packets. It has to be large enough to hold the
* largest expected decoded DLE packet size
* @param handler Function which will be called on a found packet
* @param args Arbitrary user argument
*/
DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf,
BufPair decodedBuf);
/**
* This function allows to pass new data into the parser. It then scans for DLE packets
* automatically and inserts (part of) the packet into a ring buffer if necessary.
* @param data
* @param len
* @return
*/
ReturnValue_t passData(const uint8_t* data, size_t len);
ReturnValue_t parseRingBuf(size_t& bytesRead);
ReturnValue_t confirmBytesRead(size_t bytesRead);
const Context& getContext();
/**
* Example found packet handler
* function call
* @param packet Decoded packet
* @param len Length of detected packet
*/
void defaultFoundPacketHandler(uint8_t* packet, size_t len, void* args);
/**
* Will be called if an error occured in the #passData call
* @param err
* @param ctx Context information depending on the error type
* - For buffer length errors, will be set to the detected packet length which is too large
* - For decode or ring buffer errors, will be set to the result returned from the failed call
*/
void defaultErrorHandler();
static void errorPrinter(const char* str, const char* opt = nullptr);
void setErrorContext(ErrorTypes err, ErrorInfo ctx);
/**
* Resets the parser by resetting the internal states and clearing the decoding ring buffer
*/
void reset();
private:
SimpleRingBuffer& decodeRingBuf;
DleEncoder& decoder;
BufPair encodedBuf;
BufPair decodedBuf;
Context ctx;
};

View File

@ -1,8 +1,8 @@
#include "fsfw/globalfunctions/timevalOperations.h"
timeval& operator+=(timeval& lhs, const timeval& rhs) {
int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec;
sum += rhs.tv_sec * 1000000. + rhs.tv_usec;
int64_t sum = static_cast<int64_t>(lhs.tv_sec) * 1000000. + lhs.tv_usec;
sum += static_cast<int64_t>(rhs.tv_sec) * 1000000. + rhs.tv_usec;
lhs.tv_sec = sum / 1000000;
lhs.tv_usec = sum - lhs.tv_sec * 1000000;
return lhs;

View File

@ -5,7 +5,11 @@
HealthHelper::HealthHelper(HasHealthIF* owner, object_id_t objectId)
: objectId(objectId), owner(owner) {}
HealthHelper::~HealthHelper() { healthTable->removeObject(objectId); }
HealthHelper::~HealthHelper() {
if (healthTable != nullptr) {
healthTable->removeObject(objectId);
}
}
ReturnValue_t HealthHelper::handleHealthCommand(CommandMessage* message) {
switch (message->getCommand()) {

View File

@ -1,6 +1,7 @@
#include "fsfw/osal/common/TcpIpBase.h"
#include "fsfw/platform.h"
#include "fsfw/serviceinterface.h"
#ifdef PLATFORM_UNIX
#include <errno.h>

View File

@ -8,6 +8,7 @@
#if defined(PLATFORM_WIN)
#include <sysinfoapi.h>
#define timegm _mkgmtime
#elif defined(PLATFORM_UNIX)
#include <fstream>
#endif

View File

@ -1,5 +1,7 @@
#include "fsfw/osal/windows/winTaskHelpers.h"
#include <windows.h>
#include <mutex>
TaskPriority tasks::makeWinPriority(PriorityClass prioClass, PriorityNumber prioNumber) {

View File

@ -1,10 +1,12 @@
#include <map>
#include <thread>
#include "../../tasks/TaskFactory.h"
#include "fsfw/tasks/TaskFactory.h"
#ifdef _WIN32
#include <minwindef.h>
namespace tasks {
enum PriorityClass : uint16_t {

View File

@ -31,9 +31,8 @@ LocalPool::LocalPool(object_id_t setObjectId, const LocalPoolConfig& poolConfig,
LocalPool::~LocalPool() = default;
ReturnValue_t LocalPool::addData(store_address_t* storageId, const uint8_t* data, size_t size,
bool ignoreFault) {
ReturnValue_t status = reserveSpace(size, storageId, ignoreFault);
ReturnValue_t LocalPool::addData(store_address_t* storageId, const uint8_t* data, size_t size) {
ReturnValue_t status = reserveSpace(size, storageId);
if (status == returnvalue::OK) {
write(*storageId, data, size);
}
@ -49,8 +48,8 @@ ReturnValue_t LocalPool::getData(store_address_t packetId, const uint8_t** packe
}
ReturnValue_t LocalPool::getFreeElement(store_address_t* storageId, const size_t size,
uint8_t** pData, bool ignoreFault) {
ReturnValue_t status = reserveSpace(size, storageId, ignoreFault);
uint8_t** pData) {
ReturnValue_t status = reserveSpace(size, storageId);
if (status == returnvalue::OK) {
*pData = &store[storageId->poolIndex][getRawPosition(*storageId)];
} else {
@ -167,7 +166,7 @@ void LocalPool::clearStore() {
}
}
ReturnValue_t LocalPool::reserveSpace(size_t size, store_address_t* storeId, bool ignoreFault) {
ReturnValue_t LocalPool::reserveSpace(size_t size, store_address_t* storeId) {
ReturnValue_t status = getSubPoolIndex(size, &storeId->poolIndex);
if (status != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
@ -318,27 +317,3 @@ bool LocalPool::hasDataAtId(store_address_t storeId) const {
}
return false;
}
ReturnValue_t LocalPool::getFreeElement(store_address_t* storeId, size_t size, uint8_t** pData) {
return StorageManagerIF::getFreeElement(storeId, size, pData);
}
ConstAccessorPair LocalPool::getData(store_address_t storeId) {
return StorageManagerIF::getData(storeId);
}
ReturnValue_t LocalPool::addData(store_address_t* storeId, const uint8_t* data, size_t size) {
return StorageManagerIF::addData(storeId, data, size);
}
ReturnValue_t LocalPool::getData(store_address_t storeId, ConstStorageAccessor& accessor) {
return StorageManagerIF::getData(storeId, accessor);
}
ReturnValue_t LocalPool::modifyData(store_address_t storeId, StorageAccessor& accessor) {
return StorageManagerIF::modifyData(storeId, accessor);
}
AccessorPair LocalPool::modifyData(store_address_t storeId) {
return StorageManagerIF::modifyData(storeId);
}

View File

@ -86,21 +86,13 @@ class LocalPool : public SystemObject, public StorageManagerIF {
/**
* Documentation: See StorageManagerIF.h
*/
ReturnValue_t addData(store_address_t* storeId, const uint8_t* data, size_t size,
bool ignoreFault) override;
ReturnValue_t addData(store_address_t* storeId, const uint8_t* data, size_t size) override;
ReturnValue_t getFreeElement(store_address_t* storeId, size_t size, uint8_t** pData) override;
ReturnValue_t getFreeElement(store_address_t* storeId, size_t size, uint8_t** pData,
bool ignoreFault) override;
ConstAccessorPair getData(store_address_t storeId) override;
ReturnValue_t getData(store_address_t storeId, ConstStorageAccessor& accessor) override;
ReturnValue_t getData(store_address_t storeId, const uint8_t** packet_ptr, size_t* size) override;
AccessorPair modifyData(store_address_t storeId) override;
ReturnValue_t modifyData(store_address_t storeId, uint8_t** packet_ptr, size_t* size) override;
ReturnValue_t modifyData(store_address_t storeId, StorageAccessor& accessor) override;
ReturnValue_t deleteData(store_address_t storeId) override;
ReturnValue_t deleteData(uint8_t* ptr, size_t size, store_address_t* storeId) override;
@ -136,6 +128,12 @@ class LocalPool : public SystemObject, public StorageManagerIF {
[[nodiscard]] max_subpools_t getNumberOfSubPools() const override;
[[nodiscard]] bool hasDataAtId(store_address_t storeId) const override;
// Using functions provided by StorageManagerIF requires either a fully qualified path
// like for example localPool.StorageManagerIF::getFreeElement(...) or re-exporting
// the fully qualified path with the using directive.
using StorageManagerIF::getData;
using StorageManagerIF::modifyData;
protected:
/**
* With this helper method, a free element of @c size is reserved.
@ -144,7 +142,7 @@ class LocalPool : public SystemObject, public StorageManagerIF {
* @return - returnvalue::OK on success,
* - the return codes of #getPoolIndex or #findEmpty otherwise.
*/
virtual ReturnValue_t reserveSpace(size_t size, store_address_t* address, bool ignoreFault);
virtual ReturnValue_t reserveSpace(size_t size, store_address_t* address);
private:
/**
@ -188,6 +186,8 @@ class LocalPool : public SystemObject, public StorageManagerIF {
std::vector<std::vector<size_type>> sizeLists =
std::vector<std::vector<size_type>>(NUMBER_OF_SUBPOOLS);
bool ignoreFault = false;
//! A variable to determine whether higher n pools are used if
//! the store is full.
bool spillsToHigherPools = false;

View File

@ -9,10 +9,9 @@ PoolManager::PoolManager(object_id_t setObjectId, const LocalPoolConfig& localPo
PoolManager::~PoolManager() { MutexFactory::instance()->deleteMutex(mutex); }
ReturnValue_t PoolManager::reserveSpace(const size_t size, store_address_t* address,
bool ignoreFault) {
ReturnValue_t PoolManager::reserveSpace(const size_t size, store_address_t* address) {
MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs);
ReturnValue_t status = LocalPool::reserveSpace(size, address, ignoreFault);
ReturnValue_t status = LocalPool::reserveSpace(size, address);
return status;
}

View File

@ -57,7 +57,7 @@ class PoolManager : public LocalPool {
//! Default mutex timeout value to prevent permanent blocking.
uint32_t mutexTimeoutMs = 20;
ReturnValue_t reserveSpace(size_t size, store_address_t* address, bool ignoreFault) override;
ReturnValue_t reserveSpace(size_t size, store_address_t* address) override;
/**
* @brief The mutex is created in the constructor and makes

View File

@ -55,7 +55,7 @@ class StorageManagerIF {
/**
* @brief This is the empty virtual destructor as required for C++ interfaces.
*/
~StorageManagerIF() = default;
virtual ~StorageManagerIF() = default;
/**
* @brief With addData, a free storage position is allocated and data
* stored there.
@ -66,12 +66,7 @@ class StorageManagerIF {
* @return Returns @returnvalue::OK if data was added.
* @returnvalue::FAILED if data could not be added, storageId is unchanged then.
*/
virtual ReturnValue_t addData(store_address_t* storageId, const uint8_t* data, size_t size,
bool ignoreFault) = 0;
virtual ReturnValue_t addData(store_address_t* storageId, const uint8_t* data, size_t size) {
return addData(storageId, data, size, false);
}
virtual ReturnValue_t addData(store_address_t* storageId, const uint8_t* data, size_t size) = 0;
/**
* @brief With deleteData, the storageManager frees the memory region
@ -186,12 +181,8 @@ class StorageManagerIF {
* @return Returns @returnvalue::OK if data was added.
* @returnvalue::FAILED if data could not be added, storageId is unchanged then.
*/
virtual ReturnValue_t getFreeElement(store_address_t* storageId, size_t size, uint8_t** dataPtr,
bool ignoreFault) = 0;
virtual ReturnValue_t getFreeElement(store_address_t* storageId, size_t size, uint8_t** dataPtr) {
return getFreeElement(storageId, size, dataPtr, false);
}
virtual ReturnValue_t getFreeElement(store_address_t* storageId, size_t size,
uint8_t** dataPtr) = 0;
[[nodiscard]] virtual bool hasDataAtId(store_address_t storeId) const = 0;

View File

@ -17,11 +17,11 @@ static constexpr ReturnValue_t INVALID_PACKET_TYPE = MAKE_RETURN_CODE(3);
static constexpr ReturnValue_t INVALID_SEC_HEADER_FIELD = MAKE_RETURN_CODE(4);
static constexpr ReturnValue_t INCORRECT_PRIMARY_HEADER = MAKE_RETURN_CODE(5);
static constexpr ReturnValue_t INCOMPLETE_PACKET = MAKE_RETURN_CODE(5);
static constexpr ReturnValue_t INVALID_PUS_VERSION = MAKE_RETURN_CODE(6);
static constexpr ReturnValue_t INCORRECT_CHECKSUM = MAKE_RETURN_CODE(7);
static constexpr ReturnValue_t ILLEGAL_PACKET_SUBTYPE = MAKE_RETURN_CODE(8);
static constexpr ReturnValue_t INCORRECT_SECONDARY_HEADER = MAKE_RETURN_CODE(9);
static constexpr ReturnValue_t INCOMPLETE_PACKET = MAKE_RETURN_CODE(7);
static constexpr ReturnValue_t INVALID_PUS_VERSION = MAKE_RETURN_CODE(8);
static constexpr ReturnValue_t INCORRECT_CHECKSUM = MAKE_RETURN_CODE(9);
static constexpr ReturnValue_t ILLEGAL_PACKET_SUBTYPE = MAKE_RETURN_CODE(10);
static constexpr ReturnValue_t INCORRECT_SECONDARY_HEADER = MAKE_RETURN_CODE(11);
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::TMTC_DISTRIBUTION;
//! P1: Returnvalue, P2: 0 for TM issues, 1 for TC issues

View File

@ -61,10 +61,16 @@ ReturnValue_t Clock::convertTimevalToTimeOfDay(const timeval* from, TimeOfDay_t*
if (result != returnvalue::OK) {
return result;
}
MutexGuard helper(timeMutex);
// gmtime writes its output in a global buffer which is not Thread Safe
// Therefore we have to use a Mutex here
MutexGuard helper(timeMutex);
#ifdef PLATFORM_WIN
time_t time;
time = from->tv_sec;
timeInfo = gmtime(&time);
#else
timeInfo = gmtime(&from->tv_sec);
#endif
to->year = timeInfo->tm_year + 1900;
to->month = timeInfo->tm_mon + 1;
to->day = timeInfo->tm_mday;

View File

@ -1,8 +1,16 @@
#ifndef FSFW_TIMEMANAGER_TIMEREADERIF_H
#define FSFW_TIMEMANAGER_TIMEREADERIF_H
#include <cstdio>
#include <cstdlib>
#include "fsfw/platform.h"
#ifdef PLATFORM_WIN
// wtf? Required for timeval!
#include <winsock.h>
#endif
#include "TimeStampIF.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/serialize/SerializeIF.h"

View File

@ -21,7 +21,7 @@ SpacePacketReader::~SpacePacketReader() = default;
inline uint16_t SpacePacketReader::getPacketIdRaw() const { return ccsds::getPacketId(*spHeader); }
const uint8_t* SpacePacketReader::getPacketData() { return packetDataField; }
const uint8_t* SpacePacketReader::getPacketData() const { return packetDataField; }
ReturnValue_t SpacePacketReader::setData(uint8_t* data, size_t maxSize_, void* args) {
return setInternalFields(data, maxSize_);

View File

@ -71,7 +71,7 @@ class SpacePacketReader : public SpacePacketIF,
// Helper methods:
[[nodiscard]] ReturnValue_t checkSize() const;
const uint8_t* getPacketData();
const uint8_t* getPacketData() const;
ReturnValue_t setReadOnlyData(const uint8_t* data, size_t maxSize);

View File

@ -23,11 +23,11 @@ constexpr uint16_t getSpacePacketIdFromApid(bool isTc, uint16_t apid,
return ((isTc << 4) | (secondaryHeaderFlag << 3) | ((apid >> 8) & 0x07)) << 8 | (apid & 0x00ff);
}
constexpr uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag = true) {
constexpr uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag) {
return getSpacePacketIdFromApid(true, apid, secondaryHeaderFlag);
}
constexpr uint16_t getTmSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag = true) {
constexpr uint16_t getTmSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag) {
return getSpacePacketIdFromApid(false, apid, secondaryHeaderFlag);
}

View File

@ -23,7 +23,9 @@ class AcceptsTelemetryIF {
*/
[[nodiscard]] virtual MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const = 0;
[[nodiscard]] virtual MessageQueueId_t getReportReceptionQueue() const { return getReportReceptionQueue(0); }
[[nodiscard]] virtual MessageQueueId_t getReportReceptionQueue() const {
return getReportReceptionQueue(0);
}
};
#endif /* FSFW_TMTCSERVICES_ACCEPTSTELEMETRYIF_H_ */

View File

@ -5,20 +5,28 @@
class SourceSequenceCounter {
private:
uint16_t sequenceCount;
uint16_t sequenceCount = 0;
public:
SourceSequenceCounter() : sequenceCount(0) {}
void increment() {
sequenceCount = (sequenceCount + 1) % (SpacePacketBase::LIMIT_SEQUENCE_COUNT);
SourceSequenceCounter(uint16_t initialSequenceCount = 0) : sequenceCount(initialSequenceCount) {}
void increment() { sequenceCount = (sequenceCount + 1) % (ccsds::LIMIT_SEQUENCE_COUNT); }
void decrement() { sequenceCount = (sequenceCount - 1) % (ccsds::LIMIT_SEQUENCE_COUNT); }
uint16_t get() const { return this->sequenceCount; }
void reset(uint16_t toValue = 0) { sequenceCount = toValue % (ccsds::LIMIT_SEQUENCE_COUNT); }
SourceSequenceCounter& operator++(int) {
this->increment();
return *this;
}
void decrement() {
sequenceCount = (sequenceCount - 1) % (SpacePacketBase::LIMIT_SEQUENCE_COUNT);
SourceSequenceCounter& operator--(int) {
this->decrement();
return *this;
}
uint16_t get() { return this->sequenceCount; }
void reset(uint16_t toValue = 0) {
sequenceCount = toValue % (SpacePacketBase::LIMIT_SEQUENCE_COUNT);
SourceSequenceCounter& operator=(const uint16_t& newCount) {
sequenceCount = newCount;
return *this;
}
operator uint16_t() { return this->get(); }
};
#endif /* FSFW_TMTCSERVICES_SOURCESEQUENCECOUNTER_H_ */

View File

@ -65,7 +65,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
/** AcceptsTelemetryIF override */
MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel = 0) const override;
MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
/** AcceptsTelecommandsIF override */
uint32_t getIdentifier() const override;

View File

@ -5,6 +5,14 @@
#include <string>
#include <unordered_map>
#ifdef PLATFORM_WIN
// Defined in Windows header for whatever reason, and leads to nameclash issues with
// class enums which have entries of the same name.
#undef IN
#undef OUT
#undef CALLBACK
#endif
using gpioId_t = uint16_t;
namespace gpio {

View File

@ -5,11 +5,14 @@ endif()
target_sources(${LIB_FSFW_NAME} PRIVATE UnixFileGuard.cpp CommandExecutor.cpp
utility.cpp)
if(FSFW_HAL_LINUX_ADD_LIBGPIOD)
add_subdirectory(gpio)
endif()
if(FSFW_HAL_LINUX_ADD_SERIAL_DRIVERS)
add_subdirectory(serial)
endif()
if(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS)
if(FSFW_HAL_LINUX_ADD_LIBGPIOD)
add_subdirectory(gpio)
endif()
add_subdirectory(uart)
# Adding those does not really make sense on Apple systems which are generally
# host systems. It won't even compile as the headers are missing
if(NOT APPLE)

View File

@ -32,6 +32,8 @@ ReturnValue_t CommandExecutor::execute() {
} else if (state == States::PENDING) {
return COMMAND_PENDING;
}
// Reset data in read vector
std::memset(readVec.data(), 0, readVec.size());
currentCmdFile = popen(currentCmd.c_str(), "r");
if (currentCmdFile == nullptr) {
lastError = errno;
@ -205,3 +207,5 @@ ReturnValue_t CommandExecutor::executeBlocking() {
}
return returnvalue::OK;
}
const std::vector<char>& CommandExecutor::getReadVector() const { return readVec; }

View File

@ -107,6 +107,8 @@ class CommandExecutor {
*/
void reset();
const std::vector<char>& getReadVector() const;
private:
std::string currentCmd;
bool blocking = true;

View File

@ -41,7 +41,7 @@ ReturnValue_t I2cComIF::initializeInterface(CookieIF* cookie) {
i2cAddress = i2cCookie->getAddress();
i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress);
auto i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress);
if (i2cDeviceMapIter == i2cDeviceMap.end()) {
size_t maxReplyLen = i2cCookie->getMaxReplyLen();
I2cInstance i2cInstance = {std::vector<uint8_t>(maxReplyLen), 0};
@ -89,7 +89,7 @@ ReturnValue_t I2cComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, s
}
address_t i2cAddress = i2cCookie->getAddress();
i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress);
auto i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress);
if (i2cDeviceMapIter == i2cDeviceMap.end()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "I2cComIF::sendMessage: i2cAddress of Cookie not "
@ -140,20 +140,19 @@ ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "I2cComIF::requestReceiveMessage: Invalid I2C Cookie!" << std::endl;
#endif
i2cDeviceMapIter->second.replyLen = 0;
return NULLPOINTER;
}
address_t i2cAddress = i2cCookie->getAddress();
i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress);
auto i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress);
if (i2cDeviceMapIter == i2cDeviceMap.end()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "I2cComIF::requestReceiveMessage: i2cAddress of Cookie not "
<< "registered in i2cDeviceMap" << std::endl;
#endif
i2cDeviceMapIter->second.replyLen = 0;
return returnvalue::FAILED;
}
i2cDeviceMapIter->second.replyLen = 0;
deviceFile = i2cCookie->getDeviceFile();
UnixFileGuard fileHelper(deviceFile, &fd, O_RDWR, "I2cComIF::requestReceiveMessage");
@ -162,7 +161,6 @@ ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe
}
result = openDevice(deviceFile, i2cAddress, &fd);
if (result != returnvalue::OK) {
i2cDeviceMapIter->second.replyLen = 0;
return result;
}
@ -170,14 +168,19 @@ ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe
int readLen = read(fd, replyBuffer, requestLen);
if (readLen != static_cast<int>(requestLen)) {
#if FSFW_VERBOSE_LEVEL >= 1 and FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "I2cComIF::requestReceiveMessage: Reading from I2C "
<< "device failed with error code " << errno << ". Description"
<< " of error: " << strerror(errno) << std::endl;
sif::error << "I2cComIF::requestReceiveMessage: Read only " << readLen << " from " << requestLen
<< " bytes" << std::endl;
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
if (readLen < 0) {
sif::warning << "I2cComIF::requestReceiveMessage: Reading from I2C "
<< "device failed with error code " << errno << " | " << strerror(errno)
<< std::endl;
} else {
sif::warning << "I2cComIF::requestReceiveMessage: Read only " << readLen << " from "
<< requestLen << " bytes" << std::endl;
}
#else
#endif
#endif
i2cDeviceMapIter->second.replyLen = 0;
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "I2cComIF::requestReceiveMessage: Read " << readLen << " of " << requestLen
<< " bytes" << std::endl;
@ -204,7 +207,7 @@ ReturnValue_t I2cComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
}
address_t i2cAddress = i2cCookie->getAddress();
i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress);
auto i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress);
if (i2cDeviceMapIter == i2cDeviceMap.end()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "I2cComIF::readReceivedMessage: i2cAddress of Cookie not "
@ -214,7 +217,7 @@ ReturnValue_t I2cComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
}
*buffer = i2cDeviceMapIter->second.replyBuffer.data();
*size = i2cDeviceMapIter->second.replyLen;
i2cDeviceMapIter->second.replyLen = 0;
return returnvalue::OK;
}

View File

@ -36,12 +36,10 @@ class I2cComIF : public DeviceCommunicationIF, public SystemObject {
};
using I2cDeviceMap = std::unordered_map<address_t, I2cInstance>;
using I2cDeviceMapIter = I2cDeviceMap::iterator;
/* In this map all i2c devices will be registered with their address and
* the appropriate file descriptor will be stored */
I2cDeviceMap i2cDeviceMap;
I2cDeviceMapIter i2cDeviceMapIter;
/**
* @brief This function opens an I2C device and binds the opened file

View File

@ -0,0 +1,2 @@
target_sources(${LIB_FSFW_NAME} PUBLIC SerialComIF.cpp SerialCookie.cpp
helper.cpp)

View File

@ -1,4 +1,4 @@
#include "UartComIF.h"
#include "SerialComIF.h"
#include <errno.h>
#include <fcntl.h>
@ -11,19 +11,18 @@
#include "fsfw/serviceinterface.h"
#include "fsfw_hal/linux/utility.h"
UartComIF::UartComIF(object_id_t objectId) : SystemObject(objectId) {}
SerialComIF::SerialComIF(object_id_t objectId) : SystemObject(objectId) {}
UartComIF::~UartComIF() {}
SerialComIF::~SerialComIF() {}
ReturnValue_t UartComIF::initializeInterface(CookieIF* cookie) {
ReturnValue_t SerialComIF::initializeInterface(CookieIF* cookie) {
std::string deviceFile;
UartDeviceMapIter uartDeviceMapIter;
if (cookie == nullptr) {
return NULLPOINTER;
}
UartCookie* uartCookie = dynamic_cast<UartCookie*>(cookie);
SerialCookie* uartCookie = dynamic_cast<SerialCookie*>(cookie);
if (uartCookie == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "UartComIF::initializeInterface: Invalid UART Cookie!" << std::endl;
@ -33,7 +32,7 @@ ReturnValue_t UartComIF::initializeInterface(CookieIF* cookie) {
deviceFile = uartCookie->getDeviceFile();
uartDeviceMapIter = uartDeviceMap.find(deviceFile);
auto uartDeviceMapIter = uartDeviceMap.find(deviceFile);
if (uartDeviceMapIter == uartDeviceMap.end()) {
int fileDescriptor = configureUartPort(uartCookie);
if (fileDescriptor < 0) {
@ -60,7 +59,7 @@ ReturnValue_t UartComIF::initializeInterface(CookieIF* cookie) {
return returnvalue::OK;
}
int UartComIF::configureUartPort(UartCookie* uartCookie) {
int SerialComIF::configureUartPort(SerialCookie* uartCookie) {
struct termios options = {};
std::string deviceFile = uartCookie->getDeviceFile();
@ -89,11 +88,11 @@ int UartComIF::configureUartPort(UartCookie* uartCookie) {
return fd;
}
setParityOptions(&options, uartCookie);
uart::setParity(options, uartCookie->getParity());
setStopBitOptions(&options, uartCookie);
setDatasizeOptions(&options, uartCookie);
setFixedOptions(&options);
setUartMode(&options, *uartCookie);
uart::setMode(options, uartCookie->getUartMode());
if (uartCookie->getInputShouldBeFlushed()) {
tcflush(fd, TCIFLUSH);
}
@ -102,7 +101,7 @@ int UartComIF::configureUartPort(UartCookie* uartCookie) {
options.c_cc[VTIME] = 0;
options.c_cc[VMIN] = 0;
configureBaudrate(&options, uartCookie);
uart::setBaudrate(options, uartCookie->getBaudrate());
/* Save option settings */
if (tcsetattr(fd, TCSANOW, &options) != 0) {
@ -115,24 +114,7 @@ int UartComIF::configureUartPort(UartCookie* uartCookie) {
return fd;
}
void UartComIF::setParityOptions(struct termios* options, UartCookie* uartCookie) {
/* Clear parity bit */
options->c_cflag &= ~PARENB;
switch (uartCookie->getParity()) {
case Parity::EVEN:
options->c_cflag |= PARENB;
options->c_cflag &= ~PARODD;
break;
case Parity::ODD:
options->c_cflag |= PARENB;
options->c_cflag |= PARODD;
break;
default:
break;
}
}
void UartComIF::setStopBitOptions(struct termios* options, UartCookie* uartCookie) {
void SerialComIF::setStopBitOptions(struct termios* options, SerialCookie* uartCookie) {
/* Clear stop field. Sets stop bit to one bit */
options->c_cflag &= ~CSTOPB;
switch (uartCookie->getStopBits()) {
@ -144,7 +126,7 @@ void UartComIF::setStopBitOptions(struct termios* options, UartCookie* uartCooki
}
}
void UartComIF::setDatasizeOptions(struct termios* options, UartCookie* uartCookie) {
void SerialComIF::setDatasizeOptions(struct termios* options, SerialCookie* uartCookie) {
/* Clear size bits */
options->c_cflag &= ~CSIZE;
switch (uartCookie->getBitsPerWord()) {
@ -168,7 +150,7 @@ void UartComIF::setDatasizeOptions(struct termios* options, UartCookie* uartCook
}
}
void UartComIF::setFixedOptions(struct termios* options) {
void SerialComIF::setFixedOptions(struct termios* options) {
/* Disable RTS/CTS hardware flow control */
options->c_cflag &= ~CRTSCTS;
/* Turn on READ & ignore ctrl lines (CLOCAL = 1) */
@ -191,142 +173,9 @@ void UartComIF::setFixedOptions(struct termios* options) {
options->c_oflag &= ~ONLCR;
}
void UartComIF::configureBaudrate(struct termios* options, UartCookie* uartCookie) {
switch (uartCookie->getBaudrate()) {
case UartBaudRate::RATE_50:
cfsetispeed(options, B50);
cfsetospeed(options, B50);
break;
case UartBaudRate::RATE_75:
cfsetispeed(options, B75);
cfsetospeed(options, B75);
break;
case UartBaudRate::RATE_110:
cfsetispeed(options, B110);
cfsetospeed(options, B110);
break;
case UartBaudRate::RATE_134:
cfsetispeed(options, B134);
cfsetospeed(options, B134);
break;
case UartBaudRate::RATE_150:
cfsetispeed(options, B150);
cfsetospeed(options, B150);
break;
case UartBaudRate::RATE_200:
cfsetispeed(options, B200);
cfsetospeed(options, B200);
break;
case UartBaudRate::RATE_300:
cfsetispeed(options, B300);
cfsetospeed(options, B300);
break;
case UartBaudRate::RATE_600:
cfsetispeed(options, B600);
cfsetospeed(options, B600);
break;
case UartBaudRate::RATE_1200:
cfsetispeed(options, B1200);
cfsetospeed(options, B1200);
break;
case UartBaudRate::RATE_1800:
cfsetispeed(options, B1800);
cfsetospeed(options, B1800);
break;
case UartBaudRate::RATE_2400:
cfsetispeed(options, B2400);
cfsetospeed(options, B2400);
break;
case UartBaudRate::RATE_4800:
cfsetispeed(options, B4800);
cfsetospeed(options, B4800);
break;
case UartBaudRate::RATE_9600:
cfsetispeed(options, B9600);
cfsetospeed(options, B9600);
break;
case UartBaudRate::RATE_19200:
cfsetispeed(options, B19200);
cfsetospeed(options, B19200);
break;
case UartBaudRate::RATE_38400:
cfsetispeed(options, B38400);
cfsetospeed(options, B38400);
break;
case UartBaudRate::RATE_57600:
cfsetispeed(options, B57600);
cfsetospeed(options, B57600);
break;
case UartBaudRate::RATE_115200:
cfsetispeed(options, B115200);
cfsetospeed(options, B115200);
break;
case UartBaudRate::RATE_230400:
cfsetispeed(options, B230400);
cfsetospeed(options, B230400);
break;
#ifndef __APPLE__
case UartBaudRate::RATE_460800:
cfsetispeed(options, B460800);
cfsetospeed(options, B460800);
break;
case UartBaudRate::RATE_500000:
cfsetispeed(options, B500000);
cfsetospeed(options, B500000);
break;
case UartBaudRate::RATE_576000:
cfsetispeed(options, B576000);
cfsetospeed(options, B576000);
break;
case UartBaudRate::RATE_921600:
cfsetispeed(options, B921600);
cfsetospeed(options, B921600);
break;
case UartBaudRate::RATE_1000000:
cfsetispeed(options, B1000000);
cfsetospeed(options, B1000000);
break;
case UartBaudRate::RATE_1152000:
cfsetispeed(options, B1152000);
cfsetospeed(options, B1152000);
break;
case UartBaudRate::RATE_1500000:
cfsetispeed(options, B1500000);
cfsetospeed(options, B1500000);
break;
case UartBaudRate::RATE_2000000:
cfsetispeed(options, B2000000);
cfsetospeed(options, B2000000);
break;
case UartBaudRate::RATE_2500000:
cfsetispeed(options, B2500000);
cfsetospeed(options, B2500000);
break;
case UartBaudRate::RATE_3000000:
cfsetispeed(options, B3000000);
cfsetospeed(options, B3000000);
break;
case UartBaudRate::RATE_3500000:
cfsetispeed(options, B3500000);
cfsetospeed(options, B3500000);
break;
case UartBaudRate::RATE_4000000:
cfsetispeed(options, B4000000);
cfsetospeed(options, B4000000);
break;
#endif // ! __APPLE__
default:
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UartComIF::configureBaudrate: Baudrate not supported" << std::endl;
#endif
break;
}
}
ReturnValue_t UartComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) {
ReturnValue_t SerialComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) {
int fd = 0;
std::string deviceFile;
UartDeviceMapIter uartDeviceMapIter;
if (sendLen == 0) {
return returnvalue::OK;
@ -339,7 +188,7 @@ ReturnValue_t UartComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData,
return returnvalue::FAILED;
}
UartCookie* uartCookie = dynamic_cast<UartCookie*>(cookie);
SerialCookie* uartCookie = dynamic_cast<SerialCookie*>(cookie);
if (uartCookie == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UartComIF::sendMessasge: Invalid UART Cookie!" << std::endl;
@ -348,7 +197,7 @@ ReturnValue_t UartComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData,
}
deviceFile = uartCookie->getDeviceFile();
uartDeviceMapIter = uartDeviceMap.find(deviceFile);
auto uartDeviceMapIter = uartDeviceMap.find(deviceFile);
if (uartDeviceMapIter == uartDeviceMap.end()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "UartComIF::sendMessage: Device file " << deviceFile << "not in UART map"
@ -370,13 +219,12 @@ ReturnValue_t UartComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData,
return returnvalue::OK;
}
ReturnValue_t UartComIF::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; }
ReturnValue_t SerialComIF::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; }
ReturnValue_t UartComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
ReturnValue_t SerialComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
std::string deviceFile;
UartDeviceMapIter uartDeviceMapIter;
UartCookie* uartCookie = dynamic_cast<UartCookie*>(cookie);
SerialCookie* uartCookie = dynamic_cast<SerialCookie*>(cookie);
if (uartCookie == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "UartComIF::requestReceiveMessage: Invalid Uart Cookie!" << std::endl;
@ -386,7 +234,7 @@ ReturnValue_t UartComIF::requestReceiveMessage(CookieIF* cookie, size_t requestL
UartModes uartMode = uartCookie->getUartMode();
deviceFile = uartCookie->getDeviceFile();
uartDeviceMapIter = uartDeviceMap.find(deviceFile);
auto uartDeviceMapIter = uartDeviceMap.find(deviceFile);
if (uartMode == UartModes::NON_CANONICAL and requestLen == 0) {
return returnvalue::OK;
@ -409,8 +257,8 @@ ReturnValue_t UartComIF::requestReceiveMessage(CookieIF* cookie, size_t requestL
}
}
ReturnValue_t UartComIF::handleCanonicalRead(UartCookie& uartCookie, UartDeviceMapIter& iter,
size_t requestLen) {
ReturnValue_t SerialComIF::handleCanonicalRead(SerialCookie& uartCookie,
UartDeviceMap::iterator& iter, size_t requestLen) {
ReturnValue_t result = returnvalue::OK;
uint8_t maxReadCycles = uartCookie.getReadCycles();
uint8_t currentReadCycles = 0;
@ -467,8 +315,9 @@ ReturnValue_t UartComIF::handleCanonicalRead(UartCookie& uartCookie, UartDeviceM
return result;
}
ReturnValue_t UartComIF::handleNoncanonicalRead(UartCookie& uartCookie, UartDeviceMapIter& iter,
size_t requestLen) {
ReturnValue_t SerialComIF::handleNoncanonicalRead(SerialCookie& uartCookie,
UartDeviceMap::iterator& iter,
size_t requestLen) {
int fd = iter->second.fileDescriptor;
auto bufferPtr = iter->second.replyBuffer.data();
// Size check to prevent buffer overflow
@ -501,11 +350,10 @@ ReturnValue_t UartComIF::handleNoncanonicalRead(UartCookie& uartCookie, UartDevi
return returnvalue::OK;
}
ReturnValue_t UartComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) {
ReturnValue_t SerialComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) {
std::string deviceFile;
UartDeviceMapIter uartDeviceMapIter;
UartCookie* uartCookie = dynamic_cast<UartCookie*>(cookie);
SerialCookie* uartCookie = dynamic_cast<SerialCookie*>(cookie);
if (uartCookie == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "UartComIF::readReceivedMessage: Invalid uart cookie!" << std::endl;
@ -514,7 +362,7 @@ ReturnValue_t UartComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
}
deviceFile = uartCookie->getDeviceFile();
uartDeviceMapIter = uartDeviceMap.find(deviceFile);
auto uartDeviceMapIter = uartDeviceMap.find(deviceFile);
if (uartDeviceMapIter == uartDeviceMap.end()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "UartComIF::readReceivedMessage: Device file " << deviceFile << " not in uart map"
@ -532,10 +380,9 @@ ReturnValue_t UartComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
return returnvalue::OK;
}
ReturnValue_t UartComIF::flushUartRxBuffer(CookieIF* cookie) {
ReturnValue_t SerialComIF::flushUartRxBuffer(CookieIF* cookie) {
std::string deviceFile;
UartDeviceMapIter uartDeviceMapIter;
UartCookie* uartCookie = dynamic_cast<UartCookie*>(cookie);
SerialCookie* uartCookie = dynamic_cast<SerialCookie*>(cookie);
if (uartCookie == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UartComIF::flushUartRxBuffer: Invalid uart cookie!" << std::endl;
@ -543,7 +390,7 @@ ReturnValue_t UartComIF::flushUartRxBuffer(CookieIF* cookie) {
return NULLPOINTER;
}
deviceFile = uartCookie->getDeviceFile();
uartDeviceMapIter = uartDeviceMap.find(deviceFile);
auto uartDeviceMapIter = uartDeviceMap.find(deviceFile);
if (uartDeviceMapIter != uartDeviceMap.end()) {
int fd = uartDeviceMapIter->second.fileDescriptor;
tcflush(fd, TCIFLUSH);
@ -552,10 +399,9 @@ ReturnValue_t UartComIF::flushUartRxBuffer(CookieIF* cookie) {
return returnvalue::FAILED;
}
ReturnValue_t UartComIF::flushUartTxBuffer(CookieIF* cookie) {
ReturnValue_t SerialComIF::flushUartTxBuffer(CookieIF* cookie) {
std::string deviceFile;
UartDeviceMapIter uartDeviceMapIter;
UartCookie* uartCookie = dynamic_cast<UartCookie*>(cookie);
SerialCookie* uartCookie = dynamic_cast<SerialCookie*>(cookie);
if (uartCookie == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UartComIF::flushUartTxBuffer: Invalid uart cookie!" << std::endl;
@ -563,7 +409,7 @@ ReturnValue_t UartComIF::flushUartTxBuffer(CookieIF* cookie) {
return NULLPOINTER;
}
deviceFile = uartCookie->getDeviceFile();
uartDeviceMapIter = uartDeviceMap.find(deviceFile);
auto uartDeviceMapIter = uartDeviceMap.find(deviceFile);
if (uartDeviceMapIter != uartDeviceMap.end()) {
int fd = uartDeviceMapIter->second.fileDescriptor;
tcflush(fd, TCOFLUSH);
@ -572,10 +418,9 @@ ReturnValue_t UartComIF::flushUartTxBuffer(CookieIF* cookie) {
return returnvalue::FAILED;
}
ReturnValue_t UartComIF::flushUartTxAndRxBuf(CookieIF* cookie) {
ReturnValue_t SerialComIF::flushUartTxAndRxBuf(CookieIF* cookie) {
std::string deviceFile;
UartDeviceMapIter uartDeviceMapIter;
UartCookie* uartCookie = dynamic_cast<UartCookie*>(cookie);
SerialCookie* uartCookie = dynamic_cast<SerialCookie*>(cookie);
if (uartCookie == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UartComIF::flushUartTxAndRxBuf: Invalid uart cookie!" << std::endl;
@ -583,7 +428,7 @@ ReturnValue_t UartComIF::flushUartTxAndRxBuf(CookieIF* cookie) {
return NULLPOINTER;
}
deviceFile = uartCookie->getDeviceFile();
uartDeviceMapIter = uartDeviceMap.find(deviceFile);
auto uartDeviceMapIter = uartDeviceMap.find(deviceFile);
if (uartDeviceMapIter != uartDeviceMap.end()) {
int fd = uartDeviceMapIter->second.fileDescriptor;
tcflush(fd, TCIOFLUSH);
@ -591,13 +436,3 @@ ReturnValue_t UartComIF::flushUartTxAndRxBuf(CookieIF* cookie) {
}
return returnvalue::FAILED;
}
void UartComIF::setUartMode(struct termios* options, UartCookie& uartCookie) {
UartModes uartMode = uartCookie.getUartMode();
if (uartMode == UartModes::NON_CANONICAL) {
/* Disable canonical mode */
options->c_lflag &= ~ICANON;
} else if (uartMode == UartModes::CANONICAL) {
options->c_lflag |= ICANON;
}
}

View File

@ -3,12 +3,12 @@
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw_hal/linux/serial/SerialCookie.h>
#include <fsfw_hal/linux/serial/helper.h>
#include <unordered_map>
#include <vector>
#include "UartCookie.h"
/**
* @brief This is the communication interface to access serial ports on linux based operating
* systems.
@ -18,7 +18,7 @@
*
* @author J. Meier
*/
class UartComIF : public DeviceCommunicationIF, public SystemObject {
class SerialComIF : public DeviceCommunicationIF, public SystemObject {
public:
static constexpr uint8_t uartRetvalId = CLASS_ID::HAL_UART;
@ -26,9 +26,9 @@ class UartComIF : public DeviceCommunicationIF, public SystemObject {
static constexpr ReturnValue_t UART_READ_SIZE_MISSMATCH = returnvalue::makeCode(uartRetvalId, 2);
static constexpr ReturnValue_t UART_RX_BUFFER_TOO_SMALL = returnvalue::makeCode(uartRetvalId, 3);
UartComIF(object_id_t objectId);
SerialComIF(object_id_t objectId);
virtual ~UartComIF();
virtual ~SerialComIF();
ReturnValue_t initializeInterface(CookieIF* cookie) override;
ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override;
@ -62,7 +62,6 @@ class UartComIF : public DeviceCommunicationIF, public SystemObject {
};
using UartDeviceMap = std::unordered_map<UartDeviceFile_t, UartElements>;
using UartDeviceMapIter = UartDeviceMap::iterator;
/**
* The uart devie map stores informations of initialized uart ports.
@ -76,20 +75,9 @@ class UartComIF : public DeviceCommunicationIF, public SystemObject {
* uart device file, baudrate, parity, stopbits etc.
* @return The file descriptor of the configured uart.
*/
int configureUartPort(UartCookie* uartCookie);
int configureUartPort(SerialCookie* uartCookie);
/**
* @brief This function adds the parity settings to the termios options struct.
*
* @param options Pointer to termios options struct which will be modified to enable or disable
* parity checking.
* @param uartCookie Pointer to uart cookie containing the information about the desired
* parity settings.
*
*/
void setParityOptions(struct termios* options, UartCookie* uartCookie);
void setStopBitOptions(struct termios* options, UartCookie* uartCookie);
void setStopBitOptions(struct termios* options, SerialCookie* uartCookie);
/**
* @brief This function sets options which are not configurable by the uartCookie.
@ -99,19 +87,11 @@ class UartComIF : public DeviceCommunicationIF, public SystemObject {
/**
* @brief With this function the datasize settings are added to the termios options struct.
*/
void setDatasizeOptions(struct termios* options, UartCookie* uartCookie);
void setDatasizeOptions(struct termios* options, SerialCookie* uartCookie);
/**
* @brief This functions adds the baudrate specified in the uartCookie to the termios options
* struct.
*/
void configureBaudrate(struct termios* options, UartCookie* uartCookie);
void setUartMode(struct termios* options, UartCookie& uartCookie);
ReturnValue_t handleCanonicalRead(UartCookie& uartCookie, UartDeviceMapIter& iter,
ReturnValue_t handleCanonicalRead(SerialCookie& uartCookie, UartDeviceMap::iterator& iter,
size_t requestLen);
ReturnValue_t handleNoncanonicalRead(UartCookie& uartCookie, UartDeviceMapIter& iter,
ReturnValue_t handleNoncanonicalRead(SerialCookie& uartCookie, UartDeviceMap::iterator& iter,
size_t requestLen);
};

View File

@ -0,0 +1,51 @@
#include "SerialCookie.h"
#include <fsfw/serviceinterface.h>
SerialCookie::SerialCookie(object_id_t handlerId, std::string deviceFile, UartBaudRate baudrate,
size_t maxReplyLen, UartModes uartMode)
: handlerId(handlerId),
deviceFile(deviceFile),
uartMode(uartMode),
baudrate(baudrate),
maxReplyLen(maxReplyLen) {}
SerialCookie::~SerialCookie() {}
UartBaudRate SerialCookie::getBaudrate() const { return baudrate; }
size_t SerialCookie::getMaxReplyLen() const { return maxReplyLen; }
std::string SerialCookie::getDeviceFile() const { return deviceFile; }
void SerialCookie::setParityOdd() { parity = Parity::ODD; }
void SerialCookie::setParityEven() { parity = Parity::EVEN; }
Parity SerialCookie::getParity() const { return parity; }
void SerialCookie::setBitsPerWord(BitsPerWord bitsPerWord_) { bitsPerWord = bitsPerWord_; }
BitsPerWord SerialCookie::getBitsPerWord() const { return bitsPerWord; }
StopBits SerialCookie::getStopBits() const { return stopBits; }
void SerialCookie::setTwoStopBits() { stopBits = StopBits::TWO_STOP_BITS; }
void SerialCookie::setOneStopBit() { stopBits = StopBits::ONE_STOP_BIT; }
UartModes SerialCookie::getUartMode() const { return uartMode; }
void SerialCookie::setReadCycles(uint8_t readCycles) { this->readCycles = readCycles; }
void SerialCookie::setToFlushInput(bool enable) { this->flushInput = enable; }
uint8_t SerialCookie::getReadCycles() const { return readCycles; }
bool SerialCookie::getInputShouldBeFlushed() { return this->flushInput; }
object_id_t SerialCookie::getHandlerId() const { return this->handlerId; }
void SerialCookie::setNoFixedSizeReply() { replySizeFixed = false; }
bool SerialCookie::isReplySizeFixed() { return replySizeFixed; }

View File

@ -3,50 +3,10 @@
#include <fsfw/devicehandlers/CookieIF.h>
#include <fsfw/objectmanager/SystemObjectIF.h>
#include <fsfw_hal/linux/serial/helper.h>
#include <string>
enum class Parity { NONE, EVEN, ODD };
enum class StopBits { ONE_STOP_BIT, TWO_STOP_BITS };
enum class UartModes { CANONICAL, NON_CANONICAL };
enum class BitsPerWord { BITS_5, BITS_6, BITS_7, BITS_8 };
enum class UartBaudRate {
RATE_50,
RATE_75,
RATE_110,
RATE_134,
RATE_150,
RATE_200,
RATE_300,
RATE_600,
RATE_1200,
RATE_1800,
RATE_2400,
RATE_4800,
RATE_9600,
RATE_19200,
RATE_38400,
RATE_57600,
RATE_115200,
RATE_230400,
RATE_460800,
RATE_500000,
RATE_576000,
RATE_921600,
RATE_1000000,
RATE_1152000,
RATE_1500000,
RATE_2000000,
RATE_2500000,
RATE_3000000,
RATE_3500000,
RATE_4000000
};
/**
* @brief Cookie for the UartComIF. There are many options available to configure the UART driver.
* The constructor only requests for common options like the baudrate. Other options can
@ -54,7 +14,7 @@ enum class UartBaudRate {
*
* @author J. Meier
*/
class UartCookie : public CookieIF {
class SerialCookie : public CookieIF {
public:
/**
* @brief Constructor for the uart cookie.
@ -69,10 +29,10 @@ class UartCookie : public CookieIF {
* 8 databits (number of bits transfered with one uart frame)
* One stop bit
*/
UartCookie(object_id_t handlerId, std::string deviceFile, UartModes uartMode,
UartBaudRate baudrate, size_t maxReplyLen);
SerialCookie(object_id_t handlerId, std::string deviceFile, UartBaudRate baudrate,
size_t maxReplyLen, UartModes uartMode = UartModes::NON_CANONICAL);
virtual ~UartCookie();
virtual ~SerialCookie();
UartBaudRate getBaudrate() const;
size_t getMaxReplyLen() const;

View File

@ -0,0 +1,163 @@
#include <fsfw_hal/linux/serial/helper.h>
#include <sys/ioctl.h>
#include "fsfw/serviceinterface.h"
void uart::setMode(struct termios& options, UartModes mode) {
if (mode == UartModes::NON_CANONICAL) {
/* Disable canonical mode */
options.c_lflag &= ~ICANON;
} else if (mode == UartModes::CANONICAL) {
options.c_lflag |= ICANON;
}
}
void uart::setBaudrate(struct termios& options, UartBaudRate baud) {
switch (baud) {
case UartBaudRate::RATE_50:
cfsetspeed(&options, B50);
break;
case UartBaudRate::RATE_75:
cfsetspeed(&options, B75);
break;
case UartBaudRate::RATE_110:
cfsetspeed(&options, B110);
break;
case UartBaudRate::RATE_134:
cfsetspeed(&options, B134);
break;
case UartBaudRate::RATE_150:
cfsetspeed(&options, B150);
break;
case UartBaudRate::RATE_200:
cfsetspeed(&options, B200);
break;
case UartBaudRate::RATE_300:
cfsetspeed(&options, B300);
break;
case UartBaudRate::RATE_600:
cfsetspeed(&options, B600);
break;
case UartBaudRate::RATE_1200:
cfsetspeed(&options, B1200);
break;
case UartBaudRate::RATE_1800:
cfsetspeed(&options, B1800);
break;
case UartBaudRate::RATE_2400:
cfsetspeed(&options, B2400);
break;
case UartBaudRate::RATE_4800:
cfsetspeed(&options, B4800);
break;
case UartBaudRate::RATE_9600:
cfsetspeed(&options, B9600);
break;
case UartBaudRate::RATE_19200:
cfsetspeed(&options, B19200);
break;
case UartBaudRate::RATE_38400:
cfsetspeed(&options, B38400);
break;
case UartBaudRate::RATE_57600:
cfsetspeed(&options, B57600);
break;
case UartBaudRate::RATE_115200:
cfsetspeed(&options, B115200);
break;
case UartBaudRate::RATE_230400:
cfsetspeed(&options, B230400);
break;
#ifndef __APPLE__
case UartBaudRate::RATE_460800:
cfsetspeed(&options, B460800);
break;
case UartBaudRate::RATE_500000:
cfsetspeed(&options, B500000);
break;
case UartBaudRate::RATE_576000:
cfsetspeed(&options, B576000);
break;
case UartBaudRate::RATE_921600:
cfsetspeed(&options, B921600);
break;
case UartBaudRate::RATE_1000000:
cfsetspeed(&options, B1000000);
break;
case UartBaudRate::RATE_1152000:
cfsetspeed(&options, B1152000);
break;
case UartBaudRate::RATE_1500000:
cfsetspeed(&options, B1500000);
break;
case UartBaudRate::RATE_2000000:
cfsetspeed(&options, B2000000);
break;
case UartBaudRate::RATE_2500000:
cfsetspeed(&options, B2500000);
break;
case UartBaudRate::RATE_3000000:
cfsetspeed(&options, B3000000);
break;
case UartBaudRate::RATE_3500000:
cfsetspeed(&options, B3500000);
break;
case UartBaudRate::RATE_4000000:
cfsetspeed(&options, B4000000);
break;
#endif // ! __APPLE__
default:
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UartComIF::configureBaudrate: Baudrate not supported" << std::endl;
#endif
break;
}
}
void uart::setBitsPerWord(struct termios& options, BitsPerWord bits) {
options.c_cflag &= ~CSIZE; // Clear all the size bits
if (bits == BitsPerWord::BITS_5) {
options.c_cflag |= CS5;
} else if (bits == BitsPerWord::BITS_6) {
options.c_cflag |= CS6;
} else if (bits == BitsPerWord::BITS_7) {
options.c_cflag |= CS7;
} else if (bits == BitsPerWord::BITS_8) {
options.c_cflag |= CS8;
}
}
void uart::enableRead(struct termios& options) { options.c_cflag |= CREAD; }
void uart::ignoreCtrlLines(struct termios& options) { options.c_cflag |= CLOCAL; }
void uart::setParity(struct termios& options, Parity parity) {
/* Clear parity bit */
options.c_cflag &= ~PARENB;
switch (parity) {
case Parity::EVEN:
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
break;
case Parity::ODD:
options.c_cflag |= PARENB;
options.c_cflag |= PARODD;
break;
default:
break;
}
}
int uart::readCountersAndErrors(int serialPort, serial_icounter_struct& icounter) {
return ioctl(serialPort, TIOCGICOUNT, &icounter);
}
void uart::setStopbits(struct termios& options, StopBits bits) {
if (bits == StopBits::TWO_STOP_BITS) {
// Use two stop bits
options.c_cflag |= CSTOPB;
} else {
// Clear stop field, only one stop bit used in communication
options.c_cflag &= ~CSTOPB;
}
}

View File

@ -0,0 +1,71 @@
#ifndef FSFW_HAL_LINUX_UART_HELPER_H_
#define FSFW_HAL_LINUX_UART_HELPER_H_
#include <linux/serial.h>
#include <termios.h>
enum class Parity { NONE, EVEN, ODD };
enum class StopBits { ONE_STOP_BIT, TWO_STOP_BITS };
enum class UartModes { CANONICAL, NON_CANONICAL };
enum class BitsPerWord { BITS_5, BITS_6, BITS_7, BITS_8 };
enum class UartBaudRate {
RATE_50,
RATE_75,
RATE_110,
RATE_134,
RATE_150,
RATE_200,
RATE_300,
RATE_600,
RATE_1200,
RATE_1800,
RATE_2400,
RATE_4800,
RATE_9600,
RATE_19200,
RATE_38400,
RATE_57600,
RATE_115200,
RATE_230400,
RATE_460800,
RATE_500000,
RATE_576000,
RATE_921600,
RATE_1000000,
RATE_1152000,
RATE_1500000,
RATE_2000000,
RATE_2500000,
RATE_3000000,
RATE_3500000,
RATE_4000000
};
namespace uart {
void setMode(struct termios& options, UartModes mode);
/**
* @brief This functions adds the baudrate specified in the uartCookie to the termios options
* struct.
*/
void setBaudrate(struct termios& options, UartBaudRate baud);
void setStopbits(struct termios& options, StopBits bits);
void setBitsPerWord(struct termios& options, BitsPerWord bits);
void enableRead(struct termios& options);
void setParity(struct termios& options, Parity parity);
void ignoreCtrlLines(struct termios& options);
int readCountersAndErrors(int serialPort, serial_icounter_struct& icounter);
} // namespace uart
#endif /* FSFW_HAL_LINUX_UART_HELPER_H_ */

View File

@ -1 +0,0 @@
target_sources(${LIB_FSFW_NAME} PUBLIC UartComIF.cpp UartCookie.cpp)

View File

@ -1,51 +0,0 @@
#include "UartCookie.h"
#include <fsfw/serviceinterface.h>
UartCookie::UartCookie(object_id_t handlerId, std::string deviceFile, UartModes uartMode,
UartBaudRate baudrate, size_t maxReplyLen)
: handlerId(handlerId),
deviceFile(deviceFile),
uartMode(uartMode),
baudrate(baudrate),
maxReplyLen(maxReplyLen) {}
UartCookie::~UartCookie() {}
UartBaudRate UartCookie::getBaudrate() const { return baudrate; }
size_t UartCookie::getMaxReplyLen() const { return maxReplyLen; }
std::string UartCookie::getDeviceFile() const { return deviceFile; }
void UartCookie::setParityOdd() { parity = Parity::ODD; }
void UartCookie::setParityEven() { parity = Parity::EVEN; }
Parity UartCookie::getParity() const { return parity; }
void UartCookie::setBitsPerWord(BitsPerWord bitsPerWord_) { bitsPerWord = bitsPerWord_; }
BitsPerWord UartCookie::getBitsPerWord() const { return bitsPerWord; }
StopBits UartCookie::getStopBits() const { return stopBits; }
void UartCookie::setTwoStopBits() { stopBits = StopBits::TWO_STOP_BITS; }
void UartCookie::setOneStopBit() { stopBits = StopBits::ONE_STOP_BIT; }
UartModes UartCookie::getUartMode() const { return uartMode; }
void UartCookie::setReadCycles(uint8_t readCycles) { this->readCycles = readCycles; }
void UartCookie::setToFlushInput(bool enable) { this->flushInput = enable; }
uint8_t UartCookie::getReadCycles() const { return readCycles; }
bool UartCookie::getInputShouldBeFlushed() { return this->flushInput; }
object_id_t UartCookie::getHandlerId() const { return this->handlerId; }
void UartCookie::setNoFixedSizeReply() { replySizeFixed = false; }
bool UartCookie::isReplySizeFixed() { return replySizeFixed; }

View File

@ -1,6 +1,7 @@
#include "UioMapper.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <filesystem>
@ -13,7 +14,23 @@ const char UioMapper::UIO_PATH_PREFIX[] = "/sys/class/uio/";
const char UioMapper::MAP_SUBSTR[] = "/maps/map";
const char UioMapper::SIZE_FILE_PATH[] = "/size";
UioMapper::UioMapper(std::string uioFile, int mapNum) : uioFile(uioFile), mapNum(mapNum) {}
UioMapper::UioMapper(std::string uioFile, int mapNum) : mapNum(mapNum) {
struct stat buf;
lstat(uioFile.c_str(), &buf);
if (S_ISLNK(buf.st_mode)) {
char* res = realpath(uioFile.c_str(), nullptr);
if (res) {
this->uioFile = res;
free(res);
} else {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Could not resolve real path of UIO file " << uioFile << std::endl;
#endif
}
} else {
this->uioFile = std::move(uioFile);
}
}
UioMapper::~UioMapper() {}
@ -22,7 +39,7 @@ ReturnValue_t UioMapper::getMappedAdress(uint32_t** address, Permissions permiss
int fd = open(uioFile.c_str(), O_RDWR);
if (fd < 1) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PtmeAxiConfig::initialize: Invalid UIO device file" << std::endl;
sif::error << "UioMapper::getMappedAdress: Invalid UIO device file " << uioFile << std::endl;
#endif
return returnvalue::FAILED;
}