From 703c788c31ca431af198ed82f8046d3cedc67fbd Mon Sep 17 00:00:00 2001 From: Bernardo Carvalho Date: Tue, 21 Oct 2025 14:19:34 +0100 Subject: [PATCH] Added UART 9 bit files Signed-off-by: Bernardo Carvalho --- DataSources/UARTOutput/Makefile.inc | 2 +- DataSources/UARTOutput/UART9Bit.cpp | 375 ++++++++++++++++++++++++++++ DataSources/UARTOutput/UART9Bit.h | 164 ++++++++++++ DataSources/UARTOutput/UARTOutput.h | 4 +- 4 files changed, 542 insertions(+), 3 deletions(-) create mode 100644 DataSources/UARTOutput/UART9Bit.cpp create mode 100644 DataSources/UARTOutput/UART9Bit.h diff --git a/DataSources/UARTOutput/Makefile.inc b/DataSources/UARTOutput/Makefile.inc index 877aeb3..ed38077 100644 --- a/DataSources/UARTOutput/Makefile.inc +++ b/DataSources/UARTOutput/Makefile.inc @@ -22,7 +22,7 @@ # ############################################################# -OBJSX=UARTOutput.x +OBJSX=UARTOutput.x UART9Bit.x PACKAGE=Components/DataSources diff --git a/DataSources/UARTOutput/UART9Bit.cpp b/DataSources/UARTOutput/UART9Bit.cpp new file mode 100644 index 0000000..1169565 --- /dev/null +++ b/DataSources/UARTOutput/UART9Bit.cpp @@ -0,0 +1,375 @@ +/** + * @file UART9Bit.cpp + * @brief Source file for class UART9Bit. + * @date 07/08/2018 + * @author Andre Neto + * @author Pedro Lourenco + * + * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and + * the Development of Fusion Energy ('Fusion for Energy'). + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved + * by the European Commission - subsequent versions of the EUPL (the "Licence") + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl + * + * @warning Unless required by applicable law or agreed to in writing, + * software distributed under the Licence is distributed on an "AS IS" + * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence permissions and limitations under the Licence. + * + * @details This source file contains the definition of all the methods for + * the class UART9Bit (public, protected, and private). Be aware that some + * methods, such as those inline could be defined on the header file, instead. + */ + +/*---------------------------------------------------------------------------*/ +/* Standard header includes */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Project header includes */ +/*---------------------------------------------------------------------------*/ +#include "UART9Bit.h" + +/*---------------------------------------------------------------------------*/ +/* Static definitions */ +/*---------------------------------------------------------------------------*/ +/*lint -e628 []. Justification: Argument 'errno' of 'strerror()' provided + via .*/ +/*lint -e10 []. Justification: '}' present.*/ + +/*lint -e{9141} [MISRA C++ Rule 7-3-1]. Justification: 'SpeedTable' declared " + "as global.*/ +struct SpeedTable { + MARTe::int32 code; + MARTe::uint32 speed; +}; + +/*lint -e{9141} [MISRA C++ Rule 7-3-1]. Justification: 'speedTable' declared " + "as global.*/ +const SpeedTable speedTable[] = {{B0, 0u}, + {B50, 50u}, + {B75, 75u}, + {B110, 110u}, + {B134, 134u}, + {B150, 150u}, + {B200, 200u}, + {B300, 300u}, + {B600, 600u}, + {B1200, 1200u}, + {B1800, 1800u}, + {B2400, 2400u}, + {B4800, 4800u}, + {B9600, 9600u}, + {B19200, 19200u}, + {B38400, 38400u}, + {B57600, 57600u}, + {B115200, 115200u}, + {B230400, 230400u}, + {B460800, 460800u}, + {B500000, 500000u}, + {B576000, 576000u}, + {B921600, 921600u}, + {B1000000, 1000000u}, + {B1152000, 1152000u}, + {B1500000, 1500000u}, + {B2000000, 2000000u}, + {B2500000, 2500000u}, + {B3000000, 3000000u}, + {B3500000, 3500000u}, + {B4000000, 4000000u}}; + +/*---------------------------------------------------------------------------*/ +/* Method definitions */ +/*---------------------------------------------------------------------------*/ +namespace MARTe { + +/*lint -e{1401} [MISRA C++ Rule 8-5-1]. Justification: FD_ZERO arguments + correctly initialised.*/ +UART9Bit::UART9Bit() { + + properties.fileDescriptor = -1; + properties.speedCode = B19200; + FD_ZERO(&properties.readFDS); + FD_ZERO(&properties.readFDS_done); + FD_ZERO(&properties.writeFDS); + FD_ZERO(&properties.writeFDS_done); +} + +UART9Bit::~UART9Bit() { + /*lint -e{1551} []. Justification: thrown exception non critical.*/ + Close(); +} + +bool UART9Bit::SetSpeed(const uint32 speed) { + + bool ok = (properties.fileDescriptor == -1); + if (ok) { + int32 ix = 0; + while ((speedTable[ix].code != __MAX_BAUD) && + (speed > speedTable[ix].speed)) { + ix++; + } + properties.speedCode = speedTable[ix].code; + ok = (speed == speedTable[ix].speed); + } + + return ok; +} +/*lint -e{952} [MISRA C++ Rule 7-1-1]. Justification: Parameter 'name' + kept as non const.*/ +bool UART9Bit::Open(const char8 *name) { + + // Info from termios.h: + // c_iflag - input modes; + // c_oflag - output modes; + // c_cflag - control modes; + // c_lflag - local modes; + // c_cc[NCCS] - special characters. + + bool ok = (properties.fileDescriptor == -1); + if (ok) { + ok = (name != NULL); + } + if (ok) { + /*lint -e{9130} [MISRA C++ Rule 5-0-21]. Justification: Known bitwise + operation over signed type.*/ + properties.fileDescriptor = open(name, O_RDWR | O_NOCTTY | O_NONBLOCK); + if (properties.fileDescriptor == -1) { + REPORT_ERROR_STATIC(ErrorManagement::OSError, + "UART9Bit::Open - " + "cannot open serial device %s.", + name); + ok = false; + } + FD_SET(properties.fileDescriptor, &properties.readFDS); + FD_SET(properties.fileDescriptor, &properties.writeFDS); + } + if (ok) { + struct termios newtio; + // Clean all settings + cfmakeraw(&newtio); + // Eight Data bits + // CSIZE - Character size mask. Values are CS5, CS6, CS7, or CS8. + /*lint -e{9130} [MISRA C++ Rule 5-0-21]. Justification: Known bitwise + operations over signed types.*/ + /*lint -e{9117} [MISRA C++ Rule 5-0-4]. Justification: Known signedness + change due to implicit conversion.*/ + /*lint -e{737} []. Justification: Known loss of signedness.*/ + newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS8 | properties.speedCode; + // CLOCAL - Ignore modem control lines. + // CREAD - Enable receiver. + /*lint -e{9130} [MISRA C++ Rule 5-0-21]. Justification: Known bitwise + operations over signed types.*/ + /*lint -e{9117} [MISRA C++ Rule 5-0-4]. Justification: Known signedness + change due to implicit conversion.*/ + newtio.c_cflag |= (CLOCAL | CREAD); + // No parity: + // PARENB - Enable parity generation on output and parity checking for + // input. + // PARODD - If set, then parity for input and output is odd; otherwise + // even parity is used. + /*lint -e{9130} [MISRA C++ Rule 5-0-21]. Justification: Known bitwise + operations over signed types.*/ + /*lint -e{9117} [MISRA C++ Rule 5-0-4]. Justification: Known signedness + change due to implicit conversion.*/ + newtio.c_cflag &= ~(PARENB | PARODD); + // No hardware handshake: + // CRTSCTS - Enable RTS/CTS (hardware) flow control. + /*lint -e{9130} [MISRA C++ Rule 5-0-21]. Justification: Known bitwise + operations over signed types.*/ + /*lint -e{9105} [MISRA C++ Rule 2-13-3]. Justification: Known U suffix + missing.*/ + newtio.c_cflag &= ~CRTSCTS; + // One stopbit: + // CSTOPB - Set two stop bits, rather than one. + /*lint -e{9130} [MISRA C++ Rule 5-0-21]. Justification: Known bitwise + operations over signed types.*/ + /*lint -e{9117} [MISRA C++ Rule 5-0-4]. Justification: Known signedness + change due to implicit conversion.*/ + newtio.c_cflag &= ~CSTOPB; + // IGNBRK - Ignore BREAK condition on input. + // newtio.c_iflag = IGNBRK; + // Software handshake: + // IXON - Enable XON/XOFF flow control on output. + // IXANY - Typing any character will restart stopped output. + // IXOFF - Enable XON/XOFF flow control on input. + // newtio.c_iflag |= (IXON | IXOFF | IXANY); + /*lint -e{9130} [MISRA C++ Rule 5-0-21]. Justification: Known bitwise + operations over signed types.*/ + /*lint -e{9117} [MISRA C++ Rule 5-0-4]. Justification: Known signedness + change due to implicit conversion.*/ + newtio.c_iflag &= ~(IXON | IXOFF | IXANY); + // Non cannonical mode + // ICANON - Enable canonical mode. + // ECHO - Echo input characters. + // ECHOE - If ICANON is also set, the ERASE character erases the + // preceding input character, and WERASE erases the preceding word. + // ISIG - When any of the characters INTR, QUIT, SUSP, or DSUSP are + // received, generate the corresponding signal. + /*lint -e{9130} [MISRA C++ Rule 5-0-21]. Justification: Known bitwise + operations over signed types.*/ + /*lint -e{9117} [MISRA C++ Rule 5-0-4]. Justification: Known signedness + change due to implicit conversion.*/ + newtio.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); + newtio.c_lflag = 0u; + newtio.c_oflag = 0u; + // VMIN - Minimum number of characters for noncanonical read (MIN). + newtio.c_cc[VMIN] = 1u; + // VTIME - Timeout in deciseconds for noncanonical read (TIME). + newtio.c_cc[VTIME] = 5u; + + ok = (cfsetspeed(&newtio, static_cast(properties.speedCode)) == 0); + ErrorManagement::ErrorType errorCode = + ok ? ErrorManagement::Information : ErrorManagement::OSError; + REPORT_ERROR_STATIC(errorCode, + "UART9Bit::Open - %s serial device %s " + "speed to %u.", + ok ? "successfully set" : "could not set", name, + properties.speedCode); + + if (ok) { + ok = (tcsetattr(properties.fileDescriptor, TCSANOW, &newtio) != -1); + errorCode = ok ? ErrorManagement::Information : ErrorManagement::OSError; + REPORT_ERROR_STATIC(errorCode, + "UART9Bit::Open - %s serial device " + "parameters.", + ok ? "successfully set" : "could not set"); + } + } + + return ok; +} + +void UART9Bit::Close() { + + if (properties.fileDescriptor != -1) { + int32 err = close(properties.fileDescriptor); + bool ok = (err == 0); + ErrorManagement::ErrorType errorCode = + ok ? ErrorManagement::Information : ErrorManagement::OSError; + REPORT_ERROR_STATIC(errorCode, + "UART9Bit::Close - %s serial " + "interface.", + ok ? "closed" : "failed to close"); + properties.fileDescriptor = -1; + } +} + +/*lint -e{952} [MISRA C++ Rule 7-1-1]. Justification: Parameter 'buffer' kept + as non const.*/ +/*lint -e{1762} [MISRA C++ Rule 9-3-3]. Justification: Member function :Read() + kept as non const.*/ +bool UART9Bit::Read(char8 *buffer, uint32 &size) { + + size_t readSize = static_cast(size); + ssize_t readBytes = read(properties.fileDescriptor, buffer, readSize); + size = static_cast(readBytes); + bool ok = (readBytes == static_cast(size)); + + // ErrorManagement::ErrorType errorCode = ok ? + // ErrorManagement::Information : + // ErrorManagement::OSError; + // REPORT_ERROR_STATIC(errorCode, "UART9Bit::Read - read %d bytes, " + // "requested %u.", static_cast(readBytes), + // static_cast(readSize)); + + return ok; +} + +/*lint -e{952} [MISRA C++ Rule 7-1-1]. Justification: Parameter 'buffer' kept + as non const.*/ +bool UART9Bit::Read(char8 *buffer, uint32 &size, const uint32 timeoutUsec) { + + bool ok = true; + size_t leftToRead = static_cast(size); + void *rbuffer = &buffer[0u]; + while ((leftToRead > 0u) && (ok)) { + ok = WaitRead(timeoutUsec); + if (ok) { + ssize_t readBytes = read(properties.fileDescriptor, rbuffer, leftToRead); + ok = (readBytes > 0); + if (ok) { + leftToRead -= static_cast(readBytes); + uint32 idx = size - static_cast(leftToRead); + rbuffer = &buffer[idx]; + } + ErrorManagement::ErrorType errorCode = + ok ? ErrorManagement::Information : ErrorManagement::OSError; + StreamString errorMessage; + /*lint -e{1055} [MISRA C++ Rule 14-8-2]. Justification: Symbol + 'strerror' declared.*/ + /*lint -e{746} []. Justification: Prototype not present in + MARTe::strerror().*/ + (void)errorMessage.Printf(" with error %s.", strerror(errno)); + // Error only verbosity, comment condition if needed. + if (!ok) { + /*lint -e{578} [MISRA C++ Rule 2-10-2]. Justification: Symbol + 'Buffer' has an identical name as a global + symbol 'buffer'.*/ + REPORT_ERROR_STATIC(errorCode, + "UART9Bit::Read - %s read %d " + "bytes%s", + ok ? "" : "failed to", + static_cast(readBytes), + ok ? "." : errorMessage.Buffer()); + } + } + } + size = (size - static_cast(leftToRead)); + + return ok; +} + +/*lint -e{952} [MISRA C++ Rule 7-1-1]. Justification: Parameter 'size' kept as + non const.*/ +/*lint -e{1762} [MISRA C++ Rule 9-3-3]. Justification: Member function :Read() + kept as non const.*/ +/*lint -e{818} [MISRA C++ Rule 7-1-1]. Justification: Parameter 'size' kept as + non const.*/ +bool UART9Bit::Write(char8 *buffer, uint32 size) { + + size_t writeSize = static_cast(size); + ssize_t writtenBytes = write(properties.fileDescriptor, buffer, writeSize); + bool ok = (writtenBytes == static_cast(writeSize)); + + // ErrorManagement::ErrorType errorCode = ok ? + // ErrorManagement::Information : + // ErrorManagement::OSError; + // REPORT_ERROR_STATIC(errorCode, "UART9Bit::Write - wrote %d bytes, " + // "requested %u.", static_cast(writtenBytes), size); + + return ok; +} + +bool UART9Bit::WaitRead(const uint32 timeoutUsec) { + + struct timeval timeWait; + uint32 tmp = timeoutUsec / 1000000u; + timeWait.tv_sec = static_cast(tmp); + tmp = timeoutUsec % 1000000u; + timeWait.tv_usec = static_cast(tmp); + properties.readFDS_done = properties.readFDS; + int32 readyCount = + select(properties.fileDescriptor + 1, &properties.readFDS_done, + NULL_PTR(fd_set *), NULL_PTR(fd_set *), &timeWait); + + return (readyCount > 0); +} + +bool UART9Bit::WaitWrite(const uint32 timeoutUsec) { + + struct timeval timeWait; + uint32 tmp = timeoutUsec / 1000000u; + timeWait.tv_sec = static_cast(tmp); + tmp = timeoutUsec % 1000000u; + timeWait.tv_usec = static_cast(tmp); + properties.writeFDS_done = properties.writeFDS; + int32 readyCount = + select(properties.fileDescriptor + 1, NULL_PTR(fd_set *), + &properties.writeFDS_done, NULL_PTR(fd_set *), &timeWait); + + return (readyCount > 0); +} + +} // namespace MARTe diff --git a/DataSources/UARTOutput/UART9Bit.h b/DataSources/UARTOutput/UART9Bit.h new file mode 100644 index 0000000..8817178 --- /dev/null +++ b/DataSources/UARTOutput/UART9Bit.h @@ -0,0 +1,164 @@ +/** + * @file UART9Bit.h + * @brief Header file for class UART9Bit. + * @date 16/08/2021 + * @author Filippo Sartori + * @author Pedro Lourenco + * + * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and + * the Development of Fusion Energy ('Fusion for Energy'). + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved + * by the European Commission - subsequent versions of the EUPL (the "Licence") + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl + * + * @warning Unless required by applicable law or agreed to in writing, + * software distributed under the Licence is distributed on an "AS IS" + * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence permissions and limitations under the Licence. + * + * @details This header file contains the declaration of the class UART9Bit + * with all of its public, protected and private members. It may also include + * definitions for inline methods which need to be visible to the compiler. + */ + +#ifndef UART9BIT_H_ +#define UART9BIT_H_ + +/*---------------------------------------------------------------------------*/ +/* Standard header includes */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Project header includes */ +/*---------------------------------------------------------------------------*/ +#include "AdvancedErrorManagement.h" +#include "CompilerTypes.h" +#include "GeneralDefinitions.h" +#include "StreamString.h" +#include INCLUDE_FILE_ENVIRONMENT(FileSystem, L1Portability, ENVIRONMENT, BasicUARTProperties.h) + +/*---------------------------------------------------------------------------*/ +/* Class declaration */ +/*---------------------------------------------------------------------------*/ + +namespace MARTe { + +/** + * @brief UART implementation based on the Linux general terminal interface + * that is provided to control asynchronous communications ports. + * @details Some of termio parameters are hard-coded as follows: + * - eight data bits; + * - no parity bit; + * - one stop bit; + * - noncanonical input processing mode. + */ +class DLL_API UART9Bit { +public: + /** + * @brief Default constructor. + * @details FD_ZERO the file descriptors. + */ + UART9Bit(); + + /** + * @brief Destructor. + * @details Calls Close(). + */ + virtual ~UART9Bit(); + + /** + * @brief Sets the speed of the UART. Shall be called before the Open + * method. + * @param[in] serial the speed to set. + * @return true if the speed was successfully updated. + */ + bool SetSpeed(const uint32 speed); + + /** + * @brief Opens the UART described by the provided \a name. + * @details The UART is open in read/write mode. Many of the UART + * properties are hard-coded for the CRIO use-case. + * @param[in] name the UART file descriptor location. + * @pre + * SetSpeed + */ + bool Open(const char8 *name); + + /** + * @brief Closes the UART. + * @pre + * Open + */ + void Close(); + + /** + * @brief Reads \a size bytes into the \a buffer. + * @param[in] buffer the memory where to write the read bytes. + * @param[in,out] size the number of bytes to read and the number of bytes + * that were actually read. + * @return true if the Read operation completes successfully (and reads all + * the requested bytes). + * @pre + * Open + */ + bool Read(char8 *buffer, uint32 &size); + + /** + * @brief Reads \a size bytes into the \a buffer within \a timeoutUsec + * micro-seconds. + * @param[in] buffer the memory where to write the read bytes. + * @param[in,out] size the number of bytes to read and the number of bytes + * that were actually read. + * @param[in] timeoutUsec the maximum time to complete the read operation. + * @return true if the Read operation completes successfully within the + * timeout (and reads all the requested bytes). + * @pre + * Open + */ + bool Read(char8 *buffer, uint32 &size, const uint32 timeoutUsec); + + /** + * @brief Waits \a timeoutUsec micro-seconds for data to be available for + * reading in the UART. + * @param[in] timeoutUsec the maximum time to wait for data to be + * available. + * @return true if data is available to be read within the timeout. + */ + bool WaitRead(const uint32 timeoutUsec); + + /** + * @brief Writes \a size bytes from the \a buffer. + * @param[in] buffer the memory where to read the bytes to write. + * @param[in] size the number of bytes to write. + * @param[in] timeoutUsec the maximum time to complete the read operation. + * @return true if the Read operation completes successfully within the + * timeout (and reads all the requested bytes). + * @pre + * Open + */ + bool Write(char8 *buffer, uint32 size); + + /** + * @brief Waits \a timeoutUsec micro-seconds for the UART to be available + * for writing data. + * @param[in] timeoutUsec the maximum time to wait for the write to be + * available. + * @return true if the UART is available to write within the timeout. + */ + bool WaitWrite(const uint32 timeoutUsec); + +private: + /** + * Structure with variables/parameters for different Environments. + */ + BasicUARTProperties properties; +}; + +} // namespace MARTe + +/*---------------------------------------------------------------------------*/ +/* Inline method definitions */ +/*---------------------------------------------------------------------------*/ + +#endif /* UART9BIT_H_ */ diff --git a/DataSources/UARTOutput/UARTOutput.h b/DataSources/UARTOutput/UARTOutput.h index 008322a..5993fc0 100644 --- a/DataSources/UARTOutput/UARTOutput.h +++ b/DataSources/UARTOutput/UARTOutput.h @@ -35,7 +35,6 @@ /*---------------------------------------------------------------------------*/ /* Project header includes */ /*---------------------------------------------------------------------------*/ -#include "BasicUART.h" #include "DataSourceI.h" #include "EmbeddedServiceMethodBinderI.h" #include "EventSem.h" @@ -43,6 +42,7 @@ #include "RegisteredMethodsMessageFilter.h" #include "SingleThreadService.h" +#include "UART9Bit.h" /*---------------------------------------------------------------------------*/ /* Class declaration */ /*---------------------------------------------------------------------------*/ @@ -211,7 +211,7 @@ private: /** * The UART interface. */ - BasicUART serial; + UART9Bit serial; /** * Timeout to wait for data to be available.