Improve Subsystem DHB logic #112
@ -460,7 +460,7 @@ ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceComm
|
|||||||
info.expectedReplies = 0;
|
info.expectedReplies = 0;
|
||||||
info.isExecuting = false;
|
info.isExecuting = false;
|
||||||
info.sendReplyTo = NO_COMMANDER;
|
info.sendReplyTo = NO_COMMANDER;
|
||||||
info.useAlternativeReplyId = alternativeReplyId;
|
info.useAlternativeReplyId = useAlternativeReply;
|
||||||
info.alternativeReplyId = alternativeReplyId;
|
info.alternativeReplyId = alternativeReplyId;
|
||||||
auto resultPair = deviceCommandMap.emplace(deviceCommand, info);
|
auto resultPair = deviceCommandMap.emplace(deviceCommand, info);
|
||||||
if (resultPair.second) {
|
if (resultPair.second) {
|
||||||
@ -1602,3 +1602,14 @@ const HasHealthIF* DeviceHandlerBase::getOptHealthIF() const { return this; }
|
|||||||
const HasModesIF& DeviceHandlerBase::getModeIF() const { return *this; }
|
const HasModesIF& DeviceHandlerBase::getModeIF() const { return *this; }
|
||||||
|
|
||||||
ModeTreeChildIF& DeviceHandlerBase::getModeTreeChildIF() { return *this; }
|
ModeTreeChildIF& DeviceHandlerBase::getModeTreeChildIF() { return *this; }
|
||||||
|
|
||||||
|
ReturnValue_t DeviceHandlerBase::finishAction(bool success, DeviceCommandId_t action,
|
||||||
|
ReturnValue_t result) {
|
||||||
|
auto commandIter = deviceCommandMap.find(action);
|
||||||
|
if (commandIter == deviceCommandMap.end()) {
|
||||||
|
return MessageQueueIF::NO_QUEUE;
|
||||||
|
}
|
||||||
|
commandIter->second.isExecuting = false;
|
||||||
|
actionHelper.finish(success, commandIter->second.sendReplyTo, action, result);
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
@ -407,6 +407,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
*/
|
*/
|
||||||
virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) = 0;
|
virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) = 0;
|
||||||
MessageQueueId_t getCommanderQueueId(DeviceCommandId_t replyId) const;
|
MessageQueueId_t getCommanderQueueId(DeviceCommandId_t replyId) const;
|
||||||
|
ReturnValue_t finishAction(bool success, DeviceCommandId_t action, ReturnValue_t result);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to get pending command. This is useful for devices
|
* Helper function to get pending command. This is useful for devices
|
||||||
* like SPI sensors to identify the last sent command.
|
* like SPI sensors to identify the last sent command.
|
||||||
|
@ -3,159 +3,95 @@
|
|||||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
DleParser::DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf,
|
DleParser::DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf,
|
||||||
BufPair decodedBuf, UserHandler handler, void* args)
|
BufPair decodedBuf)
|
||||||
: decodeRingBuf(decodeRingBuf),
|
: decodeRingBuf(decodeRingBuf),
|
||||||
decoder(decoder),
|
decoder(decoder),
|
||||||
encodedBuf(encodedBuf),
|
encodedBuf(encodedBuf),
|
||||||
decodedBuf(decodedBuf),
|
decodedBuf(decodedBuf) {
|
||||||
handler(handler),
|
|
||||||
ctx(args) {
|
|
||||||
if (handler == nullptr) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "DleParser::DleParser: Invalid user handler" << std::endl;
|
|
||||||
#else
|
|
||||||
sif::printError("DleParser::DleParser: Invalid user handler\n");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t DleParser::passData(uint8_t* data, size_t len) {
|
ReturnValue_t DleParser::passData(const uint8_t* data, size_t len) {
|
||||||
if (data == nullptr or len == 0 or handler == nullptr) {
|
if (data == nullptr or len == 0) {
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
size_t copyIntoRingBufFromHere = 0;
|
return decodeRingBuf.writeData(data, len);
|
||||||
size_t copyAmount = len;
|
}
|
||||||
size_t startIdx = 0;
|
|
||||||
ReturnValue_t result = returnvalue::OK;
|
ReturnValue_t DleParser::parseRingBuf(size_t& readSize) {
|
||||||
bool startFoundInThisPacket = false;
|
ctx.setType(DleParser::ContextType::NONE);
|
||||||
for (size_t idx = 0; idx < len; idx++) {
|
size_t availableData = decodeRingBuf.getAvailableReadData();
|
||||||
if (data[idx] == DleEncoder::STX_CHAR) {
|
if(availableData == 0) {
|
||||||
if (not startFound and not startFoundInThisPacket) {
|
return NO_PACKET_FOUND;
|
||||||
startIdx = idx;
|
}
|
||||||
copyIntoRingBufFromHere = idx;
|
if (availableData > encodedBuf.second) {
|
||||||
copyAmount = len - idx;
|
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 {
|
} else {
|
||||||
// Maybe print warning, should not happen
|
// might be lost packet, so we should advance the read pointer
|
||||||
decodeRingBuf.clear();
|
// without skipping the STX
|
||||||
|
readSize = vectorIdx;
|
||||||
ErrorInfo info;
|
ErrorInfo info;
|
||||||
info.len = idx;
|
setErrorContext(ErrorTypes::CONSECUTIVE_STX_CHARS, info);
|
||||||
prepareErrorContext(ErrorTypes::CONSECUTIVE_STX_CHARS, info);
|
return POSSIBLE_PACKET_LOSS;
|
||||||
handler(ctx);
|
|
||||||
copyIntoRingBufFromHere = idx;
|
|
||||||
copyAmount = len - idx;
|
|
||||||
}
|
}
|
||||||
startFound = true;
|
}
|
||||||
startFoundInThisPacket = true;
|
// handle ETX char
|
||||||
} else if (data[idx] == DleEncoder::ETX_CHAR) {
|
if (encodedBuf.first[vectorIdx] == DleEncoder::ETX_CHAR) {
|
||||||
if (startFoundInThisPacket) {
|
if (stxFound) {
|
||||||
size_t readLen = 0;
|
// This is propably a packet, so we decode it.
|
||||||
size_t decodedLen = 0;
|
size_t decodedLen = 0;
|
||||||
result = decoder.decode(data + startIdx, idx + 1 - startIdx, &readLen, decodedBuf.first,
|
size_t dummy = 0;
|
||||||
decodedBuf.second, &decodedLen);
|
|
||||||
|
ReturnValue_t result =
|
||||||
|
decoder.decode(&encodedBuf.first[stxIdx], availableData - stxIdx, &dummy,
|
||||||
|
decodedBuf.first, decodedBuf.second, &decodedLen);
|
||||||
if (result == returnvalue::OK) {
|
if (result == returnvalue::OK) {
|
||||||
ctx.setType(ContextType::PACKET_FOUND);
|
ctx.setType(ContextType::PACKET_FOUND);
|
||||||
ctx.decodedPacket.first = decodedBuf.first;
|
ctx.decodedPacket.first = decodedBuf.first;
|
||||||
ctx.decodedPacket.second = decodedLen;
|
ctx.decodedPacket.second = decodedLen;
|
||||||
this->handler(ctx);
|
readSize = ++vectorIdx;
|
||||||
} else if (result == DleEncoder::STREAM_TOO_SHORT) {
|
return returnvalue::OK;
|
||||||
|
} else {
|
||||||
|
// invalid packet, skip.
|
||||||
|
readSize = ++vectorIdx;
|
||||||
ErrorInfo info;
|
ErrorInfo info;
|
||||||
info.res = result;
|
info.res = result;
|
||||||
prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
|
setErrorContext(ErrorTypes::DECODE_ERROR, info);
|
||||||
handler(ctx);
|
return POSSIBLE_PACKET_LOSS;
|
||||||
} else {
|
|
||||||
ErrorInfo info;
|
|
||||||
info.res = result;
|
|
||||||
prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
|
|
||||||
handler(ctx);
|
|
||||||
}
|
|
||||||
decodeRingBuf.clear();
|
|
||||||
if ((idx + 1) < len) {
|
|
||||||
copyIntoRingBufFromHere = idx + 1;
|
|
||||||
copyAmount = len - idx - 1;
|
|
||||||
} else {
|
|
||||||
copyAmount = 0;
|
|
||||||
}
|
|
||||||
} else if (startFound) {
|
|
||||||
// ETX found but STX was found in another mini packet. Reconstruct the full packet
|
|
||||||
// to decode it
|
|
||||||
result = decodeRingBuf.writeData(data, idx + 1);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
ErrorInfo info;
|
|
||||||
info.res = result;
|
|
||||||
prepareErrorContext(ErrorTypes::RING_BUF_ERROR, info);
|
|
||||||
handler(ctx);
|
|
||||||
}
|
|
||||||
size_t fullEncodedLen = decodeRingBuf.getAvailableReadData();
|
|
||||||
if (fullEncodedLen > encodedBuf.second) {
|
|
||||||
ErrorInfo info;
|
|
||||||
info.len = fullEncodedLen;
|
|
||||||
prepareErrorContext(ErrorTypes::ENCODED_BUF_TOO_SMALL, info);
|
|
||||||
handler(ctx);
|
|
||||||
decodeRingBuf.clear();
|
|
||||||
} else {
|
|
||||||
size_t decodedLen = 0;
|
|
||||||
size_t readLen = 0;
|
|
||||||
decodeRingBuf.readData(encodedBuf.first, fullEncodedLen, true);
|
|
||||||
result = decoder.decode(encodedBuf.first, fullEncodedLen, &readLen, decodedBuf.first,
|
|
||||||
decodedBuf.second, &decodedLen);
|
|
||||||
if (result == returnvalue::OK) {
|
|
||||||
if (this->handler != nullptr) {
|
|
||||||
ctx.setType(ContextType::PACKET_FOUND);
|
|
||||||
ctx.decodedPacket.first = decodedBuf.first;
|
|
||||||
ctx.decodedPacket.second = decodedLen;
|
|
||||||
this->handler(ctx);
|
|
||||||
}
|
|
||||||
} else if (result == DleEncoder::STREAM_TOO_SHORT) {
|
|
||||||
ErrorInfo info;
|
|
||||||
info.res = result;
|
|
||||||
prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
|
|
||||||
handler(ctx);
|
|
||||||
} else {
|
|
||||||
ErrorInfo info;
|
|
||||||
info.res = result;
|
|
||||||
prepareErrorContext(ErrorTypes::DECODE_ERROR, info);
|
|
||||||
handler(ctx);
|
|
||||||
}
|
|
||||||
decodeRingBuf.clear();
|
|
||||||
startFound = false;
|
|
||||||
startFoundInThisPacket = false;
|
|
||||||
if ((idx + 1) < len) {
|
|
||||||
copyIntoRingBufFromHere = idx + 1;
|
|
||||||
copyAmount = len - idx - 1;
|
|
||||||
} else {
|
|
||||||
copyAmount = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// End data without preceeding STX
|
// might be lost packet, so we should advance the read pointer
|
||||||
|
readSize = ++vectorIdx;
|
||||||
ErrorInfo info;
|
ErrorInfo info;
|
||||||
info.len = idx + 1;
|
info.len = 0;
|
||||||
prepareErrorContext(ErrorTypes::CONSECUTIVE_ETX_CHARS, info);
|
setErrorContext(ErrorTypes::CONSECUTIVE_ETX_CHARS, info);
|
||||||
handler(ctx);
|
return POSSIBLE_PACKET_LOSS;
|
||||||
decodeRingBuf.clear();
|
|
||||||
if ((idx + 1) < len) {
|
|
||||||
copyIntoRingBufFromHere = idx + 1;
|
|
||||||
copyAmount = len - idx - 1;
|
|
||||||
} else {
|
|
||||||
copyAmount = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
startFoundInThisPacket = false;
|
|
||||||
startFound = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (copyAmount > 0) {
|
return NO_PACKET_FOUND;
|
||||||
result = decodeRingBuf.writeData(data + copyIntoRingBufFromHere, copyAmount);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
ErrorInfo info;
|
|
||||||
info.res = result;
|
|
||||||
prepareErrorContext(ErrorTypes::RING_BUF_ERROR, info);
|
|
||||||
handler(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DleParser::defaultFoundPacketHandler(uint8_t* packet, size_t len, void* args) {
|
void DleParser::defaultFoundPacketHandler(uint8_t* packet, size_t len, void* args) {
|
||||||
@ -169,8 +105,12 @@ void DleParser::defaultFoundPacketHandler(uint8_t* packet, size_t len, void* arg
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void DleParser::defaultErrorHandler(ErrorTypes err, ErrorInfo ctx) {
|
void DleParser::defaultErrorHandler() {
|
||||||
switch (err) {
|
if(ctx.getType() != DleParser::ContextType::ERROR) {
|
||||||
|
errorPrinter("No error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (ctx.error.first) {
|
||||||
case (ErrorTypes::NONE): {
|
case (ErrorTypes::NONE): {
|
||||||
errorPrinter("No error");
|
errorPrinter("No error");
|
||||||
break;
|
break;
|
||||||
@ -186,8 +126,8 @@ void DleParser::defaultErrorHandler(ErrorTypes err, ErrorInfo ctx) {
|
|||||||
case (ErrorTypes::ENCODED_BUF_TOO_SMALL):
|
case (ErrorTypes::ENCODED_BUF_TOO_SMALL):
|
||||||
case (ErrorTypes::DECODING_BUF_TOO_SMALL): {
|
case (ErrorTypes::DECODING_BUF_TOO_SMALL): {
|
||||||
char opt[64];
|
char opt[64];
|
||||||
snprintf(opt, sizeof(opt), ": Too small for packet with length %zu", ctx.len);
|
snprintf(opt, sizeof(opt), ": Too small for packet with length %zu", ctx.decodedPacket.second);
|
||||||
if (err == ErrorTypes::ENCODED_BUF_TOO_SMALL) {
|
if (ctx.error.first == ErrorTypes::ENCODED_BUF_TOO_SMALL) {
|
||||||
errorPrinter("Encoded buf too small", opt);
|
errorPrinter("Encoded buf too small", opt);
|
||||||
} else {
|
} else {
|
||||||
errorPrinter("Decoding buf too small", opt);
|
errorPrinter("Decoding buf too small", opt);
|
||||||
@ -218,13 +158,20 @@ void DleParser::errorPrinter(const char* str, const char* opt) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void DleParser::prepareErrorContext(ErrorTypes err, ErrorInfo info) {
|
void DleParser::setErrorContext(ErrorTypes err, ErrorInfo info) {
|
||||||
ctx.setType(ContextType::ERROR);
|
ctx.setType(ContextType::ERROR);
|
||||||
ctx.error.first = err;
|
ctx.error.first = err;
|
||||||
ctx.error.second = info;
|
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() {
|
void DleParser::reset() {
|
||||||
startFound = false;
|
|
||||||
decodeRingBuf.clear();
|
decodeRingBuf.clear();
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,11 @@
|
|||||||
*/
|
*/
|
||||||
class DleParser {
|
class DleParser {
|
||||||
public:
|
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>;
|
using BufPair = std::pair<uint8_t*, size_t>;
|
||||||
|
|
||||||
enum class ContextType { PACKET_FOUND, ERROR };
|
enum class ContextType { NONE, PACKET_FOUND, ERROR };
|
||||||
|
|
||||||
enum class ErrorTypes {
|
enum class ErrorTypes {
|
||||||
NONE,
|
NONE,
|
||||||
@ -41,7 +43,7 @@ class DleParser {
|
|||||||
|
|
||||||
struct Context {
|
struct Context {
|
||||||
public:
|
public:
|
||||||
Context(void* args) : userArgs(args) { setType(ContextType::PACKET_FOUND); }
|
Context() { setType(ContextType::PACKET_FOUND); }
|
||||||
|
|
||||||
void setType(ContextType type) {
|
void setType(ContextType type) {
|
||||||
this->type = type;
|
this->type = type;
|
||||||
@ -58,14 +60,11 @@ class DleParser {
|
|||||||
|
|
||||||
BufPair decodedPacket = {};
|
BufPair decodedPacket = {};
|
||||||
ErrorPair error;
|
ErrorPair error;
|
||||||
void* userArgs;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ContextType type;
|
ContextType type;
|
||||||
};
|
};
|
||||||
|
|
||||||
using UserHandler = void (*)(const Context& ctx);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class constructor
|
* Base class constructor
|
||||||
* @param decodeRingBuf Ring buffer used to store multiple packets to allow detecting DLE packets
|
* @param decodeRingBuf Ring buffer used to store multiple packets to allow detecting DLE packets
|
||||||
@ -79,7 +78,7 @@ class DleParser {
|
|||||||
* @param args Arbitrary user argument
|
* @param args Arbitrary user argument
|
||||||
*/
|
*/
|
||||||
DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf,
|
DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf,
|
||||||
BufPair decodedBuf, UserHandler handler, void* args);
|
BufPair decodedBuf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function allows to pass new data into the parser. It then scans for DLE packets
|
* This function allows to pass new data into the parser. It then scans for DLE packets
|
||||||
@ -88,8 +87,13 @@ class DleParser {
|
|||||||
* @param len
|
* @param len
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t passData(uint8_t* data, size_t len);
|
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
|
* Example found packet handler
|
||||||
* function call
|
* function call
|
||||||
@ -104,11 +108,11 @@ class DleParser {
|
|||||||
* - For buffer length errors, will be set to the detected packet length which is too large
|
* - 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
|
* - For decode or ring buffer errors, will be set to the result returned from the failed call
|
||||||
*/
|
*/
|
||||||
static void defaultErrorHandler(ErrorTypes err, ErrorInfo ctx);
|
void defaultErrorHandler();
|
||||||
|
|
||||||
static void errorPrinter(const char* str, const char* opt = nullptr);
|
static void errorPrinter(const char* str, const char* opt = nullptr);
|
||||||
|
|
||||||
void prepareErrorContext(ErrorTypes err, ErrorInfo ctx);
|
void setErrorContext(ErrorTypes err, ErrorInfo ctx);
|
||||||
/**
|
/**
|
||||||
* Resets the parser by resetting the internal states and clearing the decoding ring buffer
|
* Resets the parser by resetting the internal states and clearing the decoding ring buffer
|
||||||
*/
|
*/
|
||||||
@ -119,7 +123,5 @@ class DleParser {
|
|||||||
DleEncoder& decoder;
|
DleEncoder& decoder;
|
||||||
BufPair encodedBuf;
|
BufPair encodedBuf;
|
||||||
BufPair decodedBuf;
|
BufPair decodedBuf;
|
||||||
UserHandler handler = nullptr;
|
|
||||||
Context ctx;
|
Context ctx;
|
||||||
bool startFound = false;
|
|
||||||
};
|
};
|
||||||
|
@ -1 +1 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PUBLIC UartComIF.cpp UartCookie.cpp)
|
target_sources(${LIB_FSFW_NAME} PUBLIC UartComIF.cpp UartCookie.cpp helper.cpp)
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "UartComIF.h"
|
#include "UartComIF.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
@ -93,7 +92,7 @@ int UartComIF::configureUartPort(UartCookie* uartCookie) {
|
|||||||
setStopBitOptions(&options, uartCookie);
|
setStopBitOptions(&options, uartCookie);
|
||||||
setDatasizeOptions(&options, uartCookie);
|
setDatasizeOptions(&options, uartCookie);
|
||||||
setFixedOptions(&options);
|
setFixedOptions(&options);
|
||||||
setUartMode(&options, *uartCookie);
|
uart::setMode(options, uartCookie->getUartMode());
|
||||||
if (uartCookie->getInputShouldBeFlushed()) {
|
if (uartCookie->getInputShouldBeFlushed()) {
|
||||||
tcflush(fd, TCIFLUSH);
|
tcflush(fd, TCIFLUSH);
|
||||||
}
|
}
|
||||||
@ -102,7 +101,7 @@ int UartComIF::configureUartPort(UartCookie* uartCookie) {
|
|||||||
options.c_cc[VTIME] = 0;
|
options.c_cc[VTIME] = 0;
|
||||||
options.c_cc[VMIN] = 0;
|
options.c_cc[VMIN] = 0;
|
||||||
|
|
||||||
configureBaudrate(&options, uartCookie);
|
uart::setBaudrate(options, uartCookie->getBaudrate());
|
||||||
|
|
||||||
/* Save option settings */
|
/* Save option settings */
|
||||||
if (tcsetattr(fd, TCSANOW, &options) != 0) {
|
if (tcsetattr(fd, TCSANOW, &options) != 0) {
|
||||||
@ -191,138 +190,6 @@ void UartComIF::setFixedOptions(struct termios* options) {
|
|||||||
options->c_oflag &= ~ONLCR;
|
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 UartComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) {
|
||||||
int fd = 0;
|
int fd = 0;
|
||||||
std::string deviceFile;
|
std::string deviceFile;
|
||||||
@ -592,12 +459,4 @@ ReturnValue_t UartComIF::flushUartTxAndRxBuf(CookieIF* cookie) {
|
|||||||
return returnvalue::FAILED;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
#ifndef BSP_Q7S_COMIF_UARTCOMIF_H_
|
#ifndef BSP_Q7S_COMIF_UARTCOMIF_H_
|
||||||
#define BSP_Q7S_COMIF_UARTCOMIF_H_
|
#define BSP_Q7S_COMIF_UARTCOMIF_H_
|
||||||
|
|
||||||
|
#include "UartCookie.h"
|
||||||
|
#include "helper.h"
|
||||||
|
|
||||||
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
|
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
|
||||||
#include <fsfw/objectmanager/SystemObject.h>
|
#include <fsfw/objectmanager/SystemObject.h>
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "UartCookie.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is the communication interface to access serial ports on linux based operating
|
* @brief This is the communication interface to access serial ports on linux based operating
|
||||||
@ -101,14 +103,6 @@ class UartComIF : public DeviceCommunicationIF, public SystemObject {
|
|||||||
*/
|
*/
|
||||||
void setDatasizeOptions(struct termios* options, UartCookie* uartCookie);
|
void setDatasizeOptions(struct termios* options, UartCookie* 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(UartCookie& uartCookie, UartDeviceMapIter& iter,
|
||||||
size_t requestLen);
|
size_t requestLen);
|
||||||
ReturnValue_t handleNoncanonicalRead(UartCookie& uartCookie, UartDeviceMapIter& iter,
|
ReturnValue_t handleNoncanonicalRead(UartCookie& uartCookie, UartDeviceMapIter& iter,
|
||||||
|
@ -1,51 +1,14 @@
|
|||||||
#ifndef SAM9G20_COMIF_COOKIES_UART_COOKIE_H_
|
#ifndef SAM9G20_COMIF_COOKIES_UART_COOKIE_H_
|
||||||
#define SAM9G20_COMIF_COOKIES_UART_COOKIE_H_
|
#define SAM9G20_COMIF_COOKIES_UART_COOKIE_H_
|
||||||
|
|
||||||
|
#include "helper.h"
|
||||||
|
|
||||||
#include <fsfw/devicehandlers/CookieIF.h>
|
#include <fsfw/devicehandlers/CookieIF.h>
|
||||||
#include <fsfw/objectmanager/SystemObjectIF.h>
|
#include <fsfw/objectmanager/SystemObjectIF.h>
|
||||||
|
|
||||||
#include <string>
|
#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.
|
* @brief Cookie for the UartComIF. There are many options available to configure the UART driver.
|
||||||
|
150
src/fsfw_hal/linux/uart/helper.cpp
Normal file
150
src/fsfw_hal/linux/uart/helper.cpp
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
#include "helper.h"
|
||||||
|
#include "fsfw/serviceinterface.h"
|
||||||
|
|
||||||
|
#include <sys/ioctl.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:
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int uart::readCountersAndErrors(int serialPort, serial_icounter_struct& icounter) {
|
||||||
|
return ioctl(serialPort, TIOCGICOUNT, &icounter);
|
||||||
|
}
|
||||||
|
|
62
src/fsfw_hal/linux/uart/helper.h
Normal file
62
src/fsfw_hal/linux/uart/helper.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#ifndef FSFW_HAL_LINUX_UART_HELPER_H_
|
||||||
|
#define FSFW_HAL_LINUX_UART_HELPER_H_
|
||||||
|
|
||||||
|
#include <termios.h>
|
||||||
|
#include <linux/serial.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);
|
||||||
|
|
||||||
|
int readCountersAndErrors(int serialPort, serial_icounter_struct& icounter);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* FSFW_HAL_LINUX_UART_HELPER_H_ */
|
Loading…
Reference in New Issue
Block a user