diff --git a/src/fsfw/devicehandlers/DeviceHandlerBase.cpp b/src/fsfw/devicehandlers/DeviceHandlerBase.cpp index 61329366..69fa9399 100644 --- a/src/fsfw/devicehandlers/DeviceHandlerBase.cpp +++ b/src/fsfw/devicehandlers/DeviceHandlerBase.cpp @@ -460,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) { @@ -1602,3 +1602,14 @@ const HasHealthIF* DeviceHandlerBase::getOptHealthIF() const { return this; } const HasModesIF& DeviceHandlerBase::getModeIF() const { 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; +} diff --git a/src/fsfw/devicehandlers/DeviceHandlerBase.h b/src/fsfw/devicehandlers/DeviceHandlerBase.h index d7a896d5..6cf453e5 100644 --- a/src/fsfw/devicehandlers/DeviceHandlerBase.h +++ b/src/fsfw/devicehandlers/DeviceHandlerBase.h @@ -407,6 +407,8 @@ class DeviceHandlerBase : public DeviceHandlerIF, */ virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) = 0; 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 * like SPI sensors to identify the last sent command. diff --git a/src/fsfw/globalfunctions/DleParser.cpp b/src/fsfw/globalfunctions/DleParser.cpp index 44c75bab..90adfa7a 100644 --- a/src/fsfw/globalfunctions/DleParser.cpp +++ b/src/fsfw/globalfunctions/DleParser.cpp @@ -3,159 +3,95 @@ #include #include +#include +#include DleParser::DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf, - BufPair decodedBuf, UserHandler handler, void* args) + BufPair decodedBuf) : decodeRingBuf(decodeRingBuf), decoder(decoder), encodedBuf(encodedBuf), - 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 - } + decodedBuf(decodedBuf) { } -ReturnValue_t DleParser::passData(uint8_t* data, size_t len) { - if (data == nullptr or len == 0 or handler == nullptr) { +ReturnValue_t DleParser::passData(const uint8_t* data, size_t len) { + if (data == nullptr or len == 0) { return returnvalue::FAILED; } - size_t copyIntoRingBufFromHere = 0; - size_t copyAmount = len; - size_t startIdx = 0; - ReturnValue_t result = returnvalue::OK; - bool startFoundInThisPacket = false; - for (size_t idx = 0; idx < len; idx++) { - if (data[idx] == DleEncoder::STX_CHAR) { - if (not startFound and not startFoundInThisPacket) { - startIdx = idx; - copyIntoRingBufFromHere = idx; - copyAmount = len - idx; + 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 { - // Maybe print warning, should not happen - decodeRingBuf.clear(); + // might be lost packet, so we should advance the read pointer + // without skipping the STX + readSize = vectorIdx; ErrorInfo info; - info.len = idx; - prepareErrorContext(ErrorTypes::CONSECUTIVE_STX_CHARS, info); - handler(ctx); - copyIntoRingBufFromHere = idx; - copyAmount = len - idx; + setErrorContext(ErrorTypes::CONSECUTIVE_STX_CHARS, info); + return POSSIBLE_PACKET_LOSS; } - startFound = true; - startFoundInThisPacket = true; - } else if (data[idx] == DleEncoder::ETX_CHAR) { - if (startFoundInThisPacket) { - size_t readLen = 0; + } + // 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; - result = decoder.decode(data + startIdx, idx + 1 - startIdx, &readLen, decodedBuf.first, - decodedBuf.second, &decodedLen); + 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; - this->handler(ctx); - } else if (result == DleEncoder::STREAM_TOO_SHORT) { + readSize = ++vectorIdx; + return returnvalue::OK; + } else { + // invalid packet, skip. + readSize = ++vectorIdx; ErrorInfo info; info.res = result; - prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info); - handler(ctx); - } 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; - } + setErrorContext(ErrorTypes::DECODE_ERROR, info); + return POSSIBLE_PACKET_LOSS; } } else { - // End data without preceeding STX + // might be lost packet, so we should advance the read pointer + readSize = ++vectorIdx; ErrorInfo info; - info.len = idx + 1; - prepareErrorContext(ErrorTypes::CONSECUTIVE_ETX_CHARS, info); - handler(ctx); - decodeRingBuf.clear(); - if ((idx + 1) < len) { - copyIntoRingBufFromHere = idx + 1; - copyAmount = len - idx - 1; - } else { - copyAmount = 0; - } + info.len = 0; + setErrorContext(ErrorTypes::CONSECUTIVE_ETX_CHARS, info); + return POSSIBLE_PACKET_LOSS; } - startFoundInThisPacket = false; - startFound = false; } } - if (copyAmount > 0) { - 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; + return NO_PACKET_FOUND; } 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 } -void DleParser::defaultErrorHandler(ErrorTypes err, ErrorInfo ctx) { - switch (err) { +void DleParser::defaultErrorHandler() { + if(ctx.getType() != DleParser::ContextType::ERROR) { + errorPrinter("No error"); + return; + } + switch (ctx.error.first) { case (ErrorTypes::NONE): { errorPrinter("No error"); break; @@ -186,8 +126,8 @@ void DleParser::defaultErrorHandler(ErrorTypes err, ErrorInfo ctx) { 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.len); - if (err == ErrorTypes::ENCODED_BUF_TOO_SMALL) { + 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); @@ -218,13 +158,20 @@ void DleParser::errorPrinter(const char* str, const char* opt) { #endif } -void DleParser::prepareErrorContext(ErrorTypes err, ErrorInfo info) { +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() { - startFound = false; decodeRingBuf.clear(); } diff --git a/src/fsfw/globalfunctions/DleParser.h b/src/fsfw/globalfunctions/DleParser.h index 5ccd55df..9802017a 100644 --- a/src/fsfw/globalfunctions/DleParser.h +++ b/src/fsfw/globalfunctions/DleParser.h @@ -18,9 +18,11 @@ */ 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; - enum class ContextType { PACKET_FOUND, ERROR }; + enum class ContextType { NONE, PACKET_FOUND, ERROR }; enum class ErrorTypes { NONE, @@ -41,7 +43,7 @@ class DleParser { struct Context { public: - Context(void* args) : userArgs(args) { setType(ContextType::PACKET_FOUND); } + Context() { setType(ContextType::PACKET_FOUND); } void setType(ContextType type) { this->type = type; @@ -58,14 +60,11 @@ class DleParser { BufPair decodedPacket = {}; ErrorPair error; - void* userArgs; private: ContextType type; }; - using UserHandler = void (*)(const Context& ctx); - /** * Base class constructor * @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 */ 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 @@ -88,8 +87,13 @@ class DleParser { * @param len * @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 * 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 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); - 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 */ @@ -119,7 +123,5 @@ class DleParser { DleEncoder& decoder; BufPair encodedBuf; BufPair decodedBuf; - UserHandler handler = nullptr; Context ctx; - bool startFound = false; }; diff --git a/src/fsfw_hal/linux/uart/CMakeLists.txt b/src/fsfw_hal/linux/uart/CMakeLists.txt index 9cad62a4..d8daa9ff 100644 --- a/src/fsfw_hal/linux/uart/CMakeLists.txt +++ b/src/fsfw_hal/linux/uart/CMakeLists.txt @@ -1 +1 @@ -target_sources(${LIB_FSFW_NAME} PUBLIC UartComIF.cpp UartCookie.cpp) +target_sources(${LIB_FSFW_NAME} PUBLIC UartComIF.cpp UartCookie.cpp helper.cpp) diff --git a/src/fsfw_hal/linux/uart/UartComIF.cpp b/src/fsfw_hal/linux/uart/UartComIF.cpp index 8947c562..df21da64 100644 --- a/src/fsfw_hal/linux/uart/UartComIF.cpp +++ b/src/fsfw_hal/linux/uart/UartComIF.cpp @@ -1,5 +1,4 @@ #include "UartComIF.h" - #include #include #include @@ -93,7 +92,7 @@ int UartComIF::configureUartPort(UartCookie* uartCookie) { 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) { @@ -191,138 +190,6 @@ 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) { int fd = 0; std::string deviceFile; @@ -592,12 +459,4 @@ 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; - } -} + diff --git a/src/fsfw_hal/linux/uart/UartComIF.h b/src/fsfw_hal/linux/uart/UartComIF.h index 77318166..940938d9 100644 --- a/src/fsfw_hal/linux/uart/UartComIF.h +++ b/src/fsfw_hal/linux/uart/UartComIF.h @@ -1,13 +1,15 @@ #ifndef BSP_Q7S_COMIF_UARTCOMIF_H_ #define BSP_Q7S_COMIF_UARTCOMIF_H_ +#include "UartCookie.h" +#include "helper.h" + #include #include #include #include -#include "UartCookie.h" /** * @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); - /** - * @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, size_t requestLen); ReturnValue_t handleNoncanonicalRead(UartCookie& uartCookie, UartDeviceMapIter& iter, diff --git a/src/fsfw_hal/linux/uart/UartCookie.h b/src/fsfw_hal/linux/uart/UartCookie.h index cae33d58..6fa2bd1b 100644 --- a/src/fsfw_hal/linux/uart/UartCookie.h +++ b/src/fsfw_hal/linux/uart/UartCookie.h @@ -1,51 +1,14 @@ #ifndef SAM9G20_COMIF_COOKIES_UART_COOKIE_H_ #define SAM9G20_COMIF_COOKIES_UART_COOKIE_H_ +#include "helper.h" + #include #include #include -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. diff --git a/src/fsfw_hal/linux/uart/helper.cpp b/src/fsfw_hal/linux/uart/helper.cpp new file mode 100644 index 00000000..b451f457 --- /dev/null +++ b/src/fsfw_hal/linux/uart/helper.cpp @@ -0,0 +1,150 @@ +#include "helper.h" +#include "fsfw/serviceinterface.h" + +#include + +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); +} + diff --git a/src/fsfw_hal/linux/uart/helper.h b/src/fsfw_hal/linux/uart/helper.h new file mode 100644 index 00000000..b6a524d6 --- /dev/null +++ b/src/fsfw_hal/linux/uart/helper.h @@ -0,0 +1,62 @@ +#ifndef FSFW_HAL_LINUX_UART_HELPER_H_ +#define FSFW_HAL_LINUX_UART_HELPER_H_ + +#include +#include + +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_ */