UART ComIF update #11
@ -1,6 +1,7 @@
|
|||||||
#include "UartComIF.h"
|
#include "UartComIF.h"
|
||||||
|
#include "OBSWConfig.h"
|
||||||
|
|
||||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -56,7 +57,7 @@ ReturnValue_t UartComIF::initializeInterface(CookieIF * cookie) {
|
|||||||
|
|
||||||
int UartComIF::configureUartPort(UartCookie* uartCookie) {
|
int UartComIF::configureUartPort(UartCookie* uartCookie) {
|
||||||
|
|
||||||
struct termios options;
|
struct termios options = {};
|
||||||
|
|
||||||
std::string deviceFile = uartCookie->getDeviceFile();
|
std::string deviceFile = uartCookie->getDeviceFile();
|
||||||
int fd = open(deviceFile.c_str(), O_RDWR);
|
int fd = open(deviceFile.c_str(), O_RDWR);
|
||||||
@ -78,6 +79,9 @@ int UartComIF::configureUartPort(UartCookie* uartCookie) {
|
|||||||
setStopBitOptions(&options, uartCookie);
|
setStopBitOptions(&options, uartCookie);
|
||||||
setDatasizeOptions(&options, uartCookie);
|
setDatasizeOptions(&options, uartCookie);
|
||||||
setFixedOptions(&options);
|
setFixedOptions(&options);
|
||||||
|
if(uartCookie->getInputShouldBeFlushed()) {
|
||||||
|
tcflush(fd, TCIFLUSH);
|
||||||
|
}
|
||||||
|
|
||||||
/* Sets uart to non-blocking mode. Read returns immediately when there are no data available */
|
/* Sets uart to non-blocking mode. Read returns immediately when there are no data available */
|
||||||
options.c_cc[VTIME] = 0;
|
options.c_cc[VTIME] = 0;
|
||||||
@ -325,10 +329,53 @@ ReturnValue_t UartComIF::requestReceiveMessage(CookieIF *cookie, size_t requestL
|
|||||||
fd = uartDeviceMapIter->second.fileDescriptor;
|
fd = uartDeviceMapIter->second.fileDescriptor;
|
||||||
bufferPtr = uartDeviceMapIter->second.replyBuffer.data();
|
bufferPtr = uartDeviceMapIter->second.replyBuffer.data();
|
||||||
if (uartMode == UartModes::CANONICAL) {
|
if (uartMode == UartModes::CANONICAL) {
|
||||||
int bytesRead = read(fd, bufferPtr, uartCookie->getMaxReplyLen());
|
uint8_t maxReadCycles = uartCookie->getReadCycles();
|
||||||
uartDeviceMapIter->second.replyLen = bytesRead;
|
uint8_t currentReadCycles = 0;
|
||||||
|
int bytesRead = 0;
|
||||||
|
size_t currentBytesRead = 0;
|
||||||
|
size_t maxReplySize = uartCookie->getMaxReplyLen();
|
||||||
|
do {
|
||||||
|
size_t allowedReadSize = 0;
|
||||||
|
if(currentBytesRead >= maxReplySize) {
|
||||||
|
// Overflow risk. Emit warning, trigger event and break. If this happens,
|
||||||
|
// the reception buffer is not large enough or data is not polled often enough.
|
||||||
|
// TODO: Emit event
|
||||||
|
// TODO: Return error?
|
||||||
|
#if OBSW_VERBOSE_LEVEL >= 1
|
||||||
|
sif::warning << "UartComIF::requestReceiveMessage: Next read would cause overflow!"
|
||||||
|
<< std::endl;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
allowedReadSize = maxReplySize - currentBytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesRead = read(fd, bufferPtr, allowedReadSize);
|
||||||
|
if (bytesRead < 0) {
|
||||||
|
return RETURN_FAILED;
|
||||||
|
}
|
||||||
|
else if (bytesRead != static_cast<int>(requestLen)) {
|
||||||
|
sif::debug << "UartComIF::requestReceiveMessage: Only read " << bytesRead <<
|
||||||
|
" of " << requestLen << " bytes" << std::endl;
|
||||||
|
return RETURN_FAILED;
|
||||||
|
}
|
||||||
|
else if(bytesRead > 0) {
|
||||||
|
uartDeviceMapIter->second.replyLen += bytesRead;
|
||||||
|
bufferPtr += bytesRead;
|
||||||
|
currentBytesRead += bytesRead;
|
||||||
|
}
|
||||||
|
currentReadCycles++;
|
||||||
|
} while(bytesRead > 0 and currentReadCycles < maxReadCycles);
|
||||||
}
|
}
|
||||||
else if (uartMode == UartModes::NON_CANONICAL) {
|
else if (uartMode == UartModes::NON_CANONICAL) {
|
||||||
|
// Size check to prevent buffer overflow
|
||||||
|
if(requestLen > uartCookie->getMaxReplyLen()) {
|
||||||
|
// TODO: Emit warning
|
||||||
|
// TODO: Emit event
|
||||||
|
// TODO: Better returnvalue
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
int bytesRead = read(fd, bufferPtr, requestLen);
|
int bytesRead = read(fd, bufferPtr, requestLen);
|
||||||
if (bytesRead < 0) {
|
if (bytesRead < 0) {
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
|
@ -98,6 +98,7 @@ private:
|
|||||||
void configureBaudrate(struct termios* options, UartCookie* uartCookie);
|
void configureBaudrate(struct termios* options, UartCookie* uartCookie);
|
||||||
|
|
||||||
void setUartMode(struct termios* options, UartCookie& uartCookie);
|
void setUartMode(struct termios* options, UartCookie& uartCookie);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* BSP_Q7S_COMIF_UARTCOMIF_H_ */
|
#endif /* BSP_Q7S_COMIF_UARTCOMIF_H_ */
|
||||||
|
@ -66,3 +66,19 @@ void UartCookie::setOneStopBit() {
|
|||||||
UartModes UartCookie::getUartMode() const {
|
UartModes UartCookie::getUartMode() const {
|
||||||
return uartMode;
|
return uartMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UartCookie::setReadCycles(uint8_t readCycles) {
|
||||||
|
this->readCycles = readCycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UartCookie::setToFlushInput(bool enable) {
|
||||||
|
this->flushInput = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t UartCookie::getReadCycles() const {
|
||||||
|
return readCycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UartCookie::getInputShouldBeFlushed() {
|
||||||
|
return this->flushInput;
|
||||||
|
}
|
||||||
|
@ -56,6 +56,22 @@ public:
|
|||||||
uint8_t getBitsPerWord() const;
|
uint8_t getBitsPerWord() const;
|
||||||
StopBits getStopBits() const;
|
StopBits getStopBits() const;
|
||||||
UartModes getUartMode() const;
|
UartModes getUartMode() const;
|
||||||
|
/**
|
||||||
|
* The UART ComIF will only perform a specified number of read cycles for the canonical mode.
|
||||||
|
* The user can specify how many of those read cycles are performed for one device handler
|
||||||
|
* communication cycle. An example use-case would be to read all available GPS NMEA strings
|
||||||
|
* at once.
|
||||||
|
* @param readCycles
|
||||||
|
*/
|
||||||
|
void setReadCycles(uint8_t readCycles);
|
||||||
|
uint8_t getReadCycles() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to flush the data which was received but has not been read yet. This is useful
|
||||||
|
* to discard obsolete data at software startup.
|
||||||
|
*/
|
||||||
|
void setToFlushInput(bool enable);
|
||||||
|
bool getInputShouldBeFlushed();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functions two enable parity checking.
|
* Functions two enable parity checking.
|
||||||
@ -78,10 +94,12 @@ private:
|
|||||||
|
|
||||||
std::string deviceFile;
|
std::string deviceFile;
|
||||||
const UartModes uartMode;
|
const UartModes uartMode;
|
||||||
|
bool flushInput = false;
|
||||||
uint32_t baudrate;
|
uint32_t baudrate;
|
||||||
size_t maxReplyLen = 0;
|
size_t maxReplyLen = 0;
|
||||||
Parity parity = Parity::NONE;
|
Parity parity = Parity::NONE;
|
||||||
uint8_t bitsPerWord = 8;
|
uint8_t bitsPerWord = 8;
|
||||||
|
uint8_t readCycles = 1;
|
||||||
StopBits stopBits = StopBits::ONE_STOP_BIT;
|
StopBits stopBits = StopBits::ONE_STOP_BIT;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user