#include "SerialCommunicationHelper.h" #include #include #include #include #include #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(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; }