eive-obsw/linux/payload/SerialCommunicationHelper.cpp

127 lines
3.9 KiB
C++
Raw Normal View History

2024-04-30 15:14:22 +02:00
#include "SerialCommunicationHelper.h"
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <cstring>
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw_hal/linux/serial/helper.h"
SerialCommunicationHelper::SerialCommunicationHelper(SerialConfig cfg) : cfg(cfg) {}
ReturnValue_t SerialCommunicationHelper::initialize() {
fd = configureUartPort();
if (fd < 0) {
return returnvalue::FAILED;
}
return returnvalue::OK;
}
int SerialCommunicationHelper::rawFd() const { return fd; }
ReturnValue_t SerialCommunicationHelper::send(const uint8_t* data, size_t dataLen) {
if (write(fd, data, dataLen) != static_cast<int>(dataLen)) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "UartComIF::sendMessage: Failed to send data with error code " << errno
<< ": Error description: " << strerror(errno) << std::endl;
#endif
return returnvalue::FAILED;
}
return returnvalue::OK;
}
int SerialCommunicationHelper::configureUartPort() {
struct termios options = {};
int flags = O_RDWR;
if (cfg.getUartMode() == UartModes::CANONICAL) {
// In non-canonical mode, don't specify O_NONBLOCK because these properties will be
// controlled by the VTIME and VMIN parameters and O_NONBLOCK would override this
flags |= O_NONBLOCK;
}
int fd = open(cfg.getDeviceFile().c_str(), flags);
if (fd < 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UartComIF::configureUartPort: Failed to open uart "
<< cfg.getDeviceFile().c_str()
<< "with error code " << errno << strerror(errno) << std::endl;
#endif
return fd;
}
/* Read in existing settings */
if (tcgetattr(fd, &options) != 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UartComIF::configureUartPort: Error " << errno
<< "from tcgetattr: " << strerror(errno) << std::endl;
#endif
return fd;
}
serial::setParity(options, cfg.getParity());
serial::setStopbits(options, cfg.getStopBits());
serial::setBitsPerWord(options, cfg.getBitsPerWord());
setFixedOptions(&options);
serial::setMode(options, cfg.getUartMode());
tcflush(fd, TCIFLUSH);
/* Sets uart to non-blocking mode. Read returns immediately when there are no data available */
options.c_cc[VTIME] = 0;
options.c_cc[VMIN] = 0;
serial::setBaudrate(options, cfg.getBaudrate());
/* Save option settings */
if (tcsetattr(fd, TCSANOW, &options) != 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UartComIF::configureUartPort: Failed to set options with error " << errno
<< ": " << strerror(errno);
#endif
return fd;
}
return fd;
}
void SerialCommunicationHelper::setFixedOptions(struct termios* options) {
/* Disable RTS/CTS hardware flow control */
options->c_cflag &= ~CRTSCTS;
/* Turn on READ & ignore ctrl lines (CLOCAL = 1) */
options->c_cflag |= CREAD | CLOCAL;
/* Disable echo */
options->c_lflag &= ~ECHO;
/* Disable erasure */
options->c_lflag &= ~ECHOE;
/* Disable new-line echo */
options->c_lflag &= ~ECHONL;
/* Disable interpretation of INTR, QUIT and SUSP */
options->c_lflag &= ~ISIG;
/* Turn off s/w flow ctrl */
options->c_iflag &= ~(IXON | IXOFF | IXANY);
/* Disable any special handling of received bytes */
options->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL);
/* Prevent special interpretation of output bytes (e.g. newline chars) */
options->c_oflag &= ~OPOST;
/* Prevent conversion of newline to carriage return/line feed */
options->c_oflag &= ~ONLCR;
}
ReturnValue_t SerialCommunicationHelper::flushUartRxBuffer() {
serial::flushRxBuf(fd);
return returnvalue::OK;
}
ReturnValue_t SerialCommunicationHelper::flushUartTxBuffer() {
serial::flushTxBuf(fd);
return returnvalue::OK;
}
ReturnValue_t SerialCommunicationHelper::flushUartTxAndRxBuf() {
serial::flushTxRxBuf(fd);
return returnvalue::OK;
}