From 09299802f0cc4456c510f6d6dac3260b96c08777 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 28 Sep 2021 15:01:01 +0200 Subject: [PATCH 01/49] TCP refactoring This refactoring keeps the TCP connection opened until the client closes it. It also increased the robustness of the TCP reception. Because TCP is stream based and usually applied to newline separated data, a special way to handle binary space packets is required. The new SpacePacketParser class takes care of this by taking TC packet IDs as as optional start markers to parse for space packets in a given buffer. The refactored TCP server uses a ring buffer, a reception buffer and the new parser to extract space packets from a stream in a safer way. --- src/fsfw/osal/common/TcpTmTcServer.cpp | 229 ++++++++++++++++---- src/fsfw/osal/common/TcpTmTcServer.h | 68 ++++-- src/fsfw/tmtcpacket/SpacePacket.h | 109 +++++----- src/fsfw/tmtcservices/SpacePacketParser.cpp | 77 +++++++ src/fsfw/tmtcservices/SpacePacketParser.h | 96 ++++++++ 5 files changed, 473 insertions(+), 106 deletions(-) create mode 100644 src/fsfw/tmtcservices/SpacePacketParser.cpp create mode 100644 src/fsfw/tmtcservices/SpacePacketParser.h diff --git a/src/fsfw/osal/common/TcpTmTcServer.cpp b/src/fsfw/osal/common/TcpTmTcServer.cpp index 11ab71af..e320b46b 100644 --- a/src/fsfw/osal/common/TcpTmTcServer.cpp +++ b/src/fsfw/osal/common/TcpTmTcServer.cpp @@ -1,8 +1,11 @@ -#include "fsfw/osal/common/TcpTmTcServer.h" -#include "fsfw/osal/common/TcpTmTcBridge.h" -#include "fsfw/osal/common/tcpipHelpers.h" - #include "fsfw/platform.h" +#include "fsfw/FSFW.h" + +#include "TcpTmTcServer.h" +#include "TcpTmTcBridge.h" +#include "tcpipHelpers.h" + +#include "fsfw/tasks/TaskFactory.h" #include "fsfw/container/SharedRingBuffer.h" #include "fsfw/ipc/MessageQueueSenderIF.h" #include "fsfw/ipc/MutexGuard.h" @@ -17,6 +20,7 @@ #elif defined(PLATFORM_UNIX) #include #endif +#include #ifndef FSFW_TCP_RECV_WIRETAPPING_ENABLED #define FSFW_TCP_RECV_WIRETAPPING_ENABLED 0 @@ -25,12 +29,11 @@ const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT; TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge, - size_t receptionBufferSize, std::string customTcpServerPort): - SystemObject(objectId), tmtcBridgeId(tmtcTcpBridge), - tcpPort(customTcpServerPort), receptionBuffer(receptionBufferSize) { - if(tcpPort == "") { - tcpPort = DEFAULT_SERVER_PORT; - } + size_t receptionBufferSize, size_t ringBufferSize, std::string customTcpServerPort, + ReceptionModes receptionMode): + SystemObject(objectId), tmtcBridgeId(tmtcTcpBridge), receptionMode(receptionMode), + tcpConfig(customTcpServerPort), receptionBuffer(receptionBufferSize), + ringBuffer(ringBufferSize, true), validPacketIds() { } ReturnValue_t TcpTmTcServer::initialize() { @@ -41,6 +44,16 @@ ReturnValue_t TcpTmTcServer::initialize() { return result; } + switch(receptionMode) { + case(ReceptionModes::SPACE_PACKETS): { + spacePacketParser = new SpacePacketParser(validPacketIds); + if(spacePacketParser == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + tcpConfig.tcpFlags |= MSG_DONTWAIT; + } + } + tcStore = ObjectManager::instance()->get(objects::TC_STORE); if (tcStore == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 @@ -63,7 +76,7 @@ ReturnValue_t TcpTmTcServer::initialize() { hints.ai_flags = AI_PASSIVE; // Listen to all addresses (0.0.0.0) by using AI_PASSIVE in the hint flags - retval = getaddrinfo(nullptr, tcpPort.c_str(), &hints, &addrResult); + retval = getaddrinfo(nullptr, tcpConfig.tcpPort.c_str(), &hints, &addrResult); if (retval != 0) { handleError(Protocol::TCP, ErrorSources::GETADDRINFO_CALL); return HasReturnvaluesIF::RETURN_FAILED; @@ -105,7 +118,7 @@ ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) { // Listen for connection requests permanently for lifetime of program while(true) { - retval = listen(listenerTcpSocket, tcpBacklog); + retval = listen(listenerTcpSocket, tcpConfig.tcpBacklog); if(retval == SOCKET_ERROR) { handleError(Protocol::TCP, ErrorSources::LISTEN_CALL, 500); continue; @@ -123,11 +136,12 @@ ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) { handleServerOperation(connSocket); // Done, shut down connection and go back to listening for client requests - retval = shutdown(connSocket, SHUT_SEND); + retval = shutdown(connSocket, SHUT_BOTH); if(retval != 0) { handleError(Protocol::TCP, ErrorSources::SHUTDOWN_CALL); } closeSocket(connSocket); + connSocket = 0; } return HasReturnvaluesIF::RETURN_OK; } @@ -144,51 +158,82 @@ ReturnValue_t TcpTmTcServer::initializeAfterTaskCreation() { return HasReturnvaluesIF::RETURN_OK; } -void TcpTmTcServer::handleServerOperation(socket_t connSocket) { - int retval = 0; - do { - // Read all telecommands sent by the client - retval = recv(connSocket, +void TcpTmTcServer::handleServerOperation(socket_t& connSocket) { + while (true) { + int retval = recv( + connSocket, reinterpret_cast(receptionBuffer.data()), receptionBuffer.capacity(), - tcpFlags); - if (retval > 0) { - handleTcReception(retval); + tcpConfig.tcpFlags + ); + if(retval == 0) { + // Client closed connection + return; } - else if(retval == 0) { - // Client has finished sending telecommands, send telemetry now - handleTmSending(connSocket); + else if(retval > 0) { + // The ring buffer was configured for overwrite, so the returnvalue does not need to + // be checked for now + ringBuffer.writeData(receptionBuffer.data(), retval); } - else { - // Should not happen - tcpip::handleError(tcpip::Protocol::TCP, tcpip::ErrorSources::RECV_CALL); + else if(retval < 0) { + if(errno == EAGAIN) { + // No data available. Check whether any packets have been read, then send back + // telemetry if available + bool tcAvailable = false; + bool tmSent = false; + size_t availableReadData = ringBuffer.getAvailableReadData(); + if(availableReadData > lastRingBufferSize) { + tcAvailable = true; + handleTcRingBufferData(availableReadData); + } + ReturnValue_t result = handleTmSending(connSocket, tmSent); + if(result == CONN_BROKEN) { + return; + } + if(not tcAvailable and not tmSent) { + TaskFactory::delayTask(DEFAULT_LOOP_DELAY_MS); + } + } + else { + tcpip::handleError(tcpip::Protocol::TCP, tcpip::ErrorSources::RECV_CALL); + } } - } while(retval > 0); + } } -ReturnValue_t TcpTmTcServer::handleTcReception(size_t bytesRecvd) { +ReturnValue_t TcpTmTcServer::handleTcReception(uint8_t* spacePacket, size_t packetSize) { #if FSFW_TCP_RECV_WIRETAPPING_ENABLED == 1 arrayprinter::print(receptionBuffer.data(), bytesRead); #endif + if(spacePacket == nullptr or packetSize == 0) { + return HasReturnvaluesIF::RETURN_FAILED; + } store_address_t storeId; - ReturnValue_t result = tcStore->addData(&storeId, receptionBuffer.data(), bytesRecvd); + ReturnValue_t result = tcStore->addData(&storeId, spacePacket, packetSize); if (result != HasReturnvaluesIF::RETURN_OK) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning<< "TcpTmTcServer::handleServerOperation: Data storage failed." << std::endl; - sif::warning << "Packet size: " << bytesRecvd << std::endl; + sif::warning << "TcpTmTcServer::handleServerOperation: Data storage with packet size" << + packetSize << " failed" << std::endl; +#else + sif::printWarning("TcpTmTcServer::handleServerOperation: Data storage with packet size %d " + "failed\n", packetSize); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */ + return result; } TmTcMessage message(storeId); - result = MessageQueueSenderIF::sendMessage(targetTcDestination, &message); + result = MessageQueueSenderIF::sendMessage(targetTcDestination, &message); if (result != HasReturnvaluesIF::RETURN_OK) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "UdpTcPollingTask::handleSuccessfullTcRead: " + sif::warning << "TcpTmTcServer::handleServerOperation: " " Sending message to queue failed" << std::endl; +#else + sif::printWarning("TcpTmTcServer::handleServerOperation: " + " Sending message to queue failed\n"); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */ tcStore->deleteData(storeId); @@ -196,21 +241,26 @@ ReturnValue_t TcpTmTcServer::handleTcReception(size_t bytesRecvd) { return result; } -void TcpTmTcServer::setTcpBacklog(uint8_t tcpBacklog) { - this->tcpBacklog = tcpBacklog; -} - std::string TcpTmTcServer::getTcpPort() const { - return tcpPort; + return tcpConfig.tcpPort; } -ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket) { +void TcpTmTcServer::setSpacePacketParsingOptions(std::vector validPacketIds) { + this->validPacketIds = validPacketIds; +} + +TcpTmTcServer::TcpConfig& TcpTmTcServer::getTcpConfigStruct() { + return tcpConfig; +} + +ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent) { // Access to the FIFO is mutex protected because it is filled by the bridge MutexGuard(tmtcBridge->mutex, tmtcBridge->timeoutType, tmtcBridge->mutexTimeoutMs); store_address_t storeId; while((not tmtcBridge->tmFifo->empty()) and (tmtcBridge->packetSentCounter < tmtcBridge->sentPacketsPerCycle)) { - tmtcBridge->tmFifo->retrieve(&storeId); + // Send can fail, so only peek from the FIFO + tmtcBridge->tmFifo->peek(&storeId); // Using the store accessor will take care of deleting TM from the store automatically ConstStorageAccessor storeAccessor(storeId); @@ -221,10 +271,101 @@ ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket) { int retval = send(connSocket, reinterpret_cast(storeAccessor.data()), storeAccessor.size(), - tcpTmFlags); - if(retval != static_cast(storeAccessor.size())) { - tcpip::handleError(tcpip::Protocol::TCP, tcpip::ErrorSources::SEND_CALL); + tcpConfig.tcpTmFlags); + if(retval == static_cast(storeAccessor.size())) { + // Packet sent, clear FIFO entry + tmtcBridge->tmFifo->pop(); + tmSent = true; + + } + else if(retval <= 0) { + // Assume that the client has closed the connection here for now + handleSocketError(storeAccessor); + return CONN_BROKEN; } } return HasReturnvaluesIF::RETURN_OK; } + +ReturnValue_t TcpTmTcServer::handleTcRingBufferData(size_t availableReadData) { + ReturnValue_t status = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + size_t readAmount = availableReadData; + lastRingBufferSize = availableReadData; + if(readAmount >= ringBuffer.getMaxSize()) { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + // Possible configuration error, too much data or/and data coming in too fast, + // requiring larger buffers + sif::warning << "TcpTmTcServer::handleServerOperation: Ring buffer reached " << + "fill count" << std::endl; +#else + sif::printWarning("TcpTmTcServer::handleServerOperation: Ring buffer reached " + "fill count"); +#endif +#endif + } + if(readAmount >= receptionBuffer.size()) { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + // Possible configuration error, too much data or/and data coming in too fast, + // requiring larger buffers + sif::warning << "TcpTmTcServer::handleServerOperation: " + "Reception buffer too small " << std::endl; +#else + sif::printWarning("TcpTmTcServer::handleServerOperation: Reception buffer too small\n"); +#endif +#endif + readAmount = receptionBuffer.size(); + } + ringBuffer.readData(receptionBuffer.data(), readAmount, true); + const uint8_t* bufPtr = receptionBuffer.data(); + const uint8_t** bufPtrPtr = &bufPtr; + size_t startIdx = 0; + size_t foundSize = 0; + size_t readLen = 0; + while(readLen < readAmount) { + result = spacePacketParser->parseSpacePackets(bufPtrPtr, readAmount, + startIdx, foundSize, readLen); + switch(result) { + case(SpacePacketParser::NO_PACKET_FOUND): + case(SpacePacketParser::SPLIT_PACKET): { + break; + } + case(HasReturnvaluesIF::RETURN_OK): { + result = handleTcReception(receptionBuffer.data() + startIdx, foundSize); + if(result != HasReturnvaluesIF::RETURN_OK) { + status = result; + } + } + } + ringBuffer.deleteData(foundSize); + lastRingBufferSize = ringBuffer.getAvailableReadData(); + std::memset(receptionBuffer.data() + startIdx, 0, foundSize); + } + return status; +} + +void TcpTmTcServer::handleSocketError(ConstStorageAccessor &accessor) { + // Don't delete data + accessor.release(); + auto socketError = getLastSocketError(); + switch(socketError) { +#if defined PLATFORM_WIN + case(WSAECONNRESET): { + // See https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-send + // Remote client might have shut down connection + return; + } +#else + case(EPIPE): { + // See https://man7.org/linux/man-pages/man2/send.2.html + // Remote client might have shut down connection + return; + } +#endif + default: { + tcpip::handleError(tcpip::Protocol::TCP, tcpip::ErrorSources::SEND_CALL); + } + } +} diff --git a/src/fsfw/osal/common/TcpTmTcServer.h b/src/fsfw/osal/common/TcpTmTcServer.h index c6916080..a0a31655 100644 --- a/src/fsfw/osal/common/TcpTmTcServer.h +++ b/src/fsfw/osal/common/TcpTmTcServer.h @@ -1,11 +1,13 @@ #ifndef FSFW_OSAL_COMMON_TCP_TMTC_SERVER_H_ #define FSFW_OSAL_COMMON_TCP_TMTC_SERVER_H_ +#include #include "TcpIpBase.h" #include "fsfw/platform.h" #include "fsfw/osal/common/tcpipHelpers.h" #include "fsfw/ipc/messageQueueDefinitions.h" +#include "fsfw/container/SimpleRingBuffer.h" #include "fsfw/ipc/MessageQueueIF.h" #include "fsfw/objectmanager/frameworkObjects.h" #include "fsfw/objectmanager/SystemObject.h" @@ -42,9 +44,37 @@ class TcpTmTcServer: public TcpIpBase, public ExecutableObjectIF { public: + enum class ReceptionModes { + SPACE_PACKETS + }; + + struct TcpConfig { + public: + TcpConfig(std::string tcpPort): tcpPort(tcpPort) {} + + /** + * Passed to the recv call + */ + int tcpFlags = 0; + int tcpBacklog = 3; + + /** + * Passed to the select call which is used to ensure non-blocking TC reception + */ + //uint32_t selectTimeoutMs = DEFAULT_SELECT_TIMEOUT_MS; + /** + * Passed to the send call + */ + int tcpTmFlags = 0; + + const std::string tcpPort; + }; + static const std::string DEFAULT_SERVER_PORT; static constexpr size_t ETHERNET_MTU_SIZE = 1500; + static constexpr size_t RING_BUFFER_SIZE = ETHERNET_MTU_SIZE * 3; + static constexpr uint32_t DEFAULT_LOOP_DELAY_MS = 200; /** * TCP Server Constructor @@ -55,11 +85,19 @@ public: * @param customTcpServerPort The user can specify another port than the default (7301) here. */ TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge, - size_t receptionBufferSize = ETHERNET_MTU_SIZE + 1, - std::string customTcpServerPort = ""); + size_t receptionBufferSize = RING_BUFFER_SIZE, + size_t ringBufferSize = RING_BUFFER_SIZE, + std::string customTcpServerPort = DEFAULT_SERVER_PORT, + ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS); virtual~ TcpTmTcServer(); - void setTcpBacklog(uint8_t tcpBacklog); + /** + * Get a handle to the TCP configuration struct, which can be used to configure TCP + * properties + * @return + */ + TcpConfig& getTcpConfigStruct(); + void setSpacePacketParsingOptions(std::vector validPacketIds); ReturnValue_t initialize() override; ReturnValue_t performOperation(uint8_t opCode) override; @@ -71,25 +109,29 @@ protected: StorageManagerIF* tcStore = nullptr; StorageManagerIF* tmStore = nullptr; private: + static constexpr ReturnValue_t CONN_BROKEN = HasReturnvaluesIF::makeReturnCode(1, 0); //! TMTC bridge is cached. object_id_t tmtcBridgeId = objects::NO_OBJECT; TcpTmTcBridge* tmtcBridge = nullptr; - std::string tcpPort; - int tcpFlags = 0; - socket_t listenerTcpSocket = 0; + ReceptionModes receptionMode; + TcpConfig tcpConfig; struct sockaddr tcpAddress; + socket_t listenerTcpSocket = 0; + MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE; - int tcpAddrLen = sizeof(tcpAddress); - int tcpBacklog = 3; std::vector receptionBuffer; - int tcpSockOpt = 0; - int tcpTmFlags = 0; + SimpleRingBuffer ringBuffer; + std::vector validPacketIds; + SpacePacketParser* spacePacketParser = nullptr; + uint8_t lastRingBufferSize = 0; - void handleServerOperation(socket_t connSocket); - ReturnValue_t handleTcReception(size_t bytesRecvd); - ReturnValue_t handleTmSending(socket_t connSocket); + virtual void handleServerOperation(socket_t& connSocket); + ReturnValue_t handleTcReception(uint8_t* spacePacket, size_t packetSize); + ReturnValue_t handleTmSending(socket_t connSocket, bool& tmSent); + ReturnValue_t handleTcRingBufferData(size_t availableReadData); + void handleSocketError(ConstStorageAccessor& accessor); }; #endif /* FSFW_OSAL_COMMON_TCP_TMTC_SERVER_H_ */ diff --git a/src/fsfw/tmtcpacket/SpacePacket.h b/src/fsfw/tmtcpacket/SpacePacket.h index 49dd5ae5..9eec87a8 100644 --- a/src/fsfw/tmtcpacket/SpacePacket.h +++ b/src/fsfw/tmtcpacket/SpacePacket.h @@ -15,56 +15,67 @@ */ class SpacePacket: public SpacePacketBase { public: - static const uint16_t PACKET_MAX_SIZE = 1024; - /** - * The constructor initializes the packet and sets all header information - * according to the passed parameters. - * @param packetDataLength Sets the packet data length field and therefore specifies the size of the packet. - * @param isTelecommand Sets the packet type field to either TC (true) or TM (false). - * @param apid Sets the packet's APID field. The default value describes an idle packet. - * @param sequenceCount ets the packet's Source Sequence Count field. - */ - SpacePacket(uint16_t packetDataLength, bool isTelecommand = false, - uint16_t apid = APID_IDLE_PACKET, uint16_t sequenceCount = 0); - /** - * The class's default destructor. - */ - virtual ~SpacePacket(); - /** - * With this call, the complete data content (including the CCSDS Primary - * Header) is overwritten with the byte stream given. - * @param p_data Pointer to data to overwrite the content with - * @param packet_size Size of the data - * @return @li \c true if packet_size is smaller than \c MAX_PACKET_SIZE. - * @li \c false else. - */ - bool addWholeData(const uint8_t* p_data, uint32_t packet_size); + static const uint16_t PACKET_MAX_SIZE = 1024; + /** + * The constructor initializes the packet and sets all header information + * according to the passed parameters. + * @param packetDataLength Sets the packet data length field and therefore specifies + * the size of the packet. + * @param isTelecommand Sets the packet type field to either TC (true) or TM (false). + * @param apid Sets the packet's APID field. The default value describes an idle packet. + * @param sequenceCount ets the packet's Source Sequence Count field. + */ + SpacePacket(uint16_t packetDataLength, bool isTelecommand = false, + uint16_t apid = APID_IDLE_PACKET, uint16_t sequenceCount = 0); + /** + * The class's default destructor. + */ + virtual ~SpacePacket(); + + static constexpr uint16_t getTcSpacePacketIdFromApid(uint16_t apid) { + uint16_t tcPacketId = (0x18 << 8) | (((apid >> 8) & 0x07) << 8) | (apid & 0x00ff); + return tcPacketId; + } + static constexpr uint16_t getTmSpacePacketIdFromApid(uint16_t apid) { + uint16_t tmPacketId = (0x08 << 8) | (((apid >> 8) & 0x07) << 8) | (apid & 0x00ff); + return tmPacketId; + } + + /** + * With this call, the complete data content (including the CCSDS Primary + * Header) is overwritten with the byte stream given. + * @param p_data Pointer to data to overwrite the content with + * @param packet_size Size of the data + * @return @li \c true if packet_size is smaller than \c MAX_PACKET_SIZE. + * @li \c false else. + */ + bool addWholeData(const uint8_t* p_data, uint32_t packet_size); protected: - /** - * This structure defines the data structure of a Space Packet as local data. - * There's a buffer which corresponds to the Space Packet Data Field with a - * maximum size of \c PACKET_MAX_SIZE. - */ - struct PacketStructured { - CCSDSPrimaryHeader header; - uint8_t buffer[PACKET_MAX_SIZE]; - }; - /** - * This union simplifies accessing the full data content of the Space Packet. - * This is achieved by putting the \c PacketStructured struct in a union with - * a plain buffer. - */ - union SpacePacketData { - PacketStructured fields; - uint8_t byteStream[PACKET_MAX_SIZE + sizeof(CCSDSPrimaryHeader)]; - }; - /** - * This is the data representation of the class. - * It is a struct of CCSDS Primary Header and a data field, which again is - * packed in an union, so the data can be accessed as a byte stream without - * a cast. - */ - SpacePacketData localData; + /** + * This structure defines the data structure of a Space Packet as local data. + * There's a buffer which corresponds to the Space Packet Data Field with a + * maximum size of \c PACKET_MAX_SIZE. + */ + struct PacketStructured { + CCSDSPrimaryHeader header; + uint8_t buffer[PACKET_MAX_SIZE]; + }; + /** + * This union simplifies accessing the full data content of the Space Packet. + * This is achieved by putting the \c PacketStructured struct in a union with + * a plain buffer. + */ + union SpacePacketData { + PacketStructured fields; + uint8_t byteStream[PACKET_MAX_SIZE + sizeof(CCSDSPrimaryHeader)]; + }; + /** + * This is the data representation of the class. + * It is a struct of CCSDS Primary Header and a data field, which again is + * packed in an union, so the data can be accessed as a byte stream without + * a cast. + */ + SpacePacketData localData; }; #endif /* SPACEPACKET_H_ */ diff --git a/src/fsfw/tmtcservices/SpacePacketParser.cpp b/src/fsfw/tmtcservices/SpacePacketParser.cpp new file mode 100644 index 00000000..84f861cf --- /dev/null +++ b/src/fsfw/tmtcservices/SpacePacketParser.cpp @@ -0,0 +1,77 @@ +#include +#include +#include + +SpacePacketParser::SpacePacketParser(std::vector validPacketIds): + validPacketIds(validPacketIds) { +} + +ReturnValue_t SpacePacketParser::parseSpacePackets(const uint8_t *buffer, + const size_t maxSize, size_t& startIndex, size_t& foundSize) { + const uint8_t** tempPtr = &buffer; + size_t readLen = 0; + return parseSpacePackets(tempPtr, maxSize, startIndex, foundSize, readLen); +} + +ReturnValue_t SpacePacketParser::parseSpacePackets(const uint8_t **buffer, const size_t maxSize, + size_t &startIndex, size_t &foundSize, size_t& readLen) { + if(buffer == nullptr or maxSize < 5) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "SpacePacketParser::parseSpacePackets: Frame invalid" << std::endl; +#else + sif::printWarning("SpacePacketParser::parseSpacePackets: Frame invalid\n"); +#endif + return HasReturnvaluesIF::RETURN_FAILED; + } + const uint8_t* bufPtr = *buffer; + + auto verifyLengthField = [&](size_t idx) { + uint16_t lengthField = bufPtr[idx + 4] << 8 | bufPtr[idx + 5]; + size_t packetSize = lengthField + 7; + startIndex = idx; + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + if(lengthField == 0) { + // Skip whole header for now + foundSize = 6; + result = NO_PACKET_FOUND; + } + else if(packetSize + idx > maxSize) { + // Don't increment buffer and read length here, user has to decide what to do + foundSize = packetSize; + return SPLIT_PACKET; + } + else { + foundSize = packetSize; + } + *buffer += foundSize; + readLen += foundSize; + return result; + }; + + size_t idx = 0; + // Space packet ID as start marker + if(validPacketIds.size() > 0) { + while(idx < maxSize - 5) { + uint16_t currentPacketId = bufPtr[idx] << 8 | bufPtr[idx + 1]; + if(std::find(validPacketIds.begin(), validPacketIds.end(), currentPacketId) != + validPacketIds.end()) { + if(idx + 5 >= maxSize) { + return SPLIT_PACKET; + } + return verifyLengthField(idx); + } + else { + idx++; + } + } + startIndex = 0; + foundSize = maxSize; + *buffer += foundSize; + readLen += foundSize; + return NO_PACKET_FOUND; + } + // Assume that the user verified a valid start of a space packet + else { + return verifyLengthField(idx); + } +} diff --git a/src/fsfw/tmtcservices/SpacePacketParser.h b/src/fsfw/tmtcservices/SpacePacketParser.h new file mode 100644 index 00000000..16b53ea4 --- /dev/null +++ b/src/fsfw/tmtcservices/SpacePacketParser.h @@ -0,0 +1,96 @@ +#ifndef FRAMEWORK_TMTCSERVICES_PUSPARSER_H_ +#define FRAMEWORK_TMTCSERVICES_PUSPARSER_H_ + +#include "fsfw/container/DynamicFIFO.h" +#include "fsfw/returnvalues/FwClassIds.h" + +#include +#include + +/** + * @brief This small helper class scans a given buffer for PUS packets. + * Can be used if PUS packets are serialized in a tightly packed frame. + * @details + * The parser uses the length field field of the space packets to find + * the respective space packet sizes. + * + * The parser parses a buffer by taking a pointer and the maximum size to scan. + * If space packets are found, they are stored in a FIFO which stores pairs + * consisting of the index in the buffer and the respective packet sizes. + * + * If the parser detects split packets (which means that the size of the + * next packet is larger than the remaining size to scan), it can either + * store that split packet or throw away the packet. + * @author R. Mueller + */ +class SpacePacketParser { +public: + //! The first entry is the index inside the buffer while the second index + //! is the size of the PUS packet starting at that index. + using IndexSizePair = std::pair; + + static constexpr uint8_t INTERFACE_ID = CLASS_ID::PUS_PARSER; + static constexpr ReturnValue_t NO_PACKET_FOUND = MAKE_RETURN_CODE(0x00); + static constexpr ReturnValue_t SPLIT_PACKET = MAKE_RETURN_CODE(0x01); + + /** + * @brief Parser constructor. + * @param maxExpectedPusPackets + * Maximum expected number of PUS packets. A good estimate is to divide + * the frame size by the minimum size of a PUS packet (12 bytes) + * @param storeSplitPackets + * Specifies whether split packets are also stored inside the FIFO, + * with the size being the remaining frame size. + */ + SpacePacketParser(std::vector validPacketIds); + + /** + * Parse a given frame for PUS packets + * @param frame + * @param frameSize + * @param foundPackets The number of found packets will be stored here + * @return + * -@c NO_PACKET_FOUND if no packet was found + * -@c SPLIT_PACKET if splitting is enabled and a split packet was found + * -@c RETURN_OK if a packet was found. The index and sizes are stored in the internal FIFO + */ + ReturnValue_t parseSpacePackets(const uint8_t* buffer, const size_t maxSize, + size_t& startIndex, size_t& foundSize); + + ReturnValue_t parseSpacePackets(const uint8_t **buffer, const size_t maxSize, + size_t& startIndex, size_t& foundSize, size_t& readLen); + /** + * Accessor function to get a reference to the internal FIFO which + * stores pairs of index and packet sizes. This FIFO is filled + * by the #parsePusPackets function. + * @return + */ + //DynamicFIFO& fifo(); + + /** + * Retrieve the next index and packet size pair from the FIFO. + * This also removes it from the FIFO. Please note that if the FIFO + * is empty, an empty pair will be returned. + * @return + */ + //IndexSizePair getNextFifoPair(); + +private: + /** + * A FIFO is used to store information about multiple PUS packets + * inside the receive buffer. The maximum number of entries is defined + * by the first constructor argument. + */ + //DynamicFIFO indexSizePairFIFO; + + std::vector validPacketIds; + + //bool storeSplitPackets = false; + +// ReturnValue_t readMultiplePackets(const uint8_t *frame, size_t frameSize, +// size_t startIndex, uint32_t& foundPackets); +// ReturnValue_t readNextPacket(const uint8_t *frame, +// size_t frameSize, size_t& startIndex, uint32_t& foundPackets); +}; + +#endif /* FRAMEWORK_TMTCSERVICES_PUSPARSER_H_ */ From e536918804255bf035ba78e5ddb9171b01f02761 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 28 Sep 2021 15:09:56 +0200 Subject: [PATCH 02/49] wiretapping in runtime config now --- src/fsfw/osal/common/TcpTmTcServer.cpp | 24 +++++++++++++++--------- src/fsfw/osal/common/TcpTmTcServer.h | 5 ++++- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/fsfw/osal/common/TcpTmTcServer.cpp b/src/fsfw/osal/common/TcpTmTcServer.cpp index e320b46b..5be9373e 100644 --- a/src/fsfw/osal/common/TcpTmTcServer.cpp +++ b/src/fsfw/osal/common/TcpTmTcServer.cpp @@ -5,12 +5,13 @@ #include "TcpTmTcBridge.h" #include "tcpipHelpers.h" +#include "fsfw/tmtcservices/SpacePacketParser.h" #include "fsfw/tasks/TaskFactory.h" +#include "fsfw/globalfunctions/arrayprinter.h" #include "fsfw/container/SharedRingBuffer.h" #include "fsfw/ipc/MessageQueueSenderIF.h" #include "fsfw/ipc/MutexGuard.h" #include "fsfw/objectmanager/ObjectManager.h" - #include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/tmtcservices/TmTcMessage.h" @@ -20,11 +21,6 @@ #elif defined(PLATFORM_UNIX) #include #endif -#include - -#ifndef FSFW_TCP_RECV_WIRETAPPING_ENABLED -#define FSFW_TCP_RECV_WIRETAPPING_ENABLED 0 -#endif const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT; @@ -202,9 +198,11 @@ void TcpTmTcServer::handleServerOperation(socket_t& connSocket) { } ReturnValue_t TcpTmTcServer::handleTcReception(uint8_t* spacePacket, size_t packetSize) { -#if FSFW_TCP_RECV_WIRETAPPING_ENABLED == 1 - arrayprinter::print(receptionBuffer.data(), bytesRead); -#endif + if(wiretappingEnabled) { + sif::info << "Received TC:" << std::endl; + arrayprinter::print(spacePacket, packetSize); + } + if(spacePacket == nullptr or packetSize == 0) { return HasReturnvaluesIF::RETURN_FAILED; } @@ -268,6 +266,10 @@ ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent) if(result != HasReturnvaluesIF::RETURN_OK) { return result; } + if(wiretappingEnabled) { + sif::info << "Sending TM:" << std::endl; + arrayprinter::print(storeAccessor.data(), storeAccessor.size()); + } int retval = send(connSocket, reinterpret_cast(storeAccessor.data()), storeAccessor.size(), @@ -346,6 +348,10 @@ ReturnValue_t TcpTmTcServer::handleTcRingBufferData(size_t availableReadData) { return status; } +void TcpTmTcServer::enableWiretapping(bool enable) { + this->wiretappingEnabled = enable; +} + void TcpTmTcServer::handleSocketError(ConstStorageAccessor &accessor) { // Don't delete data accessor.release(); diff --git a/src/fsfw/osal/common/TcpTmTcServer.h b/src/fsfw/osal/common/TcpTmTcServer.h index a0a31655..d5214848 100644 --- a/src/fsfw/osal/common/TcpTmTcServer.h +++ b/src/fsfw/osal/common/TcpTmTcServer.h @@ -1,7 +1,6 @@ #ifndef FSFW_OSAL_COMMON_TCP_TMTC_SERVER_H_ #define FSFW_OSAL_COMMON_TCP_TMTC_SERVER_H_ -#include #include "TcpIpBase.h" #include "fsfw/platform.h" @@ -22,6 +21,7 @@ #include class TcpTmTcBridge; +class SpacePacketParser; /** * @brief TCP server implementation @@ -91,6 +91,8 @@ public: ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS); virtual~ TcpTmTcServer(); + void enableWiretapping(bool enable); + /** * Get a handle to the TCP configuration struct, which can be used to configure TCP * properties @@ -113,6 +115,7 @@ private: //! TMTC bridge is cached. object_id_t tmtcBridgeId = objects::NO_OBJECT; TcpTmTcBridge* tmtcBridge = nullptr; + bool wiretappingEnabled = false; ReceptionModes receptionMode; TcpConfig tcpConfig; From bbea5e33bc66d05589d6143c0e75931acd99de83 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 28 Sep 2021 15:12:23 +0200 Subject: [PATCH 03/49] removed obsolete empty ctor --- src/fsfw/osal/common/TcpTmTcServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsfw/osal/common/TcpTmTcServer.cpp b/src/fsfw/osal/common/TcpTmTcServer.cpp index 5be9373e..fb421fc7 100644 --- a/src/fsfw/osal/common/TcpTmTcServer.cpp +++ b/src/fsfw/osal/common/TcpTmTcServer.cpp @@ -29,7 +29,7 @@ TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge, ReceptionModes receptionMode): SystemObject(objectId), tmtcBridgeId(tmtcTcpBridge), receptionMode(receptionMode), tcpConfig(customTcpServerPort), receptionBuffer(receptionBufferSize), - ringBuffer(ringBufferSize, true), validPacketIds() { + ringBuffer(ringBufferSize, true) { } ReturnValue_t TcpTmTcServer::initialize() { From f02852d8d2bf40b2941ccd0816c1ed01d703fea7 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 28 Sep 2021 15:13:46 +0200 Subject: [PATCH 04/49] cmake lists file update --- src/fsfw/tmtcservices/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fsfw/tmtcservices/CMakeLists.txt b/src/fsfw/tmtcservices/CMakeLists.txt index c30af214..96cf99b5 100644 --- a/src/fsfw/tmtcservices/CMakeLists.txt +++ b/src/fsfw/tmtcservices/CMakeLists.txt @@ -6,4 +6,5 @@ target_sources(${LIB_FSFW_NAME} TmTcBridge.cpp TmTcMessage.cpp VerificationReporter.cpp + SpacePacketParser.cpp ) \ No newline at end of file From a4d6421510575b9eda7f27c1637963c91881f922 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 28 Sep 2021 15:30:01 +0200 Subject: [PATCH 05/49] documentation and bugfixes --- src/fsfw/tmtcservices/SpacePacketParser.cpp | 2 +- src/fsfw/tmtcservices/SpacePacketParser.h | 100 ++++++++------------ 2 files changed, 42 insertions(+), 60 deletions(-) diff --git a/src/fsfw/tmtcservices/SpacePacketParser.cpp b/src/fsfw/tmtcservices/SpacePacketParser.cpp index 84f861cf..3d442458 100644 --- a/src/fsfw/tmtcservices/SpacePacketParser.cpp +++ b/src/fsfw/tmtcservices/SpacePacketParser.cpp @@ -44,7 +44,7 @@ ReturnValue_t SpacePacketParser::parseSpacePackets(const uint8_t **buffer, const foundSize = packetSize; } *buffer += foundSize; - readLen += foundSize; + readLen += idx + foundSize; return result; }; diff --git a/src/fsfw/tmtcservices/SpacePacketParser.h b/src/fsfw/tmtcservices/SpacePacketParser.h index 16b53ea4..82b15010 100644 --- a/src/fsfw/tmtcservices/SpacePacketParser.h +++ b/src/fsfw/tmtcservices/SpacePacketParser.h @@ -8,19 +8,11 @@ #include /** - * @brief This small helper class scans a given buffer for PUS packets. - * Can be used if PUS packets are serialized in a tightly packed frame. + * @brief This small helper class scans a given buffer for space packets. + * Can be used if space packets are serialized in a tightly packed frame. * @details - * The parser uses the length field field of the space packets to find - * the respective space packet sizes. - * - * The parser parses a buffer by taking a pointer and the maximum size to scan. - * If space packets are found, they are stored in a FIFO which stores pairs - * consisting of the index in the buffer and the respective packet sizes. - * - * If the parser detects split packets (which means that the size of the - * next packet is larger than the remaining size to scan), it can either - * store that split packet or throw away the packet. + * The parser uses the length field field and the 16-bit TC packet ID of the space packets to find + * find space packets in a given data stream * @author R. Mueller */ class SpacePacketParser { @@ -35,62 +27,52 @@ public: /** * @brief Parser constructor. - * @param maxExpectedPusPackets - * Maximum expected number of PUS packets. A good estimate is to divide - * the frame size by the minimum size of a PUS packet (12 bytes) - * @param storeSplitPackets - * Specifies whether split packets are also stored inside the FIFO, - * with the size being the remaining frame size. + * @param validPacketIds This vector contains the allowed 16-bit TC packet ID start markers + * The parser will search for these stark markers to detect the start of a space packet. + * It is also possible to pass an empty vector here, but this is not recommended. + * If an empty vector is passed, the parser will assume that the start of the given stream + * contains the start of a new space packet. */ SpacePacketParser(std::vector validPacketIds); + /** + * Parse a given frame for space packets but also increment the given buffer and assign the + * total number of bytes read so far + * @param buffer Parser will look for space packets in this buffer + * @param maxSize Maximum size of the buffer + * @param startIndex Start index of a found space packet + * @param foundSize Found size of the space packet + * @param readLen Length read so far. This value is incremented by the number of parsed + * bytes which also includes the size of a found packet + * -@c NO_PACKET_FOUND if no packet was found in the given buffer or the length field is + * invalid. foundSize will be set to the size of the space packet header. buffer and + * readLen will be incremented accordingly. + * -@c SPLIT_PACKET if a packet was found but the detected size exceeds maxSize. foundSize + * will be set to the detected packet size and startIndex will be set to the start of the + * detected packet. buffer and read length will not be incremented but the found length + * will be assigned. + * -@c RETURN_OK if a packet was found + */ + ReturnValue_t parseSpacePackets(const uint8_t **buffer, const size_t maxSize, + size_t& startIndex, size_t& foundSize, size_t& readLen); + /** - * Parse a given frame for PUS packets - * @param frame - * @param frameSize - * @param foundPackets The number of found packets will be stored here - * @return - * -@c NO_PACKET_FOUND if no packet was found - * -@c SPLIT_PACKET if splitting is enabled and a split packet was found - * -@c RETURN_OK if a packet was found. The index and sizes are stored in the internal FIFO + * Parse a given frame for space packets + * @param buffer Parser will look for space packets in this buffer + * @param maxSize Maximum size of the buffer + * @param startIndex Start index of a found space packet + * @param foundSize Found size of the space packet + * -@c NO_PACKET_FOUND if no packet was found in the given buffer or the length field is + * invalid. foundSize will be set to the size of the space packet header + * -@c SPLIT_PACKET if a packet was found but the detected size exceeds maxSize. foundSize + * will be set to the detected packet size and startIndex will be set to the start of the + * detected packet + * -@c RETURN_OK if a packet was found */ ReturnValue_t parseSpacePackets(const uint8_t* buffer, const size_t maxSize, size_t& startIndex, size_t& foundSize); - - ReturnValue_t parseSpacePackets(const uint8_t **buffer, const size_t maxSize, - size_t& startIndex, size_t& foundSize, size_t& readLen); - /** - * Accessor function to get a reference to the internal FIFO which - * stores pairs of index and packet sizes. This FIFO is filled - * by the #parsePusPackets function. - * @return - */ - //DynamicFIFO& fifo(); - - /** - * Retrieve the next index and packet size pair from the FIFO. - * This also removes it from the FIFO. Please note that if the FIFO - * is empty, an empty pair will be returned. - * @return - */ - //IndexSizePair getNextFifoPair(); - private: - /** - * A FIFO is used to store information about multiple PUS packets - * inside the receive buffer. The maximum number of entries is defined - * by the first constructor argument. - */ - //DynamicFIFO indexSizePairFIFO; - std::vector validPacketIds; - - //bool storeSplitPackets = false; - -// ReturnValue_t readMultiplePackets(const uint8_t *frame, size_t frameSize, -// size_t startIndex, uint32_t& foundPackets); -// ReturnValue_t readNextPacket(const uint8_t *frame, -// size_t frameSize, size_t& startIndex, uint32_t& foundPackets); }; #endif /* FRAMEWORK_TMTCSERVICES_PUSPARSER_H_ */ From 1622e23f1c15ddcf1d4b522c332c1ab156f91fd9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 28 Sep 2021 15:32:58 +0200 Subject: [PATCH 06/49] delay configurable --- src/fsfw/osal/common/TcpTmTcServer.cpp | 2 +- src/fsfw/osal/common/TcpTmTcServer.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/fsfw/osal/common/TcpTmTcServer.cpp b/src/fsfw/osal/common/TcpTmTcServer.cpp index fb421fc7..c3936146 100644 --- a/src/fsfw/osal/common/TcpTmTcServer.cpp +++ b/src/fsfw/osal/common/TcpTmTcServer.cpp @@ -187,7 +187,7 @@ void TcpTmTcServer::handleServerOperation(socket_t& connSocket) { return; } if(not tcAvailable and not tmSent) { - TaskFactory::delayTask(DEFAULT_LOOP_DELAY_MS); + TaskFactory::delayTask(tcpConfig.tcpLoopDelay); } } else { diff --git a/src/fsfw/osal/common/TcpTmTcServer.h b/src/fsfw/osal/common/TcpTmTcServer.h index d5214848..da0e8bd5 100644 --- a/src/fsfw/osal/common/TcpTmTcServer.h +++ b/src/fsfw/osal/common/TcpTmTcServer.h @@ -59,9 +59,10 @@ public: int tcpBacklog = 3; /** - * Passed to the select call which is used to ensure non-blocking TC reception + * If no telecommands packets are being received and no telemetry is being sent, + * the TCP server will delay periodically by this amount to decrease the CPU load */ - //uint32_t selectTimeoutMs = DEFAULT_SELECT_TIMEOUT_MS; + uint32_t tcpLoopDelay = DEFAULT_LOOP_DELAY_MS ; /** * Passed to the send call */ From bf02f14772184394c51c500ccc6dc312839de746 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 28 Sep 2021 16:31:53 +0200 Subject: [PATCH 07/49] C++11 adaptions --- src/fsfw/tmtcpacket/SpacePacket.h | 17 ++++++++--------- src/fsfw/tmtcservices/SpacePacketParser.h | 2 +- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/fsfw/tmtcpacket/SpacePacket.h b/src/fsfw/tmtcpacket/SpacePacket.h index 9eec87a8..67746859 100644 --- a/src/fsfw/tmtcpacket/SpacePacket.h +++ b/src/fsfw/tmtcpacket/SpacePacket.h @@ -32,15 +32,6 @@ public: */ virtual ~SpacePacket(); - static constexpr uint16_t getTcSpacePacketIdFromApid(uint16_t apid) { - uint16_t tcPacketId = (0x18 << 8) | (((apid >> 8) & 0x07) << 8) | (apid & 0x00ff); - return tcPacketId; - } - static constexpr uint16_t getTmSpacePacketIdFromApid(uint16_t apid) { - uint16_t tmPacketId = (0x08 << 8) | (((apid >> 8) & 0x07) << 8) | (apid & 0x00ff); - return tmPacketId; - } - /** * With this call, the complete data content (including the CCSDS Primary * Header) is overwritten with the byte stream given. @@ -78,4 +69,12 @@ protected: SpacePacketData localData; }; +constexpr uint16_t getTcSpacePacketIdFromApid(uint16_t apid) { + return (0x18 << 8) | (((apid >> 8) & 0x07) << 8) | (apid & 0x00ff); +} + +constexpr uint16_t getTmSpacePacketIdFromApid(uint16_t apid) { + return (0x08 << 8) | (((apid >> 8) & 0x07) << 8) | (apid & 0x00ff); +} + #endif /* SPACEPACKET_H_ */ diff --git a/src/fsfw/tmtcservices/SpacePacketParser.h b/src/fsfw/tmtcservices/SpacePacketParser.h index 82b15010..bed3369b 100644 --- a/src/fsfw/tmtcservices/SpacePacketParser.h +++ b/src/fsfw/tmtcservices/SpacePacketParser.h @@ -21,7 +21,7 @@ public: //! is the size of the PUS packet starting at that index. using IndexSizePair = std::pair; - static constexpr uint8_t INTERFACE_ID = CLASS_ID::PUS_PARSER; + static constexpr uint8_t INTERFACE_ID = CLASS_ID::SPACE_PACKET_PARSER; static constexpr ReturnValue_t NO_PACKET_FOUND = MAKE_RETURN_CODE(0x00); static constexpr ReturnValue_t SPLIT_PACKET = MAKE_RETURN_CODE(0x01); From 936bac5abdd6e56e8f3be85b624620948fecf714 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 28 Sep 2021 16:32:43 +0200 Subject: [PATCH 08/49] class id renamed --- src/fsfw/returnvalues/FwClassIds.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fsfw/returnvalues/FwClassIds.h b/src/fsfw/returnvalues/FwClassIds.h index cdbf5657..337709ed 100644 --- a/src/fsfw/returnvalues/FwClassIds.h +++ b/src/fsfw/returnvalues/FwClassIds.h @@ -78,6 +78,7 @@ enum: uint8_t { HAL_GPIO, //HGIO MGM_LIS3MDL, //MGMLIS3 MGM_RM3100, //MGMRM3100 + SPACE_PACKET_PARSER, //SPPA FW_CLASS_ID_COUNT // [EXPORT] : [END] }; From 32b5060c626261bd2729210f318bcc127d0117c3 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 28 Sep 2021 17:26:02 +0200 Subject: [PATCH 09/49] all windows fixes --- src/fsfw/osal/common/TcpTmTcServer.cpp | 158 +++++++++++++++++++++++-- src/fsfw/osal/common/TcpTmTcServer.h | 17 ++- 2 files changed, 162 insertions(+), 13 deletions(-) diff --git a/src/fsfw/osal/common/TcpTmTcServer.cpp b/src/fsfw/osal/common/TcpTmTcServer.cpp index 11ab71af..b22f4412 100644 --- a/src/fsfw/osal/common/TcpTmTcServer.cpp +++ b/src/fsfw/osal/common/TcpTmTcServer.cpp @@ -41,6 +41,17 @@ ReturnValue_t TcpTmTcServer::initialize() { return result; } + switch(receptionMode) { + case(ReceptionModes::SPACE_PACKETS): { + spacePacketParser = new SpacePacketParser(validPacketIds); + if(spacePacketParser == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } +#if defined PLATFORM_UNIX + tcpConfig.tcpFlags |= MSG_DONTWAIT; +#endif + } + } tcStore = ObjectManager::instance()->get(objects::TC_STORE); if (tcStore == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 @@ -144,11 +155,14 @@ ReturnValue_t TcpTmTcServer::initializeAfterTaskCreation() { return HasReturnvaluesIF::RETURN_OK; } -void TcpTmTcServer::handleServerOperation(socket_t connSocket) { - int retval = 0; - do { - // Read all telecommands sent by the client - retval = recv(connSocket, +void TcpTmTcServer::handleServerOperation(socket_t& connSocket) { +#if defined PLATFORM_WIN + setSocketNonBlocking(connSocket); +#endif + + while (true) { + int retval = recv( + connSocket, reinterpret_cast(receptionBuffer.data()), receptionBuffer.capacity(), tcpFlags); @@ -159,9 +173,34 @@ void TcpTmTcServer::handleServerOperation(socket_t connSocket) { // Client has finished sending telecommands, send telemetry now handleTmSending(connSocket); } - else { - // Should not happen - tcpip::handleError(tcpip::Protocol::TCP, tcpip::ErrorSources::RECV_CALL); + else if(retval < 0) { + int errorValue = GetLastError(); +#if defined PLATFORM_UNIX + int wouldBlockValue = EAGAIN; +#elif defined PLATFORM_WIN + int wouldBlockValue = WSAEWOULDBLOCK; +#endif + if(errorValue == wouldBlockValue) { + // No data available. Check whether any packets have been read, then send back + // telemetry if available + bool tcAvailable = false; + bool tmSent = false; + size_t availableReadData = ringBuffer.getAvailableReadData(); + if(availableReadData > lastRingBufferSize) { + tcAvailable = true; + handleTcRingBufferData(availableReadData); + } + ReturnValue_t result = handleTmSending(connSocket, tmSent); + if(result == CONN_BROKEN) { + return; + } + if(not tcAvailable and not tmSent) { + TaskFactory::delayTask(tcpConfig.tcpLoopDelay); + } + } + else { + tcpip::handleError(tcpip::Protocol::TCP, tcpip::ErrorSources::RECV_CALL, 300); + } } } while(retval > 0); } @@ -228,3 +267,106 @@ ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket) { } return HasReturnvaluesIF::RETURN_OK; } + +ReturnValue_t TcpTmTcServer::handleTcRingBufferData(size_t availableReadData) { + ReturnValue_t status = HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + size_t readAmount = availableReadData; + lastRingBufferSize = availableReadData; + if(readAmount >= ringBuffer.getMaxSize()) { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + // Possible configuration error, too much data or/and data coming in too fast, + // requiring larger buffers + sif::warning << "TcpTmTcServer::handleServerOperation: Ring buffer reached " << + "fill count" << std::endl; +#else + sif::printWarning("TcpTmTcServer::handleServerOperation: Ring buffer reached " + "fill count"); +#endif +#endif + } + if(readAmount >= receptionBuffer.size()) { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + // Possible configuration error, too much data or/and data coming in too fast, + // requiring larger buffers + sif::warning << "TcpTmTcServer::handleServerOperation: " + "Reception buffer too small " << std::endl; +#else + sif::printWarning("TcpTmTcServer::handleServerOperation: Reception buffer too small\n"); +#endif +#endif + readAmount = receptionBuffer.size(); + } + ringBuffer.readData(receptionBuffer.data(), readAmount, true); + const uint8_t* bufPtr = receptionBuffer.data(); + const uint8_t** bufPtrPtr = &bufPtr; + size_t startIdx = 0; + size_t foundSize = 0; + size_t readLen = 0; + while(readLen < readAmount) { + result = spacePacketParser->parseSpacePackets(bufPtrPtr, readAmount, + startIdx, foundSize, readLen); + switch(result) { + case(SpacePacketParser::NO_PACKET_FOUND): + case(SpacePacketParser::SPLIT_PACKET): { + break; + } + case(HasReturnvaluesIF::RETURN_OK): { + result = handleTcReception(receptionBuffer.data() + startIdx, foundSize); + if(result != HasReturnvaluesIF::RETURN_OK) { + status = result; + } + } + } + ringBuffer.deleteData(foundSize); + lastRingBufferSize = ringBuffer.getAvailableReadData(); + std::memset(receptionBuffer.data() + startIdx, 0, foundSize); + } + return status; +} + +void TcpTmTcServer::enableWiretapping(bool enable) { + this->wiretappingEnabled = enable; +} + +void TcpTmTcServer::handleSocketError(ConstStorageAccessor &accessor) { + // Don't delete data + accessor.release(); + auto socketError = getLastSocketError(); + switch(socketError) { +#if defined PLATFORM_WIN + case(WSAECONNRESET): { + // See https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-send + // Remote client might have shut down connection + return; + } +#else + case(EPIPE): { + // See https://man7.org/linux/man-pages/man2/send.2.html + // Remote client might have shut down connection + return; + } +#endif + default: { + tcpip::handleError(tcpip::Protocol::TCP, tcpip::ErrorSources::SEND_CALL); + } + } +} + +void TcpTmTcServer::setSocketNonBlocking(socket_t &connSocket) { + u_long iMode = 1; + int iResult = ioctlsocket(connSocket, FIONBIO, &iMode); + if(iResult != NO_ERROR) { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "TcpTmTcServer::handleServerOperation: Setting socket" + " non-blocking failed with error " << iResult; +#else + sif::printWarning("TcpTmTcServer::handleServerOperation: Setting socket" + " non-blocking failed with error %d\n", iResult); +#endif +#endif + } +} diff --git a/src/fsfw/osal/common/TcpTmTcServer.h b/src/fsfw/osal/common/TcpTmTcServer.h index c6916080..2104d859 100644 --- a/src/fsfw/osal/common/TcpTmTcServer.h +++ b/src/fsfw/osal/common/TcpTmTcServer.h @@ -84,12 +84,19 @@ private: int tcpBacklog = 3; std::vector receptionBuffer; - int tcpSockOpt = 0; - int tcpTmFlags = 0; + SimpleRingBuffer ringBuffer; + std::vector validPacketIds; + SpacePacketParser* spacePacketParser = nullptr; + uint8_t lastRingBufferSize = 0; - void handleServerOperation(socket_t connSocket); - ReturnValue_t handleTcReception(size_t bytesRecvd); - ReturnValue_t handleTmSending(socket_t connSocket); + virtual void handleServerOperation(socket_t& connSocket); + ReturnValue_t handleTcReception(uint8_t* spacePacket, size_t packetSize); + ReturnValue_t handleTmSending(socket_t connSocket, bool& tmSent); + ReturnValue_t handleTcRingBufferData(size_t availableReadData); + void handleSocketError(ConstStorageAccessor& accessor); +#if defined PLATFORM_WIN + void setSocketNonBlocking(socket_t& connSocket); +#endif }; #endif /* FSFW_OSAL_COMMON_TCP_TMTC_SERVER_H_ */ From b1a9c90087bad07c81f9f96594edf7e2fa51d077 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 28 Sep 2021 17:38:35 +0200 Subject: [PATCH 10/49] this should work for both OSes --- src/fsfw/osal/common/TcpTmTcServer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/fsfw/osal/common/TcpTmTcServer.cpp b/src/fsfw/osal/common/TcpTmTcServer.cpp index 4348e21e..519df547 100644 --- a/src/fsfw/osal/common/TcpTmTcServer.cpp +++ b/src/fsfw/osal/common/TcpTmTcServer.cpp @@ -177,7 +177,7 @@ void TcpTmTcServer::handleServerOperation(socket_t& connSocket) { ringBuffer.writeData(receptionBuffer.data(), retval); } else if(retval < 0) { - int errorValue = GetLastError(); + int errorValue = getLastSocketError(); #if defined PLATFORM_UNIX int wouldBlockValue = EAGAIN; #elif defined PLATFORM_WIN @@ -387,6 +387,7 @@ void TcpTmTcServer::handleSocketError(ConstStorageAccessor &accessor) { } } +#if defined PLATFORM_WIN void TcpTmTcServer::setSocketNonBlocking(socket_t &connSocket) { u_long iMode = 1; int iResult = ioctlsocket(connSocket, FIONBIO, &iMode); @@ -402,3 +403,4 @@ void TcpTmTcServer::setSocketNonBlocking(socket_t &connSocket) { #endif } } +#endif From cffd77ed325aa24bef3f22bc85dbd573c2db362e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 28 Sep 2021 17:42:29 +0200 Subject: [PATCH 11/49] put functions in namespace --- src/fsfw/tmtcpacket/SpacePacket.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/fsfw/tmtcpacket/SpacePacket.h b/src/fsfw/tmtcpacket/SpacePacket.h index 67746859..fe8a1044 100644 --- a/src/fsfw/tmtcpacket/SpacePacket.h +++ b/src/fsfw/tmtcpacket/SpacePacket.h @@ -69,6 +69,8 @@ protected: SpacePacketData localData; }; +namespace spacepacket { + constexpr uint16_t getTcSpacePacketIdFromApid(uint16_t apid) { return (0x18 << 8) | (((apid >> 8) & 0x07) << 8) | (apid & 0x00ff); } @@ -77,4 +79,6 @@ constexpr uint16_t getTmSpacePacketIdFromApid(uint16_t apid) { return (0x08 << 8) | (((apid >> 8) & 0x07) << 8) | (apid & 0x00ff); } +} + #endif /* SPACEPACKET_H_ */ From 0a6a32a13003103ee6462d1c46f814e0c44ab07b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 29 Sep 2021 11:45:20 +0200 Subject: [PATCH 12/49] printout separation --- src/fsfw/osal/common/TcpTmTcServer.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/fsfw/osal/common/TcpTmTcServer.cpp b/src/fsfw/osal/common/TcpTmTcServer.cpp index 519df547..8b34b1a3 100644 --- a/src/fsfw/osal/common/TcpTmTcServer.cpp +++ b/src/fsfw/osal/common/TcpTmTcServer.cpp @@ -210,7 +210,11 @@ void TcpTmTcServer::handleServerOperation(socket_t& connSocket) { ReturnValue_t TcpTmTcServer::handleTcReception(uint8_t* spacePacket, size_t packetSize) { if(wiretappingEnabled) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "Received TC:" << std::endl; +#else + sif::printInfo("Received TC:\n"); +#endif arrayprinter::print(spacePacket, packetSize); } @@ -278,7 +282,11 @@ ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent) return result; } if(wiretappingEnabled) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "Sending TM:" << std::endl; +#else + sif::printInfo("Sending TM:\n"); +#endif arrayprinter::print(storeAccessor.data(), storeAccessor.size()); } int retval = send(connSocket, From ade15ad16d9d03512b148fa83e1be14cb3d48570 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 7 Oct 2021 13:24:46 +0200 Subject: [PATCH 13/49] tests can now be built as part of FSFW This PR refactores the tests so they are built as part of the FSFW. This is done by adding Catch2 with the FetchContent directive. A future implementation might also use a system installation of Catch2 by first checking whether Catch2 can already be found as a package The custom configuration folder testcfg was moved from the user folder to the actual unittest folder. The tests can be built by setting the CMake FSFW_BUILD_UNITTESTS option to TRUE/ON. They are built with the static library and dropped inside the build folders fsfw directory. --- CMakeLists.txt | 129 +++++++++++++++++- README.md | 76 ++++++++++- scripts/coverage.py | 74 ++++++++++ tests/src/fsfw_tests/CMakeLists.txt | 2 +- .../internal/InternalUnitTester.cpp | 6 +- .../fsfw_tests/internal/osal/CMakeLists.txt | 6 +- .../internal/osal/testCmdExecutor.cpp | 1 + .../internal/osal/testCmdExecutor.h | 10 ++ .../osal/{IntTestMq.cpp => testMq.cpp} | 2 +- .../internal/osal/{IntTestMq.h => testMq.h} | 0 .../osal/{IntTestMutex.cpp => testMutex.cpp} | 2 +- .../osal/{IntTestMutex.h => testMutex.h} | 0 ...IntTestSemaphore.cpp => testSemaphore.cpp} | 2 +- .../{IntTestSemaphore.h => testSemaphore.h} | 0 tests/src/fsfw_tests/unit/CMakeLists.txt | 9 +- tests/src/fsfw_tests/unit/CatchFactory.h | 2 +- tests/src/fsfw_tests/unit/CatchRunner.cpp | 2 +- tests/src/fsfw_tests/unit/CatchRunner.h | 2 +- .../src/fsfw_tests/unit/action/CMakeLists.txt | 2 +- .../fsfw_tests/unit/container/CMakeLists.txt | 2 +- .../unit/datapoollocal/CMakeLists.txt | 2 +- .../unit/globalfunctions/CMakeLists.txt | 2 +- tests/src/fsfw_tests/unit/osal/CMakeLists.txt | 2 +- .../fsfw_tests/unit/serialize/CMakeLists.txt | 2 +- .../unit/storagemanager/CMakeLists.txt | 2 +- .../fsfw_tests/unit/testcfg/CMakeLists.txt | 28 ++++ .../fsfw_tests/unit}/testcfg/FSFWConfig.h.in | 39 +++--- .../fsfw_tests/unit/testcfg/OBSWConfig.h.in | 15 ++ .../fsfw_tests/unit}/testcfg/TestsConfig.h.in | 0 .../testcfg/devices/logicalAddresses.cpp | 0 .../unit}/testcfg/devices/logicalAddresses.h | 3 +- .../testcfg/devices/powerSwitcherList.cpp | 0 .../unit}/testcfg/devices/powerSwitcherList.h | 0 .../unit}/testcfg/events/subsystemIdRanges.h | 7 +- .../unit/testcfg/events/translateEvents.cpp | 15 ++ .../unit/testcfg/events/translateEvents.h | 8 ++ .../unit}/testcfg/ipc/MissionMessageTypes.cpp | 0 .../unit}/testcfg/ipc/MissionMessageTypes.h | 0 .../unit}/testcfg/objects/systemObjectList.h | 7 +- .../unit/testcfg/objects/translateObjects.cpp | 19 +++ .../unit/testcfg/objects/translateObjects.h | 8 ++ .../PollingSequenceFactory.cpp | 2 +- .../pollingsequence/PollingSequenceFactory.h | 0 .../unit}/testcfg/returnvalues/classIds.h | 3 +- .../fsfw_tests/unit}/testcfg/tmtc/apid.h | 1 + .../fsfw_tests/unit}/testcfg/tmtc/pusIds.h | 0 .../unit/timemanager/CMakeLists.txt | 2 +- .../fsfw_tests/unit/tmtcpacket/CMakeLists.txt | 2 +- tests/user/README.md | 19 --- tests/user/testcfg/CMakeLists.txt | 11 -- tests/user/testcfg/OBSWConfig.h.in | 8 -- 51 files changed, 429 insertions(+), 107 deletions(-) create mode 100755 scripts/coverage.py create mode 100644 tests/src/fsfw_tests/internal/osal/testCmdExecutor.cpp create mode 100644 tests/src/fsfw_tests/internal/osal/testCmdExecutor.h rename tests/src/fsfw_tests/internal/osal/{IntTestMq.cpp => testMq.cpp} (96%) rename tests/src/fsfw_tests/internal/osal/{IntTestMq.h => testMq.h} (100%) rename tests/src/fsfw_tests/internal/osal/{IntTestMutex.cpp => testMutex.cpp} (96%) rename tests/src/fsfw_tests/internal/osal/{IntTestMutex.h => testMutex.h} (100%) rename tests/src/fsfw_tests/internal/osal/{IntTestSemaphore.cpp => testSemaphore.cpp} (98%) rename tests/src/fsfw_tests/internal/osal/{IntTestSemaphore.h => testSemaphore.h} (100%) create mode 100644 tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt rename tests/{user => src/fsfw_tests/unit}/testcfg/FSFWConfig.h.in (67%) create mode 100644 tests/src/fsfw_tests/unit/testcfg/OBSWConfig.h.in rename tests/{user => src/fsfw_tests/unit}/testcfg/TestsConfig.h.in (100%) rename tests/{user => src/fsfw_tests/unit}/testcfg/devices/logicalAddresses.cpp (100%) rename tests/{user => src/fsfw_tests/unit}/testcfg/devices/logicalAddresses.h (84%) rename tests/{user => src/fsfw_tests/unit}/testcfg/devices/powerSwitcherList.cpp (100%) rename tests/{user => src/fsfw_tests/unit}/testcfg/devices/powerSwitcherList.h (100%) rename tests/{user => src/fsfw_tests/unit}/testcfg/events/subsystemIdRanges.h (64%) create mode 100644 tests/src/fsfw_tests/unit/testcfg/events/translateEvents.cpp create mode 100644 tests/src/fsfw_tests/unit/testcfg/events/translateEvents.h rename tests/{user => src/fsfw_tests/unit}/testcfg/ipc/MissionMessageTypes.cpp (100%) rename tests/{user => src/fsfw_tests/unit}/testcfg/ipc/MissionMessageTypes.h (100%) rename tests/{user => src/fsfw_tests/unit}/testcfg/objects/systemObjectList.h (84%) create mode 100644 tests/src/fsfw_tests/unit/testcfg/objects/translateObjects.cpp create mode 100644 tests/src/fsfw_tests/unit/testcfg/objects/translateObjects.h rename tests/{user => src/fsfw_tests/unit}/testcfg/pollingsequence/PollingSequenceFactory.cpp (97%) rename tests/{user => src/fsfw_tests/unit}/testcfg/pollingsequence/PollingSequenceFactory.h (100%) rename tests/{user => src/fsfw_tests/unit}/testcfg/returnvalues/classIds.h (76%) rename tests/{user => src/fsfw_tests/unit}/testcfg/tmtc/apid.h (90%) rename tests/{user => src/fsfw_tests/unit}/testcfg/tmtc/pusIds.h (100%) delete mode 100644 tests/user/README.md delete mode 100644 tests/user/testcfg/CMakeLists.txt delete mode 100644 tests/user/testcfg/OBSWConfig.h.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ff66a6d..ff631201 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,9 @@ cmake_minimum_required(VERSION 3.13) +set(FSFW_VERSION 2) +set(FSFW_SUBVERSION 0) +set(FSFW_REVISION 0) + option(FSFW_GENERATE_SECTIONS "Generate function and data sections. Required to remove unused code" ON ) @@ -7,6 +11,11 @@ if(FSFW_GENERATE_SECTIONS) option(FSFW_REMOVE_UNUSED_CODE "Remove unused code" ON) endif() +option(FSFW_BUILD_UNITTESTS "Build unittest binary in addition to static library" OFF) +if(FSFW_BUILD_UNITTESTS) + option(FSFW_TESTS_GEN_COV "Generate coverage data for unittests" ON) +endif() + option(FSFW_WARNING_SHADOW_LOCAL_GCC "Enable -Wshadow=local warning in GCC" ON) # Options to exclude parts of the FSFW from compilation. option(FSFW_ADD_INTERNAL_TESTS "Add internal unit tests" ON) @@ -26,11 +35,57 @@ option(FSFW_ADD_TMSTORAGE "Compile with tm storage components" OFF) option(FSFW_ADD_SGP4_PROPAGATOR "Add SGP4 propagator code" OFF) set(LIB_FSFW_NAME fsfw) +set(FSFW_TEST_TGT fsfw-tests) + add_library(${LIB_FSFW_NAME}) + +if(FSFW_BUILD_UNITTESTS) + # Check whether the user has already installed Catch2 first + find_package(Catch2 3) + # Not installed, so use FetchContent to download and provide Catch2 + if(NOT Catch2_FOUND) + include(FetchContent) + + FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG v3.0.0-preview3 + ) + + FetchContent_MakeAvailable(Catch2) + endif() + + configure_file(tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in tests/FSFWConfig.h) + configure_file(tests/src/fsfw_tests/unit/testcfg/TestsConfig.h.in tests/TestsConfig.h) + configure_file(tests/src/fsfw_tests/unit/testcfg/OBSWConfig.h.in tests/OBSWConfig.h) + add_executable(${FSFW_TEST_TGT}) + + if(FSFW_TESTS_GEN_COV) + include(FetchContent) + FetchContent_Declare( + cmake-modules + GIT_REPOSITORY https://github.com/bilke/cmake-modules.git + ) + FetchContent_MakeAvailable(cmake-modules) + list(APPEND CMAKE_MODULE_PATH ${cmake-modules_SOURCE_DIR}) + include(CodeCoverage) + endif() +endif() + set(FSFW_CORE_INC_PATH "inc") set_property(CACHE FSFW_OSAL PROPERTY STRINGS host linux rtems freertos) +# Configure Files +target_include_directories(${LIB_FSFW_NAME} PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} +) +target_include_directories(${LIB_FSFW_NAME} INTERFACE + ${CMAKE_CURRENT_BINARY_DIR} +) +configure_file(src/fsfw/FSFW.h.in FSFW.h) +configure_file(src/fsfw/FSFWVersion.h.in FSFWVersion.h) + if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) @@ -63,29 +118,29 @@ endif() set(FSFW_OSAL_DEFINITION FSFW_OSAL_HOST) if(FSFW_OSAL MATCHES host) - set(OS_FSFW_NAME "Host") + set(FSFW_OS_NAME "Host") set(FSFW_OSAL_HOST ON) elseif(FSFW_OSAL MATCHES linux) - set(OS_FSFW_NAME "Linux") + set(FSFW_OS_NAME "Linux") set(FSFW_OSAL_LINUX ON) elseif(FSFW_OSAL MATCHES freertos) - set(OS_FSFW_NAME "FreeRTOS") + set(FSFW_OS_NAME "FreeRTOS") set(FSFW_OSAL_FREERTOS ON) target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${LIB_OS_NAME} ) elseif(FSFW_OSAL STREQUAL rtems) - set(OS_FSFW_NAME "RTEMS") + set(FSFW_OS_NAME "RTEMS") set(FSFW_OSAL_RTEMS ON) else() message(WARNING "Invalid operating system for FSFW specified! Setting to host.." ) - set(OS_FSFW_NAME "Host") + set(FSFW_OS_NAME "Host") set(OS_FSFW "host") endif() -message(STATUS "Compiling FSFW for the ${OS_FSFW_NAME} operating system.") +message(STATUS "Compiling FSFW for the ${FSFW_OS_NAME} operating system.") add_subdirectory(src) add_subdirectory(tests) @@ -94,6 +149,66 @@ if(FSFW_ADD_HAL) endif() add_subdirectory(contrib) +if(FSFW_BUILD_UNITTESTS) + if(FSFW_TESTS_GEN_COV) + if(CMAKE_COMPILER_IS_GNUCXX) + include(CodeCoverage) + + # Remove quotes. + separate_arguments(COVERAGE_COMPILER_FLAGS + NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}" + ) + + # Add compile options manually, we don't want coverage for Catch2 + target_compile_options(${FSFW_TEST_TGT} PRIVATE + "${COVERAGE_COMPILER_FLAGS}" + ) + target_compile_options(${LIB_FSFW_NAME} PRIVATE + "${COVERAGE_COMPILER_FLAGS}" + ) + + # Exclude directories here + if(WIN32) + set(GCOVR_ADDITIONAL_ARGS + "--exclude-throw-branches" + "--exclude-unreachable-branches" + ) + set(COVERAGE_EXCLUDES + "/c/msys64/mingw64/*" + ) + elseif(UNIX) + set(COVERAGE_EXCLUDES + "/usr/include/*" "/usr/bin/*" "Catch2/*" + ) + endif() + + target_link_options(${FSFW_TEST_TGT} PRIVATE + -fprofile-arcs + -ftest-coverage + ) + target_link_options(${LIB_FSFW_NAME} PRIVATE + -fprofile-arcs + -ftest-coverage + ) + + if(WIN32) + setup_target_for_coverage_gcovr_html( + NAME ${FSFW_TEST_TGT}_coverage + EXECUTABLE ${FSFW_TEST_TGT} + DEPENDENCIES ${FSFW_TEST_TGT} + ) + else() + setup_target_for_coverage_lcov( + NAME ${FSFW_TEST_TGT}_coverage + EXECUTABLE ${FSFW_TEST_TGT} + DEPENDENCIES ${FSFW_TEST_TGT} + ) + endif() + endif() + endif() + target_link_libraries(${FSFW_TEST_TGT} PRIVATE Catch2::Catch2 ${LIB_FSFW_NAME}) +endif() + # The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it. # If this is not given, we include the default configuration and emit a warning. if(NOT FSFW_CONFIG_PATH) @@ -186,4 +301,4 @@ target_compile_options(${LIB_FSFW_NAME} PRIVATE target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${FSFW_ADDITIONAL_LINK_LIBS} -) \ No newline at end of file +) diff --git a/README.md b/README.md index 48d2b8e7..a7ae0e20 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,83 @@ Currently, the FSFW provides the following OSALs: - FreeRTOS - RTEMS -The recommended hardware is a microprocessor with more than 1 MB of RAM and 1 MB of non-volatile Memory. For reference, current applications use a Cobham Gaisler UT699 (LEON3FT), a ISISPACE IOBC or a Zynq-7020 SoC. The `fsfw` was also successfully run on the STM32H743ZI-Nucleo board and on a Raspberry Pi and is currently running on the active satellite mission Flying Laptop. +The recommended hardware is a microprocessor with more than 1 MB of RAM and 1 MB of non-volatile +memory. For reference, current applications use a Cobham Gaisler UT699 (LEON3FT), a +ISISPACE IOBC or a Zynq-7020 SoC. The `fsfw` was also successfully run on the +STM32H743ZI-Nucleo board and on a Raspberry Pi and is currently running on the active +satellite mission Flying Laptop. ## Getting started -The [FSFW example](https://egit.irs.uni-stuttgart.de/fsfw/fsfw_example) provides a good starting point and a demo to see the FSFW capabilities and build it with the Make or the CMake build system. It is recommended to evaluate the FSFW by building and playing around with the demo application. +The [Hosted FSFW example](https://egit.irs.uni-stuttgart.de/fsfw/fsfw-example-hosted) provides a +good starting point and a demo to see the FSFW capabilities. +It is recommended to get started by building and playing around with the demo application. +There are also other examples provided for all OSALs using the popular embedded platforms +Raspberry Pi, Beagle Bone Black and STM32H7. -Generally, the FSFW is included in a project by compiling the FSFW sources and providing -a configuration folder and adding it to the include path. There are some functions like `printChar` which are different depending on the target architecture and need to be implemented by the mission developer. +Generally, the FSFW is included in a project by providing +a configuration folder, building the static library and linking against it. +There are some functions like `printChar` which are different depending on the target architecture +and need to be implemented by the mission developer. A template configuration folder was provided and can be copied into the project root to have -a starting point. The [configuration section](doc/README-config.md#top) provides more specific information about the possible options. +a starting point. The [configuration section](doc/README-config.md#top) provides more specific +information about the possible options. + +## Adding the library + +The following steps show how to add and use FSFW components. It is still recommended to +try out the example mentioned above to get started, but the following steps show how to +add and link against the FSFW library in general. + +1. Add this repository as a submodule + + ```sh + git submodule add https://egit.irs.uni-stuttgart.de/fsfw/fsfw.git fsfw + ``` + +2. Add the following directive inside the uppermost `CMakeLists.txt` file of your project + + ```cmake + add_subdirectory(fsfw) + ``` + +3. Make sure to provide a configuration folder and supply the path to that folder with + the `FSFW_CONFIG_PATH` CMake variable from the uppermost `CMakeLists.txt` file. + It is also necessary to provide the `printChar` function. You can find an example + implementation for a hosted build + [here](https://egit.irs.uni-stuttgart.de/fsfw/fsfw-example-hosted/src/branch/master/bsp_hosted/utility/printChar.c). + +4. Link against the FSFW library + + ```cmake + target_link_libraries( PRIVATE fsfw) + ``` + +5. It should now be possible use the FSFW as a static library from the user code. + +## Building the unittests + +The FSFW also has unittests which use the [Catch2 library](https://github.com/catchorg/Catch2). +These are built by setting the CMake option `FSFW_BUILD_UNITTESTS` to `ON` or `TRUE` +from your project `CMakeLists.txt` file or from the command line. + +The fsfw-tests binary will be built as part of the static library and dropped alongside it inside +the `fsfw` folder of the build folder. + +If the unittests are built, the library and the tests will be built with coverage information by +default. This can be disabled by setting the `FSFW_TESTS_COV_GEN` option to `OFF` or `FALSE`. + +Coverage data in HTML format can be generated using the `CodeCoverage` +[CMake module](https://github.com/bilke/cmake-modules/tree/master). +To build the unittests, run them and then generare the coverage data in this format, +the following command can be used inside the build directory after the build system was set up + +```sh +cmake --build . -- fsfw-tests_coverage -j +``` + +The `coverage.py` script located in the `script` folder can also be used to do this conveniently. ## Index diff --git a/scripts/coverage.py b/scripts/coverage.py new file mode 100755 index 00000000..d15c3154 --- /dev/null +++ b/scripts/coverage.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -* +"""Small portable helper script to generate LCOV HTML coverage data""" +import os +import platform +import sys +import time +import argparse +from typing import List + + +"""Copy this helper script into your project folder. It will try to determine a CMake build folder +and then attempt to build your project with coverage information. + +See Unittest documentation at https://egit.irs.uni-stuttgart.de/fsfw/fsfw for more +information how to set up the build folder. +""" +def main(): + + parser = argparse.ArgumentParser(description="Processing arguments for LCOV helper script.") + + build_dir_list = [] + for directory in os.listdir("."): + if os.path.isdir(directory): + os.chdir(directory) + check_for_cmake_build_dir(build_dir_list) + os.chdir("..") + + if len(build_dir_list) == 0: + print("No valid CMake build directory found. Trying to set up hosted build") + build_directory = 'build-Debug-Host' + os.mkdir(build_directory) + os.chdir(build_directory) + os.system('cmake -DFSFW_OSAL=host -DFSFW_BUILD_UNITTESTS=ON ..') + os.chdir('..') + elif len(build_dir_list) == 1: + build_directory = build_dir_list[0] + else: + print("Multiple build directories found!") + build_directory = determine_build_dir(build_dir_list) + perform_lcov_operation(build_directory) + + +def check_for_cmake_build_dir(build_dir_dict: list): + if os.path.isfile("CMakeCache.txt"): + build_dir_dict.append(os.getcwd()) + + +def perform_lcov_operation(directory): + os.chdir(directory) + os.system("cmake --build . -- fsfw-tests_coverage -j") + + +def determine_build_dir(build_dir_list: List[str]): + build_directory = "" + for idx, directory in enumerate(build_dir_list): + print(f"{idx + 1}: {directory}") + while True: + idx = input("Pick the directory to perform LCOV HTML generation by index: ") + if not idx.isdigit(): + print("Invalid input!") + continue + + idx = int(idx) + if idx > len(build_dir_list) or idx < 1: + print("Invalid input!") + continue + build_directory = build_dir_list[idx - 1] + break + return build_directory + + +if __name__ == "__main__": + main() diff --git a/tests/src/fsfw_tests/CMakeLists.txt b/tests/src/fsfw_tests/CMakeLists.txt index e4a6be80..80efdeaf 100644 --- a/tests/src/fsfw_tests/CMakeLists.txt +++ b/tests/src/fsfw_tests/CMakeLists.txt @@ -3,6 +3,6 @@ if(FSFW_ADD_INTERNAL_TESTS) add_subdirectory(internal) endif() -if(FSFW_ADD_UNITTESTS) +if(FSFW_BUILD_UNITTESTS) add_subdirectory(unit) endif() diff --git a/tests/src/fsfw_tests/internal/InternalUnitTester.cpp b/tests/src/fsfw_tests/internal/InternalUnitTester.cpp index 20998d64..3c8eec1e 100644 --- a/tests/src/fsfw_tests/internal/InternalUnitTester.cpp +++ b/tests/src/fsfw_tests/internal/InternalUnitTester.cpp @@ -1,9 +1,9 @@ #include "fsfw_tests/internal/InternalUnitTester.h" #include "fsfw_tests/internal/UnittDefinitions.h" -#include "fsfw_tests/internal/osal/IntTestMq.h" -#include "fsfw_tests/internal/osal/IntTestSemaphore.h" -#include "fsfw_tests/internal/osal/IntTestMutex.h" +#include "fsfw_tests/internal/osal/testMq.h" +#include "fsfw_tests/internal/osal/testSemaphore.h" +#include "fsfw_tests/internal/osal/testMutex.h" #include "fsfw_tests/internal/serialize/IntTestSerialization.h" #include "fsfw_tests/internal/globalfunctions/TestArrayPrinter.h" diff --git a/tests/src/fsfw_tests/internal/osal/CMakeLists.txt b/tests/src/fsfw_tests/internal/osal/CMakeLists.txt index 84316089..8d79d759 100644 --- a/tests/src/fsfw_tests/internal/osal/CMakeLists.txt +++ b/tests/src/fsfw_tests/internal/osal/CMakeLists.txt @@ -1,5 +1,5 @@ target_sources(${LIB_FSFW_NAME} PRIVATE - IntTestMq.cpp - IntTestMutex.cpp - IntTestSemaphore.cpp + testMq.cpp + testMutex.cpp + testSemaphore.cpp ) diff --git a/tests/src/fsfw_tests/internal/osal/testCmdExecutor.cpp b/tests/src/fsfw_tests/internal/osal/testCmdExecutor.cpp new file mode 100644 index 00000000..f0bed8ad --- /dev/null +++ b/tests/src/fsfw_tests/internal/osal/testCmdExecutor.cpp @@ -0,0 +1 @@ +#include "testCmdExecutor.h" diff --git a/tests/src/fsfw_tests/internal/osal/testCmdExecutor.h b/tests/src/fsfw_tests/internal/osal/testCmdExecutor.h new file mode 100644 index 00000000..4779dde9 --- /dev/null +++ b/tests/src/fsfw_tests/internal/osal/testCmdExecutor.h @@ -0,0 +1,10 @@ +#ifndef FSFW_TESTS_SRC_FSFW_TESTS_INTERNAL_OSAL_TESTCMDEXECUTOR_H_ +#define FSFW_TESTS_SRC_FSFW_TESTS_INTERNAL_OSAL_TESTCMDEXECUTOR_H_ + +namespace testcmdexec { + +} + + + +#endif /* FSFW_TESTS_SRC_FSFW_TESTS_INTERNAL_OSAL_TESTCMDEXECUTOR_H_ */ diff --git a/tests/src/fsfw_tests/internal/osal/IntTestMq.cpp b/tests/src/fsfw_tests/internal/osal/testMq.cpp similarity index 96% rename from tests/src/fsfw_tests/internal/osal/IntTestMq.cpp rename to tests/src/fsfw_tests/internal/osal/testMq.cpp index 6c31b354..8a252910 100644 --- a/tests/src/fsfw_tests/internal/osal/IntTestMq.cpp +++ b/tests/src/fsfw_tests/internal/osal/testMq.cpp @@ -1,4 +1,4 @@ -#include "fsfw_tests/internal/osal/IntTestMq.h" +#include "testMq.h" #include "fsfw_tests/internal/UnittDefinitions.h" #include diff --git a/tests/src/fsfw_tests/internal/osal/IntTestMq.h b/tests/src/fsfw_tests/internal/osal/testMq.h similarity index 100% rename from tests/src/fsfw_tests/internal/osal/IntTestMq.h rename to tests/src/fsfw_tests/internal/osal/testMq.h diff --git a/tests/src/fsfw_tests/internal/osal/IntTestMutex.cpp b/tests/src/fsfw_tests/internal/osal/testMutex.cpp similarity index 96% rename from tests/src/fsfw_tests/internal/osal/IntTestMutex.cpp rename to tests/src/fsfw_tests/internal/osal/testMutex.cpp index d9184cd8..9b50121a 100644 --- a/tests/src/fsfw_tests/internal/osal/IntTestMutex.cpp +++ b/tests/src/fsfw_tests/internal/osal/testMutex.cpp @@ -1,4 +1,4 @@ -#include "fsfw_tests/internal/osal/IntTestMutex.h" +#include "testMutex.h" #include "fsfw_tests/internal/UnittDefinitions.h" #include "fsfw/platform.h" diff --git a/tests/src/fsfw_tests/internal/osal/IntTestMutex.h b/tests/src/fsfw_tests/internal/osal/testMutex.h similarity index 100% rename from tests/src/fsfw_tests/internal/osal/IntTestMutex.h rename to tests/src/fsfw_tests/internal/osal/testMutex.h diff --git a/tests/src/fsfw_tests/internal/osal/IntTestSemaphore.cpp b/tests/src/fsfw_tests/internal/osal/testSemaphore.cpp similarity index 98% rename from tests/src/fsfw_tests/internal/osal/IntTestSemaphore.cpp rename to tests/src/fsfw_tests/internal/osal/testSemaphore.cpp index 4b28f961..458dcb04 100644 --- a/tests/src/fsfw_tests/internal/osal/IntTestSemaphore.cpp +++ b/tests/src/fsfw_tests/internal/osal/testSemaphore.cpp @@ -1,5 +1,5 @@ #include "fsfw/FSFW.h" -#include "fsfw_tests/internal/osal/IntTestSemaphore.h" +#include "testSemaphore.h" #include "fsfw_tests/internal/UnittDefinitions.h" #include "fsfw/tasks/SemaphoreFactory.h" diff --git a/tests/src/fsfw_tests/internal/osal/IntTestSemaphore.h b/tests/src/fsfw_tests/internal/osal/testSemaphore.h similarity index 100% rename from tests/src/fsfw_tests/internal/osal/IntTestSemaphore.h rename to tests/src/fsfw_tests/internal/osal/testSemaphore.h diff --git a/tests/src/fsfw_tests/unit/CMakeLists.txt b/tests/src/fsfw_tests/unit/CMakeLists.txt index f30e4b6b..164e3bde 100644 --- a/tests/src/fsfw_tests/unit/CMakeLists.txt +++ b/tests/src/fsfw_tests/unit/CMakeLists.txt @@ -1,16 +1,17 @@ -target_sources(${TARGET_NAME} PRIVATE +target_sources(${FSFW_TEST_TGT} PRIVATE CatchDefinitions.cpp CatchFactory.cpp printChar.cpp ) -if(FSFW_CUSTOM_UNITTEST_RUNNER) - target_sources(${TARGET_NAME} PRIVATE +# if(FSFW_CUSTOM_UNITTEST_RUNNER) + target_sources(${FSFW_TEST_TGT} PRIVATE CatchRunner.cpp CatchSetup.cpp ) -endif() +# endif() +add_subdirectory(testcfg) add_subdirectory(action) add_subdirectory(container) add_subdirectory(osal) diff --git a/tests/src/fsfw_tests/unit/CatchFactory.h b/tests/src/fsfw_tests/unit/CatchFactory.h index 38ec46bd..cc14e3d9 100644 --- a/tests/src/fsfw_tests/unit/CatchFactory.h +++ b/tests/src/fsfw_tests/unit/CatchFactory.h @@ -1,7 +1,7 @@ #ifndef FSFW_CATCHFACTORY_H_ #define FSFW_CATCHFACTORY_H_ -#include "TestsConfig.h" +#include "tests/TestsConfig.h" #include "fsfw/objectmanager/SystemObjectIF.h" #include "fsfw/objectmanager/ObjectManager.h" diff --git a/tests/src/fsfw_tests/unit/CatchRunner.cpp b/tests/src/fsfw_tests/unit/CatchRunner.cpp index c96db7f4..1ea3ab35 100644 --- a/tests/src/fsfw_tests/unit/CatchRunner.cpp +++ b/tests/src/fsfw_tests/unit/CatchRunner.cpp @@ -14,7 +14,7 @@ extern int customSetup(); -int fsfwtest::customMain(int argc, char* argv[]) { +int main(int argc, char* argv[]) { customSetup(); // Catch internal function call diff --git a/tests/src/fsfw_tests/unit/CatchRunner.h b/tests/src/fsfw_tests/unit/CatchRunner.h index 720625c6..06ff07b6 100644 --- a/tests/src/fsfw_tests/unit/CatchRunner.h +++ b/tests/src/fsfw_tests/unit/CatchRunner.h @@ -7,7 +7,7 @@ namespace fsfwtest { * Can be called by upper level main() if default Catch2 main is overriden * @return */ -int customMain(int argc, char* argv[]); +//int customMain(int argc, char* argv[]); } diff --git a/tests/src/fsfw_tests/unit/action/CMakeLists.txt b/tests/src/fsfw_tests/unit/action/CMakeLists.txt index 0339000f..659f251a 100644 --- a/tests/src/fsfw_tests/unit/action/CMakeLists.txt +++ b/tests/src/fsfw_tests/unit/action/CMakeLists.txt @@ -1,3 +1,3 @@ -target_sources(${TARGET_NAME} PRIVATE +target_sources(${FSFW_TEST_TGT} PRIVATE TestActionHelper.cpp ) diff --git a/tests/src/fsfw_tests/unit/container/CMakeLists.txt b/tests/src/fsfw_tests/unit/container/CMakeLists.txt index 966c5834..5dae974c 100644 --- a/tests/src/fsfw_tests/unit/container/CMakeLists.txt +++ b/tests/src/fsfw_tests/unit/container/CMakeLists.txt @@ -1,4 +1,4 @@ -target_sources(${TARGET_NAME} PRIVATE +target_sources(${FSFW_TEST_TGT} PRIVATE RingBufferTest.cpp TestArrayList.cpp TestDynamicFifo.cpp diff --git a/tests/src/fsfw_tests/unit/datapoollocal/CMakeLists.txt b/tests/src/fsfw_tests/unit/datapoollocal/CMakeLists.txt index 1c98e7dc..bf465282 100644 --- a/tests/src/fsfw_tests/unit/datapoollocal/CMakeLists.txt +++ b/tests/src/fsfw_tests/unit/datapoollocal/CMakeLists.txt @@ -1,4 +1,4 @@ -target_sources(${TARGET_NAME} PRIVATE +target_sources(${FSFW_TEST_TGT} PRIVATE LocalPoolVariableTest.cpp LocalPoolVectorTest.cpp DataSetTest.cpp diff --git a/tests/src/fsfw_tests/unit/globalfunctions/CMakeLists.txt b/tests/src/fsfw_tests/unit/globalfunctions/CMakeLists.txt index 617c7f5a..209ce75f 100644 --- a/tests/src/fsfw_tests/unit/globalfunctions/CMakeLists.txt +++ b/tests/src/fsfw_tests/unit/globalfunctions/CMakeLists.txt @@ -1,3 +1,3 @@ -target_sources(${TARGET_NAME} PRIVATE +target_sources(${FSFW_TEST_TGT} PRIVATE testDleEncoder.cpp ) diff --git a/tests/src/fsfw_tests/unit/osal/CMakeLists.txt b/tests/src/fsfw_tests/unit/osal/CMakeLists.txt index 5ca5e400..293be2e8 100644 --- a/tests/src/fsfw_tests/unit/osal/CMakeLists.txt +++ b/tests/src/fsfw_tests/unit/osal/CMakeLists.txt @@ -1,4 +1,4 @@ -target_sources(${TARGET_NAME} PRIVATE +target_sources(${FSFW_TEST_TGT} PRIVATE TestMessageQueue.cpp TestSemaphore.cpp ) diff --git a/tests/src/fsfw_tests/unit/serialize/CMakeLists.txt b/tests/src/fsfw_tests/unit/serialize/CMakeLists.txt index 5a9d9a0f..96c80f4a 100644 --- a/tests/src/fsfw_tests/unit/serialize/CMakeLists.txt +++ b/tests/src/fsfw_tests/unit/serialize/CMakeLists.txt @@ -1,4 +1,4 @@ -target_sources(${TARGET_NAME} PRIVATE +target_sources(${FSFW_TEST_TGT} PRIVATE TestSerialBufferAdapter.cpp TestSerialization.cpp TestSerialLinkedPacket.cpp diff --git a/tests/src/fsfw_tests/unit/storagemanager/CMakeLists.txt b/tests/src/fsfw_tests/unit/storagemanager/CMakeLists.txt index ed7be7d5..7b6280df 100644 --- a/tests/src/fsfw_tests/unit/storagemanager/CMakeLists.txt +++ b/tests/src/fsfw_tests/unit/storagemanager/CMakeLists.txt @@ -1,4 +1,4 @@ -target_sources(${TARGET_NAME} PRIVATE +target_sources(${FSFW_TEST_TGT} PRIVATE TestNewAccessor.cpp TestPool.cpp ) diff --git a/tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt b/tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt new file mode 100644 index 00000000..3272958a --- /dev/null +++ b/tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt @@ -0,0 +1,28 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE + ipc/MissionMessageTypes.cpp + pollingsequence/PollingSequenceFactory.cpp +) + +# Add include paths for the executable +target_include_directories(${FSFW_TEST_TGT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} +) + +# These translation files are actually not that relevant for the tests. However, the FSFW tests +# compile against a user-configured variant of the FSFW, which might be configured to include +# translation information. Therefore, empty dummy translation files are compiled here +# so the tests compile in any case. + +# If a special translation file for object IDs exists, compile it. +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/objects/translateObjects.cpp") + target_sources(${FSFW_TEST_TGT} PRIVATE + objects/translateObjects.cpp + ) +endif() + +# If a special translation file for events exists, compile it. +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/objects/translateObjects.cpp") + target_sources(${FSFW_TEST_TGT} PRIVATE + events/translateEvents.cpp + ) +endif() \ No newline at end of file diff --git a/tests/user/testcfg/FSFWConfig.h.in b/tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in similarity index 67% rename from tests/user/testcfg/FSFWConfig.h.in rename to tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in index d38f0648..d03ec3e5 100644 --- a/tests/user/testcfg/FSFWConfig.h.in +++ b/tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in @@ -7,33 +7,30 @@ //! Used to determine whether C++ ostreams are used which can increase //! the binary size significantly. If this is disabled, //! the C stdio functions can be used alternatively -#define FSFW_CPP_OSTREAM_ENABLED 0 +#define FSFW_CPP_OSTREAM_ENABLED 0 -//! More FSFW related printouts. Useful for development. -#define FSFW_ENHANCED_PRINTOUT 0 +//! More FSFW related printouts depending on level. Useful for development. +#define FSFW_VERBOSE_LEVEL 1 //! Can be used to completely disable printouts, even the C stdio ones. -//! By default, printouts will be disabled for the unit tests. -#if FSFW_CPP_OSTREAM_ENABLED == 0 && FSFW_ENHANCED_PRINTOUT == 0 - #ifndef FSFW_DISABLE_PRINTOUT - #define FSFW_DISABLE_PRINTOUT 1 - #endif +#if FSFW_CPP_OSTREAM_ENABLED == 0 && FSFW_VERBOSE_LEVEL == 0 + #define FSFW_DISABLE_PRINTOUT 0 #endif -//! Can be used to enable additional debugging printouts for developing the FSFW -#define FSFW_PRINT_VERBOSITY_LEVEL 0 +#define FSFW_USE_PUS_C_TELEMETRY 1 +#define FSFW_USE_PUS_C_TELECOMMANDS 1 //! Can be used to disable the ANSI color sequences for C stdio. -#define FSFW_COLORED_OUTPUT 0 +#define FSFW_COLORED_OUTPUT 1 //! If FSFW_OBJ_EVENT_TRANSLATION is set to one, //! additional output which requires the translation files translateObjects //! and translateEvents (and their compiled source files) -#define FSFW_OBJ_EVENT_TRANSLATION 0 +#define FSFW_OBJ_EVENT_TRANSLATION 0 #if FSFW_OBJ_EVENT_TRANSLATION == 1 //! Specify whether info events are printed too. -#define FSFW_DEBUG_INFO 1 +#define FSFW_DEBUG_INFO 1 #include "objects/translateObjects.h" #include "events/translateEvents.h" #else @@ -41,22 +38,22 @@ //! When using the newlib nano library, C99 support for stdio facilities //! will not be provided. This define should be set to 1 if this is the case. -#define FSFW_NO_C99_IO 1 +#define FSFW_NO_C99_IO 1 //! Specify whether a special mode store is used for Subsystem components. -#define FSFW_USE_MODESTORE 0 +#define FSFW_USE_MODESTORE 0 //! Defines if the real time scheduler for linux should be used. //! If set to 0, this will also disable priority settings for linux //! as most systems will not allow to set nice values without privileges //! For embedded linux system set this to 1. //! If set to 1 the binary needs "cap_sys_nice=eip" privileges to run -#define FSFW_USE_REALTIME_FOR_LINUX 1 +#define FSFW_USE_REALTIME_FOR_LINUX 1 namespace fsfwconfig { -//! Default timestamp size. The default timestamp will be an eight byte CDC -//! short timestamp. -static constexpr uint8_t FSFW_MISSION_TIMESTAMP_SIZE = 8; + +//! Default timestamp size. The default timestamp will be an seven byte CDC short timestamp. +static constexpr uint8_t FSFW_MISSION_TIMESTAMP_SIZE = 7; //! Configure the allocated pool sizes for the event manager. static constexpr size_t FSFW_EVENTMGMR_MATCHTREE_NODES = 240; @@ -65,13 +62,13 @@ static constexpr size_t FSFW_EVENTMGMR_RANGEMATCHERS = 120; //! Defines the FIFO depth of each commanding service base which //! also determines how many commands a CSB service can handle in one cycle -//! simulataneously. This will increase the required RAM for +//! simultaneously. This will increase the required RAM for //! each CSB service ! static constexpr uint8_t FSFW_CSB_FIFO_DEPTH = 6; static constexpr size_t FSFW_PRINT_BUFFER_SIZE = 124; -static constexpr size_t FSFW_MAX_TM_PACKET_SIZE = 1500; +static constexpr size_t FSFW_MAX_TM_PACKET_SIZE = 2048; } diff --git a/tests/src/fsfw_tests/unit/testcfg/OBSWConfig.h.in b/tests/src/fsfw_tests/unit/testcfg/OBSWConfig.h.in new file mode 100644 index 00000000..5d8a9255 --- /dev/null +++ b/tests/src/fsfw_tests/unit/testcfg/OBSWConfig.h.in @@ -0,0 +1,15 @@ +#ifndef CONFIG_TMTC_TMTCSIZE_H_ +#define CONFIG_TMTC_TMTCSIZE_H_ + +#include +#include + +#define OBSW_PRINT_MISSED_DEADLINES 0 +#define OBSW_VERBOSE_LEVEL 0 +#define OBSW_ADD_TEST_CODE 1 + +namespace config { +static constexpr uint32_t MAX_STORED_TELECOMMANDS = 2000; +} + +#endif /* CONFIG_TMTC_TMTCSIZE_H_ */ diff --git a/tests/user/testcfg/TestsConfig.h.in b/tests/src/fsfw_tests/unit/testcfg/TestsConfig.h.in similarity index 100% rename from tests/user/testcfg/TestsConfig.h.in rename to tests/src/fsfw_tests/unit/testcfg/TestsConfig.h.in diff --git a/tests/user/testcfg/devices/logicalAddresses.cpp b/tests/src/fsfw_tests/unit/testcfg/devices/logicalAddresses.cpp similarity index 100% rename from tests/user/testcfg/devices/logicalAddresses.cpp rename to tests/src/fsfw_tests/unit/testcfg/devices/logicalAddresses.cpp diff --git a/tests/user/testcfg/devices/logicalAddresses.h b/tests/src/fsfw_tests/unit/testcfg/devices/logicalAddresses.h similarity index 84% rename from tests/user/testcfg/devices/logicalAddresses.h rename to tests/src/fsfw_tests/unit/testcfg/devices/logicalAddresses.h index cdf87025..a0240037 100644 --- a/tests/user/testcfg/devices/logicalAddresses.h +++ b/tests/src/fsfw_tests/unit/testcfg/devices/logicalAddresses.h @@ -2,7 +2,8 @@ #define CONFIG_DEVICES_LOGICALADDRESSES_H_ #include -#include +#include "common/devices/commonAddresses.h" + #include namespace addresses { diff --git a/tests/user/testcfg/devices/powerSwitcherList.cpp b/tests/src/fsfw_tests/unit/testcfg/devices/powerSwitcherList.cpp similarity index 100% rename from tests/user/testcfg/devices/powerSwitcherList.cpp rename to tests/src/fsfw_tests/unit/testcfg/devices/powerSwitcherList.cpp diff --git a/tests/user/testcfg/devices/powerSwitcherList.h b/tests/src/fsfw_tests/unit/testcfg/devices/powerSwitcherList.h similarity index 100% rename from tests/user/testcfg/devices/powerSwitcherList.h rename to tests/src/fsfw_tests/unit/testcfg/devices/powerSwitcherList.h diff --git a/tests/user/testcfg/events/subsystemIdRanges.h b/tests/src/fsfw_tests/unit/testcfg/events/subsystemIdRanges.h similarity index 64% rename from tests/user/testcfg/events/subsystemIdRanges.h rename to tests/src/fsfw_tests/unit/testcfg/events/subsystemIdRanges.h index 24eee819..c9c7c20d 100644 --- a/tests/user/testcfg/events/subsystemIdRanges.h +++ b/tests/src/fsfw_tests/unit/testcfg/events/subsystemIdRanges.h @@ -1,8 +1,10 @@ #ifndef CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_ #define CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_ +#include "fsfw/events/fwSubsystemIdRanges.h" +#include "common/events/commonSubsystemIds.h" #include -#include + /** * @brief Custom subsystem IDs can be added here @@ -11,7 +13,8 @@ */ namespace SUBSYSTEM_ID { enum: uint8_t { - SUBSYSTEM_ID_START = FW_SUBSYSTEM_ID_RANGE, + SUBSYSTEM_ID_START = COMMON_SUBSYSTEM_ID_RANGE, + SUBSYSTEM_ID_END // [EXPORT] : [END] }; } diff --git a/tests/src/fsfw_tests/unit/testcfg/events/translateEvents.cpp b/tests/src/fsfw_tests/unit/testcfg/events/translateEvents.cpp new file mode 100644 index 00000000..47186727 --- /dev/null +++ b/tests/src/fsfw_tests/unit/testcfg/events/translateEvents.cpp @@ -0,0 +1,15 @@ +/** + * @brief Auto-generated event translation file. Contains 81 translations. + * @details + * Generated on: 2021-05-18 16:28:16 + */ +#include "translateEvents.h" + + +const char * translateEvents(Event event) { + switch( (event & 0xffff) ) { + default: + return "UNKNOWN_EVENT"; + } + return 0; +} diff --git a/tests/src/fsfw_tests/unit/testcfg/events/translateEvents.h b/tests/src/fsfw_tests/unit/testcfg/events/translateEvents.h new file mode 100644 index 00000000..9034dcf2 --- /dev/null +++ b/tests/src/fsfw_tests/unit/testcfg/events/translateEvents.h @@ -0,0 +1,8 @@ +#ifndef FSFWCONFIG_EVENTS_TRANSLATEEVENTS_H_ +#define FSFWCONFIG_EVENTS_TRANSLATEEVENTS_H_ + +#include + +const char * translateEvents(Event event); + +#endif /* FSFWCONFIG_EVENTS_TRANSLATEEVENTS_H_ */ diff --git a/tests/user/testcfg/ipc/MissionMessageTypes.cpp b/tests/src/fsfw_tests/unit/testcfg/ipc/MissionMessageTypes.cpp similarity index 100% rename from tests/user/testcfg/ipc/MissionMessageTypes.cpp rename to tests/src/fsfw_tests/unit/testcfg/ipc/MissionMessageTypes.cpp diff --git a/tests/user/testcfg/ipc/MissionMessageTypes.h b/tests/src/fsfw_tests/unit/testcfg/ipc/MissionMessageTypes.h similarity index 100% rename from tests/user/testcfg/ipc/MissionMessageTypes.h rename to tests/src/fsfw_tests/unit/testcfg/ipc/MissionMessageTypes.h diff --git a/tests/user/testcfg/objects/systemObjectList.h b/tests/src/fsfw_tests/unit/testcfg/objects/systemObjectList.h similarity index 84% rename from tests/user/testcfg/objects/systemObjectList.h rename to tests/src/fsfw_tests/unit/testcfg/objects/systemObjectList.h index efd21e0d..bd0daa62 100644 --- a/tests/user/testcfg/objects/systemObjectList.h +++ b/tests/src/fsfw_tests/unit/testcfg/objects/systemObjectList.h @@ -1,8 +1,9 @@ #ifndef HOSTED_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ #define HOSTED_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ +#include "fsfw/objectmanager/frameworkObjects.h" +#include "common/objects/commonObjectsList.h" #include -#include // The objects will be instantiated in the ID order namespace objects { @@ -11,10 +12,6 @@ namespace objects { FSFW_CONFIG_RESERVED_START = PUS_SERVICE_1_VERIFICATION, FSFW_CONFIG_RESERVED_END = TM_STORE, - CCSDS_DISTRIBUTOR = 10, - PUS_DISTRIBUTOR = 11, - TM_FUNNEL = 12, - UDP_BRIDGE = 15, UDP_POLLING_TASK = 16, diff --git a/tests/src/fsfw_tests/unit/testcfg/objects/translateObjects.cpp b/tests/src/fsfw_tests/unit/testcfg/objects/translateObjects.cpp new file mode 100644 index 00000000..63636ced --- /dev/null +++ b/tests/src/fsfw_tests/unit/testcfg/objects/translateObjects.cpp @@ -0,0 +1,19 @@ +/** + * @brief Auto-generated object translation file. + * @details + * Contains 69 translations. + * Generated on: 2021-05-18 16:37:37 + */ +#include "translateObjects.h" + +const char *NO_OBJECT_STRING = "NO_OBJECT"; + +const char* translateObject(object_id_t object) { + switch( (object & 0xFFFFFFFF) ) { + case 0xFFFFFFFF: + return NO_OBJECT_STRING; + default: + return "UNKNOWN_OBJECT"; + } + return 0; +} diff --git a/tests/src/fsfw_tests/unit/testcfg/objects/translateObjects.h b/tests/src/fsfw_tests/unit/testcfg/objects/translateObjects.h new file mode 100644 index 00000000..dbf5b468 --- /dev/null +++ b/tests/src/fsfw_tests/unit/testcfg/objects/translateObjects.h @@ -0,0 +1,8 @@ +#ifndef FSFWCONFIG_OBJECTS_TRANSLATEOBJECTS_H_ +#define FSFWCONFIG_OBJECTS_TRANSLATEOBJECTS_H_ + +#include + +const char* translateObject(object_id_t object); + +#endif /* FSFWCONFIG_OBJECTS_TRANSLATEOBJECTS_H_ */ diff --git a/tests/user/testcfg/pollingsequence/PollingSequenceFactory.cpp b/tests/src/fsfw_tests/unit/testcfg/pollingsequence/PollingSequenceFactory.cpp similarity index 97% rename from tests/user/testcfg/pollingsequence/PollingSequenceFactory.cpp rename to tests/src/fsfw_tests/unit/testcfg/pollingsequence/PollingSequenceFactory.cpp index e3ee874a..1d29ef86 100644 --- a/tests/user/testcfg/pollingsequence/PollingSequenceFactory.cpp +++ b/tests/src/fsfw_tests/unit/testcfg/pollingsequence/PollingSequenceFactory.cpp @@ -1,6 +1,6 @@ #include "PollingSequenceFactory.h" -#include +#include "tests/TestsConfig.h" #include #include diff --git a/tests/user/testcfg/pollingsequence/PollingSequenceFactory.h b/tests/src/fsfw_tests/unit/testcfg/pollingsequence/PollingSequenceFactory.h similarity index 100% rename from tests/user/testcfg/pollingsequence/PollingSequenceFactory.h rename to tests/src/fsfw_tests/unit/testcfg/pollingsequence/PollingSequenceFactory.h diff --git a/tests/user/testcfg/returnvalues/classIds.h b/tests/src/fsfw_tests/unit/testcfg/returnvalues/classIds.h similarity index 76% rename from tests/user/testcfg/returnvalues/classIds.h rename to tests/src/fsfw_tests/unit/testcfg/returnvalues/classIds.h index 606cc60b..919b9628 100644 --- a/tests/user/testcfg/returnvalues/classIds.h +++ b/tests/src/fsfw_tests/unit/testcfg/returnvalues/classIds.h @@ -1,7 +1,8 @@ #ifndef CONFIG_RETURNVALUES_CLASSIDS_H_ #define CONFIG_RETURNVALUES_CLASSIDS_H_ -#include +#include "common/returnvalues/commonClassIds.h" +#include "fsfw/returnvalues/FwClassIds.h" /** * @brief CLASS_ID defintions which are required for custom returnvalues. diff --git a/tests/user/testcfg/tmtc/apid.h b/tests/src/fsfw_tests/unit/testcfg/tmtc/apid.h similarity index 90% rename from tests/user/testcfg/tmtc/apid.h rename to tests/src/fsfw_tests/unit/testcfg/tmtc/apid.h index c0231bca..0e633afb 100644 --- a/tests/user/testcfg/tmtc/apid.h +++ b/tests/src/fsfw_tests/unit/testcfg/tmtc/apid.h @@ -12,6 +12,7 @@ */ namespace apid { static const uint16_t DEFAULT_APID = 0x00; + static const uint16_t SOURCE_OBSW = 0x73; } diff --git a/tests/user/testcfg/tmtc/pusIds.h b/tests/src/fsfw_tests/unit/testcfg/tmtc/pusIds.h similarity index 100% rename from tests/user/testcfg/tmtc/pusIds.h rename to tests/src/fsfw_tests/unit/testcfg/tmtc/pusIds.h diff --git a/tests/src/fsfw_tests/unit/timemanager/CMakeLists.txt b/tests/src/fsfw_tests/unit/timemanager/CMakeLists.txt index 2c635711..6ce1c6c6 100644 --- a/tests/src/fsfw_tests/unit/timemanager/CMakeLists.txt +++ b/tests/src/fsfw_tests/unit/timemanager/CMakeLists.txt @@ -1,3 +1,3 @@ -target_sources(${TARGET_NAME} PRIVATE +target_sources(${FSFW_TEST_TGT} PRIVATE TestCountdown.cpp ) diff --git a/tests/src/fsfw_tests/unit/tmtcpacket/CMakeLists.txt b/tests/src/fsfw_tests/unit/tmtcpacket/CMakeLists.txt index a1a4c1b6..36838b24 100644 --- a/tests/src/fsfw_tests/unit/tmtcpacket/CMakeLists.txt +++ b/tests/src/fsfw_tests/unit/tmtcpacket/CMakeLists.txt @@ -1,3 +1,3 @@ -target_sources(${TARGET_NAME} PRIVATE +target_sources(${FSFW_TEST_TGT} PRIVATE PusTmTest.cpp ) diff --git a/tests/user/README.md b/tests/user/README.md deleted file mode 100644 index d6a4bb85..00000000 --- a/tests/user/README.md +++ /dev/null @@ -1,19 +0,0 @@ -## FSFW Testing - -This folder contains testing and unit testing components. - -### Instructions - -The easiest way to run the unittest contained in this folder is to follow -the steps in the [test repository](https://egit.irs.uni-stuttgart.de/fsfw/fsfw_tests). -This is recommended even if the goal is to set up a custom test repository to have -a starting point. - -To set up a custom test repository or project, following steps can be performed: - -1. Copy the user folder content into the project root. -2. Clone [Catch2](https://github.com/catchorg/Catch2) in the project root. -3. Use the `CMakeLists.txt` as a starting point to add tests and build the test - executable. - - diff --git a/tests/user/testcfg/CMakeLists.txt b/tests/user/testcfg/CMakeLists.txt deleted file mode 100644 index dbf0256f..00000000 --- a/tests/user/testcfg/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -target_sources(${TARGET_NAME} - PRIVATE - ipc/MissionMessageTypes.cpp - pollingsequence/PollingSequenceFactory.cpp -) - -# Add include paths for the executable -target_include_directories(${TARGET_NAME} - PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR} -) diff --git a/tests/user/testcfg/OBSWConfig.h.in b/tests/user/testcfg/OBSWConfig.h.in deleted file mode 100644 index 34eda31f..00000000 --- a/tests/user/testcfg/OBSWConfig.h.in +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef TESTCFG_OBSWCONFIG_H_ -#define TESTCFG_OBSWCONFIG_H_ - - - - - -#endif /* TESTCFG_OBSWCONFIG_H_ */ From cd6d616806d55c665152485d2521ec4d3919e2db Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 7 Oct 2021 13:26:31 +0200 Subject: [PATCH 14/49] using .h.in version fle now --- src/fsfw/FSFWVersion.h | 10 ---------- src/fsfw/FSFWVersion.h.in | 11 +++++++++++ 2 files changed, 11 insertions(+), 10 deletions(-) delete mode 100644 src/fsfw/FSFWVersion.h create mode 100644 src/fsfw/FSFWVersion.h.in diff --git a/src/fsfw/FSFWVersion.h b/src/fsfw/FSFWVersion.h deleted file mode 100644 index c581a85c..00000000 --- a/src/fsfw/FSFWVersion.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef FSFW_VERSION_H_ -#define FSFW_VERSION_H_ - -const char* const FSFW_VERSION_NAME = "ASTP"; - -#define FSFW_VERSION 2 -#define FSFW_SUBVERSION 0 -#define FSFW_REVISION 0 - -#endif /* FSFW_VERSION_H_ */ diff --git a/src/fsfw/FSFWVersion.h.in b/src/fsfw/FSFWVersion.h.in new file mode 100644 index 00000000..a858d703 --- /dev/null +++ b/src/fsfw/FSFWVersion.h.in @@ -0,0 +1,11 @@ +#ifndef FSFW_VERSION_H_ +#define FSFW_VERSION_H_ + +const char* const FSFW_VERSION_NAME = "ASTP"; + +// Versioning is kept in project CMakeLists.txt file +#define FSFW_VERSION @FSFW_VERSION@ +#define FSFW_SUBVERSION @FSFW_SUBVERSION@ +#define FSFW_REVISION @FSFW_REVISION@ + +#endif /* FSFW_VERSION_H_ */ From dd1631a45623dc8cc3c96e1708f558bd1b4d0089 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 7 Oct 2021 14:20:34 +0200 Subject: [PATCH 15/49] updated CMakeLists.txt - More information about FSFW build --- CMakeLists.txt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ff631201..fd6850a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,7 @@ set(FSFW_TEST_TGT fsfw-tests) add_library(${LIB_FSFW_NAME}) if(FSFW_BUILD_UNITTESTS) + message(STATUS "Building the FSFW unittests in addition to the static library") # Check whether the user has already installed Catch2 first find_package(Catch2 3) # Not installed, so use FetchContent to download and provide Catch2 @@ -61,12 +62,17 @@ if(FSFW_BUILD_UNITTESTS) add_executable(${FSFW_TEST_TGT}) if(FSFW_TESTS_GEN_COV) + message(STATUS "Generating coverage data for the library") + message(STATUS "Targets linking against ${LIB_FSFW_NAME} " + "will be compiled with coverage data as well" + ) include(FetchContent) FetchContent_Declare( cmake-modules GIT_REPOSITORY https://github.com/bilke/cmake-modules.git ) FetchContent_MakeAvailable(cmake-modules) + set(CMAKE_BUILD_TYPE "Debug") list(APPEND CMAKE_MODULE_PATH ${cmake-modules_SOURCE_DIR}) include(CodeCoverage) endif() @@ -190,6 +196,11 @@ if(FSFW_BUILD_UNITTESTS) -fprofile-arcs -ftest-coverage ) + # Need to specify this as an interface, otherwise there will the compile issues + target_link_options(${LIB_FSFW_NAME} INTERFACE + -fprofile-arcs + -ftest-coverage + ) if(WIN32) setup_target_for_coverage_gcovr_html( @@ -302,3 +313,16 @@ target_compile_options(${LIB_FSFW_NAME} PRIVATE target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${FSFW_ADDITIONAL_LINK_LIBS} ) + +string(CONCAT POST_BUILD_COMMENT + "######################################################################\n" + "Building FSFW v${FSFW_VERSION}.${FSFW_SUBVERSION}.${FSFW_REVISION}, " + "Target OSAL: ${FSFW_OS_NAME}\n" + "######################################################################\n" +) + +add_custom_command( + TARGET ${LIB_FSFW_NAME} + POST_BUILD + COMMENT ${POST_BUILD_COMMENT} +) From 6ad7f51297bff44f07543c3875481388460a8179 Mon Sep 17 00:00:00 2001 From: Jakob Meier Date: Fri, 8 Oct 2021 13:24:51 +0200 Subject: [PATCH 16/49] added bind call error string --- src/fsfw/osal/common/tcpipCommon.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/fsfw/osal/common/tcpipCommon.cpp b/src/fsfw/osal/common/tcpipCommon.cpp index 0fdbf867..2551496d 100644 --- a/src/fsfw/osal/common/tcpipCommon.cpp +++ b/src/fsfw/osal/common/tcpipCommon.cpp @@ -21,6 +21,9 @@ void tcpip::determineErrorStrings(Protocol protocol, ErrorSources errorSrc, std: if(errorSrc == ErrorSources::SETSOCKOPT_CALL) { srcString = "setsockopt call"; } + if(errorSrc == ErrorSources::BIND_CALL) { + srcString = "bind call"; + } else if(errorSrc == ErrorSources::SOCKET_CALL) { srcString = "socket call"; } From 9bcd701a50151491d3fe1b7d1c4d652556266cbd Mon Sep 17 00:00:00 2001 From: Jakob Meier Date: Fri, 8 Oct 2021 13:51:32 +0200 Subject: [PATCH 17/49] tcp server also parses TCs when client closes connection --- src/fsfw/osal/common/TcpTmTcServer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/fsfw/osal/common/TcpTmTcServer.cpp b/src/fsfw/osal/common/TcpTmTcServer.cpp index 8b34b1a3..7e6853fc 100644 --- a/src/fsfw/osal/common/TcpTmTcServer.cpp +++ b/src/fsfw/osal/common/TcpTmTcServer.cpp @@ -168,7 +168,10 @@ void TcpTmTcServer::handleServerOperation(socket_t& connSocket) { tcpConfig.tcpFlags ); if(retval == 0) { - // Client closed connection + size_t availableReadData = ringBuffer.getAvailableReadData(); + if(availableReadData > lastRingBufferSize) { + handleTcRingBufferData(availableReadData); + } return; } else if(retval > 0) { From ad3238aa19ecbab79743a5db38e33f370591e198 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 13:48:17 +0200 Subject: [PATCH 18/49] removed problematic includes --- tests/src/fsfw_tests/unit/testcfg/events/subsystemIdRanges.h | 3 +-- tests/src/fsfw_tests/unit/testcfg/returnvalues/classIds.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/src/fsfw_tests/unit/testcfg/events/subsystemIdRanges.h b/tests/src/fsfw_tests/unit/testcfg/events/subsystemIdRanges.h index c9c7c20d..b88cd875 100644 --- a/tests/src/fsfw_tests/unit/testcfg/events/subsystemIdRanges.h +++ b/tests/src/fsfw_tests/unit/testcfg/events/subsystemIdRanges.h @@ -2,7 +2,6 @@ #define CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_ #include "fsfw/events/fwSubsystemIdRanges.h" -#include "common/events/commonSubsystemIds.h" #include @@ -13,7 +12,7 @@ */ namespace SUBSYSTEM_ID { enum: uint8_t { - SUBSYSTEM_ID_START = COMMON_SUBSYSTEM_ID_RANGE, + SUBSYSTEM_ID_START = 0, SUBSYSTEM_ID_END // [EXPORT] : [END] }; } diff --git a/tests/src/fsfw_tests/unit/testcfg/returnvalues/classIds.h b/tests/src/fsfw_tests/unit/testcfg/returnvalues/classIds.h index 919b9628..1001d012 100644 --- a/tests/src/fsfw_tests/unit/testcfg/returnvalues/classIds.h +++ b/tests/src/fsfw_tests/unit/testcfg/returnvalues/classIds.h @@ -1,7 +1,6 @@ #ifndef CONFIG_RETURNVALUES_CLASSIDS_H_ #define CONFIG_RETURNVALUES_CLASSIDS_H_ -#include "common/returnvalues/commonClassIds.h" #include "fsfw/returnvalues/FwClassIds.h" /** From a827ec6a92b0cdf37138b084c182e7cd5cf866eb Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 13:51:08 +0200 Subject: [PATCH 19/49] removed another include --- tests/src/fsfw_tests/unit/testcfg/objects/systemObjectList.h | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/src/fsfw_tests/unit/testcfg/objects/systemObjectList.h b/tests/src/fsfw_tests/unit/testcfg/objects/systemObjectList.h index bd0daa62..accf0d81 100644 --- a/tests/src/fsfw_tests/unit/testcfg/objects/systemObjectList.h +++ b/tests/src/fsfw_tests/unit/testcfg/objects/systemObjectList.h @@ -2,7 +2,6 @@ #define HOSTED_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ #include "fsfw/objectmanager/frameworkObjects.h" -#include "common/objects/commonObjectsList.h" #include // The objects will be instantiated in the ID order From e02ac0509702af5056a5f3b9199a96001856c50b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 13:57:00 +0200 Subject: [PATCH 20/49] fixed a bug for default cfg path --- CMakeLists.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fd6850a0..192134fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -223,9 +223,10 @@ endif() # The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it. # If this is not given, we include the default configuration and emit a warning. if(NOT FSFW_CONFIG_PATH) - message(WARNING "Flight Software Framework configuration path not set!") - message(WARNING "Setting default configuration!") - add_subdirectory(defaultcfg/fsfwconfig) + message(WARNING "Flight Software Framework configuration path not set!") + set(DEF_CONF_PATH misc/defaultcfg/fsfwconfig) + message(WARNING "Setting default configuration from ${DEF_CONF_PATH} ..") + add_subdirectory(${DEF_CONF_PATH}) endif() # FSFW might be part of a possibly complicated folder structure, so we From c26c2a5a96e25ebb0b1352f0896a2ee456c7ae25 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 14:56:42 +0200 Subject: [PATCH 21/49] hardcoding config path --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 192134fd..847ea572 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,9 +56,8 @@ if(FSFW_BUILD_UNITTESTS) FetchContent_MakeAvailable(Catch2) endif() - configure_file(tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in tests/FSFWConfig.h) + set(FSFW_CONFIG_PATH tests/src/fsfw_tests/unit/testcfg) configure_file(tests/src/fsfw_tests/unit/testcfg/TestsConfig.h.in tests/TestsConfig.h) - configure_file(tests/src/fsfw_tests/unit/testcfg/OBSWConfig.h.in tests/OBSWConfig.h) add_executable(${FSFW_TEST_TGT}) if(FSFW_TESTS_GEN_COV) From ad117e07e0fb1875af3b4c960c724dc826348a02 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 15:03:03 +0200 Subject: [PATCH 22/49] FSFW_CONFIG_PATH update --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 847ea572..34f16d0f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -226,6 +226,7 @@ if(NOT FSFW_CONFIG_PATH) set(DEF_CONF_PATH misc/defaultcfg/fsfwconfig) message(WARNING "Setting default configuration from ${DEF_CONF_PATH} ..") add_subdirectory(${DEF_CONF_PATH}) + set(FSFW_CONFIG_PATH ${DEF_CONF_PATH}) endif() # FSFW might be part of a possibly complicated folder structure, so we From b00f61445d97b183456b5f778df32411002c745b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 15:07:52 +0200 Subject: [PATCH 23/49] works --- .gitignore | 2 ++ CMakeLists.txt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index fbd138e9..d6efb9cf 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ .project .settings .metadata + +/build* diff --git a/CMakeLists.txt b/CMakeLists.txt index 34f16d0f..5000b9b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,7 +57,9 @@ if(FSFW_BUILD_UNITTESTS) endif() set(FSFW_CONFIG_PATH tests/src/fsfw_tests/unit/testcfg) + configure_file(tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in FSFWConfig.h) configure_file(tests/src/fsfw_tests/unit/testcfg/TestsConfig.h.in tests/TestsConfig.h) + configure_file(tests/src/fsfw_tests/unit/testcfg/OBSWConfig.h.in OBSWConfig.h) add_executable(${FSFW_TEST_TGT}) if(FSFW_TESTS_GEN_COV) From 5798aa1e3abd55f94bc138ea26f93ef43644975b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 15:09:19 +0200 Subject: [PATCH 24/49] create project to suppress warning --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5000b9b0..eae1fc25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,7 @@ if(FSFW_BUILD_UNITTESTS) configure_file(tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in FSFWConfig.h) configure_file(tests/src/fsfw_tests/unit/testcfg/TestsConfig.h.in tests/TestsConfig.h) configure_file(tests/src/fsfw_tests/unit/testcfg/OBSWConfig.h.in OBSWConfig.h) + project(${FSFW_TEST_TGT} CXX C) add_executable(${FSFW_TEST_TGT}) if(FSFW_TESTS_GEN_COV) From 1b6fa9822b35ad63d7347f5f836c7f9212a42736 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 15:40:29 +0200 Subject: [PATCH 25/49] this should work --- scripts/coverage.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/coverage.py b/scripts/coverage.py index d15c3154..71b6fb03 100755 --- a/scripts/coverage.py +++ b/scripts/coverage.py @@ -20,6 +20,8 @@ def main(): parser = argparse.ArgumentParser(description="Processing arguments for LCOV helper script.") build_dir_list = [] + if not os.path.isfile('README.md'): + os.chdir('..') for directory in os.listdir("."): if os.path.isdir(directory): os.chdir(directory) From fb67df6d7f447e651eac1e02f81ca80028500678 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 15:45:37 +0200 Subject: [PATCH 26/49] using testsconfig.h now --- tests/src/fsfw_tests/unit/CatchFactory.cpp | 1 + tests/src/fsfw_tests/unit/datapoollocal/DataSetTest.cpp | 1 + tests/src/fsfw_tests/unit/datapoollocal/LocalPoolOwnerBase.h | 2 +- .../src/fsfw_tests/unit/datapoollocal/LocalPoolVariableTest.cpp | 1 + tests/src/fsfw_tests/unit/datapoollocal/LocalPoolVectorTest.cpp | 1 + tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt | 2 +- 6 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/src/fsfw_tests/unit/CatchFactory.cpp b/tests/src/fsfw_tests/unit/CatchFactory.cpp index 010ab5dd..42cb927e 100644 --- a/tests/src/fsfw_tests/unit/CatchFactory.cpp +++ b/tests/src/fsfw_tests/unit/CatchFactory.cpp @@ -1,4 +1,5 @@ #include "CatchFactory.h" +#include "tests/TestsConfig.h" #include "datapoollocal/LocalPoolOwnerBase.h" #include "mocks/HkReceiverMock.h" diff --git a/tests/src/fsfw_tests/unit/datapoollocal/DataSetTest.cpp b/tests/src/fsfw_tests/unit/datapoollocal/DataSetTest.cpp index 94b13f2f..c967b241 100644 --- a/tests/src/fsfw_tests/unit/datapoollocal/DataSetTest.cpp +++ b/tests/src/fsfw_tests/unit/datapoollocal/DataSetTest.cpp @@ -1,4 +1,5 @@ #include "LocalPoolOwnerBase.h" +#include "tests/TestsConfig.h" #include "fsfw_tests/unit/CatchDefinitions.h" #include diff --git a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolOwnerBase.h b/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolOwnerBase.h index ea5bb7e0..1f532568 100644 --- a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolOwnerBase.h +++ b/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolOwnerBase.h @@ -1,7 +1,7 @@ #ifndef FSFW_UNITTEST_TESTS_DATAPOOLLOCAL_LOCALPOOLOWNERBASE_H_ #define FSFW_UNITTEST_TESTS_DATAPOOLLOCAL_LOCALPOOLOWNERBASE_H_ -#include "objects/systemObjectList.h" +#include "tests/TestsConfig.h" #include "../mocks/MessageQueueMockBase.h" #include diff --git a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolVariableTest.cpp b/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolVariableTest.cpp index 648a76e2..b029ec26 100644 --- a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolVariableTest.cpp +++ b/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolVariableTest.cpp @@ -1,4 +1,5 @@ #include "LocalPoolOwnerBase.h" +#include "tests/TestsConfig.h" #include "fsfw_tests/unit/CatchDefinitions.h" #include diff --git a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolVectorTest.cpp b/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolVectorTest.cpp index 3f846dec..5298e5b9 100644 --- a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolVectorTest.cpp +++ b/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolVectorTest.cpp @@ -1,4 +1,5 @@ #include "LocalPoolOwnerBase.h" +#include "tests/TestsConfig.h" #include "fsfw_tests/unit/CatchDefinitions.h" #include diff --git a/tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt b/tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt index 3272958a..531972ac 100644 --- a/tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt +++ b/tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt @@ -4,7 +4,7 @@ target_sources(${FSFW_TEST_TGT} PRIVATE ) # Add include paths for the executable -target_include_directories(${FSFW_TEST_TGT} PUBLIC +target_include_directories(${FSFW_TEST_TGT} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ) From 6c75b56054c841b83a8057a0b99ff62337e5e654 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 15:51:27 +0200 Subject: [PATCH 27/49] README update --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a7ae0e20..eea403a1 100644 --- a/README.md +++ b/README.md @@ -83,12 +83,17 @@ The FSFW also has unittests which use the [Catch2 library](https://github.com/ca These are built by setting the CMake option `FSFW_BUILD_UNITTESTS` to `ON` or `TRUE` from your project `CMakeLists.txt` file or from the command line. -The fsfw-tests binary will be built as part of the static library and dropped alongside it inside -the `fsfw` folder of the build folder. - +The fsfw-tests binary will be built as part of the static library and dropped alongside it. If the unittests are built, the library and the tests will be built with coverage information by default. This can be disabled by setting the `FSFW_TESTS_COV_GEN` option to `OFF` or `FALSE`. +You can use the following commands inside the `fsfw` folder to set up the build system + +```sh +mkdir build-Unittest && cd build-Unittest +cmake -DFSFW_BUILD_UNITTESTS=ON .. +``` + Coverage data in HTML format can be generated using the `CodeCoverage` [CMake module](https://github.com/bilke/cmake-modules/tree/master). To build the unittests, run them and then generare the coverage data in this format, From ad744fb593a5ce70d1a365ffcda255bc1ead89f0 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 15:56:04 +0200 Subject: [PATCH 28/49] README improvement --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index eea403a1..312bc077 100644 --- a/README.md +++ b/README.md @@ -91,9 +91,11 @@ You can use the following commands inside the `fsfw` folder to set up the build ```sh mkdir build-Unittest && cd build-Unittest -cmake -DFSFW_BUILD_UNITTESTS=ON .. +cmake -DFSFW_BUILD_UNITTESTS=ON -DFSFW_OSAL=host .. ``` +You can also use `-DFSFW_OSAL=linux` on Linux systems. + Coverage data in HTML format can be generated using the `CodeCoverage` [CMake module](https://github.com/bilke/cmake-modules/tree/master). To build the unittests, run them and then generare the coverage data in this format, From ac8df112b1a51896279ab6a0bb566dcd133fbf0e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 16:01:14 +0200 Subject: [PATCH 29/49] small correction --- tests/src/fsfw_tests/unit/testcfg/events/subsystemIdRanges.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/fsfw_tests/unit/testcfg/events/subsystemIdRanges.h b/tests/src/fsfw_tests/unit/testcfg/events/subsystemIdRanges.h index b88cd875..b14c4bc5 100644 --- a/tests/src/fsfw_tests/unit/testcfg/events/subsystemIdRanges.h +++ b/tests/src/fsfw_tests/unit/testcfg/events/subsystemIdRanges.h @@ -12,7 +12,7 @@ */ namespace SUBSYSTEM_ID { enum: uint8_t { - SUBSYSTEM_ID_START = 0, + SUBSYSTEM_ID_START = FW_SUBSYSTEM_ID_RANGE, SUBSYSTEM_ID_END // [EXPORT] : [END] }; } From 22dbabba38d998108a1a7b5e2e5cccd5a6b4f512 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 16:01:58 +0200 Subject: [PATCH 30/49] removed copy and paste error --- tests/src/fsfw_tests/unit/testcfg/tmtc/apid.h | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/src/fsfw_tests/unit/testcfg/tmtc/apid.h b/tests/src/fsfw_tests/unit/testcfg/tmtc/apid.h index 0e633afb..c0231bca 100644 --- a/tests/src/fsfw_tests/unit/testcfg/tmtc/apid.h +++ b/tests/src/fsfw_tests/unit/testcfg/tmtc/apid.h @@ -12,7 +12,6 @@ */ namespace apid { static const uint16_t DEFAULT_APID = 0x00; - static const uint16_t SOURCE_OBSW = 0x73; } From 19061c3d50c74dce25159aa3e1850938f5518b6e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 16:04:43 +0200 Subject: [PATCH 31/49] removed obsolete files --- tests/src/fsfw_tests/internal/osal/testCmdExecutor.cpp | 1 - tests/src/fsfw_tests/internal/osal/testCmdExecutor.h | 10 ---------- 2 files changed, 11 deletions(-) delete mode 100644 tests/src/fsfw_tests/internal/osal/testCmdExecutor.cpp delete mode 100644 tests/src/fsfw_tests/internal/osal/testCmdExecutor.h diff --git a/tests/src/fsfw_tests/internal/osal/testCmdExecutor.cpp b/tests/src/fsfw_tests/internal/osal/testCmdExecutor.cpp deleted file mode 100644 index f0bed8ad..00000000 --- a/tests/src/fsfw_tests/internal/osal/testCmdExecutor.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "testCmdExecutor.h" diff --git a/tests/src/fsfw_tests/internal/osal/testCmdExecutor.h b/tests/src/fsfw_tests/internal/osal/testCmdExecutor.h deleted file mode 100644 index 4779dde9..00000000 --- a/tests/src/fsfw_tests/internal/osal/testCmdExecutor.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef FSFW_TESTS_SRC_FSFW_TESTS_INTERNAL_OSAL_TESTCMDEXECUTOR_H_ -#define FSFW_TESTS_SRC_FSFW_TESTS_INTERNAL_OSAL_TESTCMDEXECUTOR_H_ - -namespace testcmdexec { - -} - - - -#endif /* FSFW_TESTS_SRC_FSFW_TESTS_INTERNAL_OSAL_TESTCMDEXECUTOR_H_ */ From 306a4b647f5afa72ee7cf6664103886a3a5b126b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 16:06:12 +0200 Subject: [PATCH 32/49] more review corrections --- CMakeLists.txt | 2 +- src/fsfw/FSFWVersion.h.in | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index eae1fc25..101232e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -320,7 +320,7 @@ target_link_libraries(${LIB_FSFW_NAME} PRIVATE string(CONCAT POST_BUILD_COMMENT "######################################################################\n" - "Building FSFW v${FSFW_VERSION}.${FSFW_SUBVERSION}.${FSFW_REVISION}, " + "Built FSFW v${FSFW_VERSION}.${FSFW_SUBVERSION}.${FSFW_REVISION}, " "Target OSAL: ${FSFW_OS_NAME}\n" "######################################################################\n" ) diff --git a/src/fsfw/FSFWVersion.h.in b/src/fsfw/FSFWVersion.h.in index a858d703..7935b2f6 100644 --- a/src/fsfw/FSFWVersion.h.in +++ b/src/fsfw/FSFWVersion.h.in @@ -1,8 +1,6 @@ #ifndef FSFW_VERSION_H_ #define FSFW_VERSION_H_ -const char* const FSFW_VERSION_NAME = "ASTP"; - // Versioning is kept in project CMakeLists.txt file #define FSFW_VERSION @FSFW_VERSION@ #define FSFW_SUBVERSION @FSFW_SUBVERSION@ From bb9ae86159bb68a9fc830ade50581a9022266833 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 16:12:32 +0200 Subject: [PATCH 33/49] indentation fixes --- tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in b/tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in index d03ec3e5..1df7ef48 100644 --- a/tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in +++ b/tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in @@ -7,30 +7,30 @@ //! Used to determine whether C++ ostreams are used which can increase //! the binary size significantly. If this is disabled, //! the C stdio functions can be used alternatively -#define FSFW_CPP_OSTREAM_ENABLED 0 +#define FSFW_CPP_OSTREAM_ENABLED 0 //! More FSFW related printouts depending on level. Useful for development. -#define FSFW_VERBOSE_LEVEL 1 +#define FSFW_VERBOSE_LEVEL 1 //! Can be used to completely disable printouts, even the C stdio ones. #if FSFW_CPP_OSTREAM_ENABLED == 0 && FSFW_VERBOSE_LEVEL == 0 - #define FSFW_DISABLE_PRINTOUT 0 + #define FSFW_DISABLE_PRINTOUT 1 #endif #define FSFW_USE_PUS_C_TELEMETRY 1 #define FSFW_USE_PUS_C_TELECOMMANDS 1 //! Can be used to disable the ANSI color sequences for C stdio. -#define FSFW_COLORED_OUTPUT 1 +#define FSFW_COLORED_OUTPUT 1 //! If FSFW_OBJ_EVENT_TRANSLATION is set to one, //! additional output which requires the translation files translateObjects //! and translateEvents (and their compiled source files) -#define FSFW_OBJ_EVENT_TRANSLATION 0 +#define FSFW_OBJ_EVENT_TRANSLATION 0 #if FSFW_OBJ_EVENT_TRANSLATION == 1 //! Specify whether info events are printed too. -#define FSFW_DEBUG_INFO 1 +#define FSFW_DEBUG_INFO 1 #include "objects/translateObjects.h" #include "events/translateEvents.h" #else @@ -38,7 +38,7 @@ //! When using the newlib nano library, C99 support for stdio facilities //! will not be provided. This define should be set to 1 if this is the case. -#define FSFW_NO_C99_IO 1 +#define FSFW_NO_C99_IO 1 //! Specify whether a special mode store is used for Subsystem components. #define FSFW_USE_MODESTORE 0 From 3d6f28c48df51d093f01797faa90a22128ffdfca Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 16:14:30 +0200 Subject: [PATCH 34/49] printouts disable by default --- tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in b/tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in index 1df7ef48..f05ef40b 100644 --- a/tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in +++ b/tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in @@ -10,7 +10,7 @@ #define FSFW_CPP_OSTREAM_ENABLED 0 //! More FSFW related printouts depending on level. Useful for development. -#define FSFW_VERBOSE_LEVEL 1 +#define FSFW_VERBOSE_LEVEL 0 //! Can be used to completely disable printouts, even the C stdio ones. #if FSFW_CPP_OSTREAM_ENABLED == 0 && FSFW_VERBOSE_LEVEL == 0 From 460941c2251476eb9863c54422244a253441d3a9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 16:16:49 +0200 Subject: [PATCH 35/49] tiny tweak --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 101232e9..af19b4c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,7 @@ if(FSFW_BUILD_UNITTESTS) configure_file(tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in FSFWConfig.h) configure_file(tests/src/fsfw_tests/unit/testcfg/TestsConfig.h.in tests/TestsConfig.h) configure_file(tests/src/fsfw_tests/unit/testcfg/OBSWConfig.h.in OBSWConfig.h) + project(${FSFW_TEST_TGT} CXX C) add_executable(${FSFW_TEST_TGT}) From bf5590ce2632102abd77711df3e64c5edffc7d80 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 16:25:01 +0200 Subject: [PATCH 36/49] configure file correction --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index af19b4c5..4af52a5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,8 +92,8 @@ target_include_directories(${LIB_FSFW_NAME} PRIVATE target_include_directories(${LIB_FSFW_NAME} INTERFACE ${CMAKE_CURRENT_BINARY_DIR} ) -configure_file(src/fsfw/FSFW.h.in FSFW.h) -configure_file(src/fsfw/FSFWVersion.h.in FSFWVersion.h) +configure_file(src/fsfw/FSFW.h.in fsfw/FSFW.h) +configure_file(src/fsfw/FSFWVersion.h.in fsfw/FSFWVersion.h) if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 11) From d4bb9397ee24f766be36350b7179e7e7c3df3e21 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 16:32:19 +0200 Subject: [PATCH 37/49] better handling for configure files --- CMakeLists.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4af52a5b..e0a0bfb0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,8 +92,14 @@ target_include_directories(${LIB_FSFW_NAME} PRIVATE target_include_directories(${LIB_FSFW_NAME} INTERFACE ${CMAKE_CURRENT_BINARY_DIR} ) -configure_file(src/fsfw/FSFW.h.in fsfw/FSFW.h) -configure_file(src/fsfw/FSFWVersion.h.in fsfw/FSFWVersion.h) + +if(FSFW_BUILD_UNITTESTS) + configure_file(src/fsfw/FSFW.h.in fsfw/FSFW.h) + configure_file(src/fsfw/FSFWVersion.h.in fsfw/FSFWVersion.h) +else() + configure_file(src/fsfw/FSFW.h.in FSFW.h) + configure_file(src/fsfw/FSFWVersion.h.in FSFWVersion.h) +endif() if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 11) From fc9101cd8f8e926ea41e87849cfc4a20dee3b226 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 17:12:42 +0200 Subject: [PATCH 38/49] deleted unrequired files, common include deleted --- .../unit/testcfg/devices/logicalAddresses.h | 1 - .../unit/testcfg/events/translateEvents.cpp | 15 --------------- .../unit/testcfg/events/translateEvents.h | 8 -------- .../unit/testcfg/objects/translateObjects.cpp | 19 ------------------- .../unit/testcfg/objects/translateObjects.h | 8 -------- 5 files changed, 51 deletions(-) delete mode 100644 tests/src/fsfw_tests/unit/testcfg/events/translateEvents.cpp delete mode 100644 tests/src/fsfw_tests/unit/testcfg/events/translateEvents.h delete mode 100644 tests/src/fsfw_tests/unit/testcfg/objects/translateObjects.cpp delete mode 100644 tests/src/fsfw_tests/unit/testcfg/objects/translateObjects.h diff --git a/tests/src/fsfw_tests/unit/testcfg/devices/logicalAddresses.h b/tests/src/fsfw_tests/unit/testcfg/devices/logicalAddresses.h index a0240037..d7b73e15 100644 --- a/tests/src/fsfw_tests/unit/testcfg/devices/logicalAddresses.h +++ b/tests/src/fsfw_tests/unit/testcfg/devices/logicalAddresses.h @@ -2,7 +2,6 @@ #define CONFIG_DEVICES_LOGICALADDRESSES_H_ #include -#include "common/devices/commonAddresses.h" #include diff --git a/tests/src/fsfw_tests/unit/testcfg/events/translateEvents.cpp b/tests/src/fsfw_tests/unit/testcfg/events/translateEvents.cpp deleted file mode 100644 index 47186727..00000000 --- a/tests/src/fsfw_tests/unit/testcfg/events/translateEvents.cpp +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @brief Auto-generated event translation file. Contains 81 translations. - * @details - * Generated on: 2021-05-18 16:28:16 - */ -#include "translateEvents.h" - - -const char * translateEvents(Event event) { - switch( (event & 0xffff) ) { - default: - return "UNKNOWN_EVENT"; - } - return 0; -} diff --git a/tests/src/fsfw_tests/unit/testcfg/events/translateEvents.h b/tests/src/fsfw_tests/unit/testcfg/events/translateEvents.h deleted file mode 100644 index 9034dcf2..00000000 --- a/tests/src/fsfw_tests/unit/testcfg/events/translateEvents.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef FSFWCONFIG_EVENTS_TRANSLATEEVENTS_H_ -#define FSFWCONFIG_EVENTS_TRANSLATEEVENTS_H_ - -#include - -const char * translateEvents(Event event); - -#endif /* FSFWCONFIG_EVENTS_TRANSLATEEVENTS_H_ */ diff --git a/tests/src/fsfw_tests/unit/testcfg/objects/translateObjects.cpp b/tests/src/fsfw_tests/unit/testcfg/objects/translateObjects.cpp deleted file mode 100644 index 63636ced..00000000 --- a/tests/src/fsfw_tests/unit/testcfg/objects/translateObjects.cpp +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @brief Auto-generated object translation file. - * @details - * Contains 69 translations. - * Generated on: 2021-05-18 16:37:37 - */ -#include "translateObjects.h" - -const char *NO_OBJECT_STRING = "NO_OBJECT"; - -const char* translateObject(object_id_t object) { - switch( (object & 0xFFFFFFFF) ) { - case 0xFFFFFFFF: - return NO_OBJECT_STRING; - default: - return "UNKNOWN_OBJECT"; - } - return 0; -} diff --git a/tests/src/fsfw_tests/unit/testcfg/objects/translateObjects.h b/tests/src/fsfw_tests/unit/testcfg/objects/translateObjects.h deleted file mode 100644 index dbf5b468..00000000 --- a/tests/src/fsfw_tests/unit/testcfg/objects/translateObjects.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef FSFWCONFIG_OBJECTS_TRANSLATEOBJECTS_H_ -#define FSFWCONFIG_OBJECTS_TRANSLATEOBJECTS_H_ - -#include - -const char* translateObject(object_id_t object); - -#endif /* FSFWCONFIG_OBJECTS_TRANSLATEOBJECTS_H_ */ From b2b648c4aa1f1f3cd50f23a61d01979c861b64ad Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 17:14:30 +0200 Subject: [PATCH 39/49] removed obsolete comment --- tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt b/tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt index 531972ac..f840e38b 100644 --- a/tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt +++ b/tests/src/fsfw_tests/unit/testcfg/CMakeLists.txt @@ -8,11 +8,6 @@ target_include_directories(${FSFW_TEST_TGT} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ) -# These translation files are actually not that relevant for the tests. However, the FSFW tests -# compile against a user-configured variant of the FSFW, which might be configured to include -# translation information. Therefore, empty dummy translation files are compiled here -# so the tests compile in any case. - # If a special translation file for object IDs exists, compile it. if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/objects/translateObjects.cpp") target_sources(${FSFW_TEST_TGT} PRIVATE From e8927d6aa888b78aa7db68daa277eb693913c74a Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 17:22:29 +0200 Subject: [PATCH 40/49] moved testtemplate and removed user folder --- .../unit}/testtemplate/TestTemplate.cpp | 5 +- tests/user/CMakeLists.txt | 261 ------------------ tests/user/lcov.sh | 3 - 3 files changed, 2 insertions(+), 267 deletions(-) rename tests/{user => src/fsfw_tests/unit}/testtemplate/TestTemplate.cpp (90%) delete mode 100644 tests/user/CMakeLists.txt delete mode 100644 tests/user/lcov.sh diff --git a/tests/user/testtemplate/TestTemplate.cpp b/tests/src/fsfw_tests/unit/testtemplate/TestTemplate.cpp similarity index 90% rename from tests/user/testtemplate/TestTemplate.cpp rename to tests/src/fsfw_tests/unit/testtemplate/TestTemplate.cpp index 6b5fc3d2..a779d80c 100644 --- a/tests/user/testtemplate/TestTemplate.cpp +++ b/tests/src/fsfw_tests/unit/testtemplate/TestTemplate.cpp @@ -1,6 +1,5 @@ -#include -#include - +#include "fsfw_tests/unit/CatchDefinitions.h" +#include /** * @brief Template test file diff --git a/tests/user/CMakeLists.txt b/tests/user/CMakeLists.txt deleted file mode 100644 index 2e1fdee3..00000000 --- a/tests/user/CMakeLists.txt +++ /dev/null @@ -1,261 +0,0 @@ -################################################################################ -# CMake support for the Flight Software Framework Tests -# Author: R. Mueller -################################################################################ - -################################################################################ -# Pre-Project preparation -################################################################################ -cmake_minimum_required(VERSION 3.13) - -# set(CMAKE_VERBOSE TRUE) -# set(CODE_COVERAGE_VERBOSE TRUE) - -set(CMAKE_SCRIPT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") - -option(TMTC_TEST "Build binary for manual or automatic TMTC tests" FALSE) -option(GENERATE_COVERAGE - "Specify whether coverage data is generated with GCOV" - TRUE -) - -set(FSFW_ADD_UNITTESTS ON) - -if(TMTC_TEST) - set(LINK_CATCH2 FALSE) -else() - set(LINK_CATCH2 TRUE) -endif() - -# Tests can be built with the Host OSAL or with the Linux OSAL. -if(NOT FSFW_OSAL) - set(FSFW_OSAL host CACHE STRING "OS for the FSFW.") -endif() - -option(FSFW_CUSTOM_UNITTEST_RUNNER - "Specify whether custom main or Catch2 main is used" TRUE -) - -# Project Name -project(fsfw-tests C CXX) - -################################################################################ -# Pre-Sources preparation -################################################################################ - -# Specify the C++ standard -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED True) - -# Set names and variables -set(TARGET_NAME ${CMAKE_PROJECT_NAME}) -if(FSFW_CUSTOM_UNITTEST_RUNNER) - set(CATCH2_TARGET Catch2) -else() - set(CATCH2_TARGET Catch2WithMain) -endif() -set(LIB_FSFW_NAME fsfw) - -# Set path names -set(FSFW_PATH fsfw) -set(CATCH2_PATH Catch2) -set(FSFW_TESTS_PATH fsfw/unittest) -set(TEST_SETUP_PATH unittest) -set(TMTC_TEST_PATH tests) - -# Analyse different OS and architecture/target options and -# determine BSP_PATH - -# FreeRTOS -if(FSFW_OSAL STREQUAL linux) - add_definitions(-DUNIX -DLINUX) - find_package(Threads REQUIRED) -# Hosted -else() - if(WIN32) - add_definitions(-DWIN32) - elseif(UNIX) - find_package(Threads REQUIRED) - add_definitions(-DUNIX -DLINUX) - endif() -endif() - -if(GENERATE_COVERAGE) - list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/cmake-modules) - if(CMAKE_COMPILER_IS_GNUCXX) - include(CodeCoverage) - # Add compile options on target base, we don't want coverage for Catch2 - # append_coverage_compiler_flags() - endif() -endif() - -set(FSFW_CONFIG_PATH testcfg) -set(FSFW_ADDITIONAL_INC_PATHS ${CMAKE_CURRENT_BINARY_DIR}) - -configure_file(${FSFW_CONFIG_PATH}/FSFWConfig.h.in FSFWConfig.h) -configure_file(${FSFW_CONFIG_PATH}/OBSWConfig.h.in OBSWConfig.h) -configure_file(${FSFW_CONFIG_PATH}/TestsConfig.h.in TestsConfig.h) - -################################################################################ -# Executable and Sources -################################################################################ - -# Add executable -add_executable(${TARGET_NAME}) - -# Add subdirectories -add_subdirectory(${FSFW_PATH}) -add_subdirectory(${FSFW_CONFIG_PATH}) - -if(LINK_CATCH2) - add_subdirectory(${CATCH2_PATH}) - add_subdirectory(${TEST_SETUP_PATH}) -else() - target_compile_definitions(${TARGET_NAME} PRIVATE - FSFW_DISABLE_PRINTOUT=0 - ) - target_compile_definitions(${LIB_FSFW_NAME} PRIVATE - FSFW_DISABLE_PRINTOUT=0 - ) - add_subdirectory(${TMTC_TEST_PATH}) - add_subdirectory(${FSFW_TESTS_PATH}) -endif() - - -################################################################################ -# Post-Sources preparation -################################################################################ - -# Add libraries for all sources. -target_link_libraries(${TARGET_NAME} PRIVATE - ${LIB_FSFW_NAME} -) - -if(LINK_CATCH2) - target_link_libraries(${TARGET_NAME} PRIVATE - ${CATCH2_TARGET} - ) -endif() - -if(GENERATE_COVERAGE) - if(CMAKE_COMPILER_IS_GNUCXX) - # set(CODE_COVERAGE_VERBOSE TRUE) - include(CodeCoverage) - - # Remove quotes. - separate_arguments(COVERAGE_COMPILER_FLAGS - NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}" - ) - - # Add compile options manually, we don't want coverage for Catch2 - target_compile_options(${TARGET_NAME} PRIVATE - "${COVERAGE_COMPILER_FLAGS}" - ) - target_compile_options(${LIB_FSFW_NAME} PRIVATE - "${COVERAGE_COMPILER_FLAGS}" - ) - - # Exclude internal unittest from coverage for now. - if(WIN32) - set(GCOVR_ADDITIONAL_ARGS - "--exclude-throw-branches" - "--exclude-unreachable-branches" - ) - set(COVERAGE_EXCLUDES - "/c/msys64/mingw64/*" "Catch2" - "${CMAKE_CURRENT_SOURCE_DIR}/fsfw/unittest/internal" - ) - elseif(UNIX) - set(COVERAGE_EXCLUDES - "/usr/include/*" "/usr/bin/*" "Catch2/*" - "fsfw/unittest/internal/*" - ) - endif() - - target_link_options(${TARGET_NAME} PRIVATE - -fprofile-arcs - -ftest-coverage - ) - target_link_options(${LIB_FSFW_NAME} PRIVATE - -fprofile-arcs - -ftest-coverage - ) - - if(WIN32) - setup_target_for_coverage_gcovr_html( - NAME ${TARGET_NAME}_coverage - EXECUTABLE ${TARGET_NAME} - DEPENDENCIES ${TARGET_NAME} - ) - else() - setup_target_for_coverage_lcov( - NAME ${TARGET_NAME}_coverage - EXECUTABLE ${TARGET_NAME} - DEPENDENCIES ${TARGET_NAME} - ) - endif() - endif() -endif() - -# Add include paths for all sources. -target_include_directories(${TARGET_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${FSFW_CONFIG_PATH} - ${CMAKE_CURRENT_BINARY_DIR} -) - -if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(WARNING_FLAGS - -Wall - -Wextra - -Wshadow=local - -Wimplicit-fallthrough=1 - -Wno-unused-parameter - -Wno-psabi - ) - - # Remove unused sections. - target_compile_options(${TARGET_NAME} PRIVATE - "-ffunction-sections" - "-fdata-sections" - ) - - # Removed unused sections. - target_link_options(${TARGET_NAME} PRIVATE - "-Wl,--gc-sections" - ) - -elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - set(COMPILER_FLAGS "/permissive-") -endif() - -if(CMAKE_VERBOSE) - message(STATUS "Warning flags: ${WARNING_FLAGS}") -endif() - -# Compile options for all sources. -target_compile_options(${TARGET_NAME} PRIVATE - ${WARNING_FLAGS} -) - -if(NOT CMAKE_SIZE) - set(CMAKE_SIZE size) - if(WIN32) - set(FILE_SUFFIX ".exe") - endif() -endif() - -string(CONCAT POST_BUILD_COMMENT - "Build directory: ${CMAKE_BINARY_DIR}\n" - "Target OSAL: ${FSFW_OSAL}\n" - "Target Build Type: ${CMAKE_BUILD_TYPE}" -) - -add_custom_command(TARGET ${TARGET_NAME} - POST_BUILD - COMMAND ${CMAKE_SIZE} ${TARGET_NAME}${FILE_SUFFIX} - COMMENT ${POST_BUILD_COMMENT} -) - -include (${CMAKE_SCRIPT_PATH}/BuildType.cmake) -set_build_type() diff --git a/tests/user/lcov.sh b/tests/user/lcov.sh deleted file mode 100644 index 4db16e5f..00000000 --- a/tests/user/lcov.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -lcov --capture --directory . --output-file coverage.info -genhtml coverage.info --output-directory _coverage From 348975ba5f80bb95383c9d7618b172cc0e99a827 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 17:28:07 +0200 Subject: [PATCH 41/49] additional coverage excludes --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index e0a0bfb0..0f45de01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -194,6 +194,8 @@ if(FSFW_BUILD_UNITTESTS) elseif(UNIX) set(COVERAGE_EXCLUDES "/usr/include/*" "/usr/bin/*" "Catch2/*" + "/usr/local/include/*" "*/fsfw_tests/*" + "/catch2-src/*" ) endif() From 060b3a3b2c4814e04a3122a4fff124850fecccc0 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 17:51:13 +0200 Subject: [PATCH 42/49] added missing leading * --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f45de01..923d5cc5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -195,7 +195,7 @@ if(FSFW_BUILD_UNITTESTS) set(COVERAGE_EXCLUDES "/usr/include/*" "/usr/bin/*" "Catch2/*" "/usr/local/include/*" "*/fsfw_tests/*" - "/catch2-src/*" + "*/catch2-src/*" ) endif() From c46bde417e7b56b39bab50a1faa2688b3e65eff4 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 19:37:23 +0200 Subject: [PATCH 43/49] small bugfix for LIS3 handler --- hal/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hal/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp b/hal/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp index 804e83f2..1a61bfe2 100644 --- a/hal/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp +++ b/hal/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp @@ -73,7 +73,7 @@ ReturnValue_t MgmLIS3MDLHandler::buildTransitionDeviceCommand( switch (internalState) { case(InternalState::STATE_NONE): case(InternalState::STATE_NORMAL): { - return HasReturnvaluesIF::RETURN_OK; + return DeviceHandlerBase::NOTHING_TO_SEND; } case(InternalState::STATE_FIRST_CONTACT): { *id = MGMLIS3MDL::IDENTIFY_DEVICE; From 2180c47f4fc40786af594c2df7d30492edb5c87e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 19:47:41 +0200 Subject: [PATCH 44/49] more printouts for rejected packet --- src/fsfw/tcdistribution/PUSDistributor.cpp | 27 ++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/fsfw/tcdistribution/PUSDistributor.cpp b/src/fsfw/tcdistribution/PUSDistributor.cpp index eec02429..1a5f713d 100644 --- a/src/fsfw/tcdistribution/PUSDistributor.cpp +++ b/src/fsfw/tcdistribution/PUSDistributor.cpp @@ -29,12 +29,31 @@ PUSDistributor::TcMqMapIter PUSDistributor::selectDestination() { tcStatus = checker.checkPacket(currentPacket); if(tcStatus != HasReturnvaluesIF::RETURN_OK) { #if FSFW_VERBOSE_LEVEL >= 1 + std::string keyword; + if(tcStatus == TcPacketCheck::INCORRECT_CHECKSUM) { + keyword = "checksum"; + } + else if(tcStatus == TcPacketCheck::INCORRECT_PRIMARY_HEADER) { + keyword = "incorrect primary header"; + } + else if(tcStatus == TcPacketCheck::ILLEGAL_APID) { + keyword = "illegal APID"; + } + else if(tcStatus == TcPacketCheck::INCORRECT_SECONDARY_HEADER) { + keyword = "incorrect secondary header"; + } + else if(tcStatus == TcPacketCheck::INCOMPLETE_PACKET) { + keyword = "incomplete packet"; + } + else { + keyword = "unnamed error"; + } #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "PUSDistributor::handlePacket: Packet format invalid, code " << - static_cast(tcStatus) << std::endl; + sif::warning << "PUSDistributor::handlePacket: Packet format invalid, " + << keyword << " error" << std::endl; #else - sif::printDebug("PUSDistributor::handlePacket: Packet format invalid, code %d\n", - static_cast(tcStatus)); + sif::printWarning("PUSDistributor::handlePacket: Packet format invalid, " + "%s error\n", keyword); #endif #endif } From cae3feb5da403405c241690220b316ef17d1892f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Oct 2021 19:55:37 +0200 Subject: [PATCH 45/49] Add feature to open GPIO by line name This features was provided by Jakob Meier as part of https://egit.irs.uni-stuttgart.de/eive/fsfw/pulls/19 . It adds the feature to open GPIOs supplying their line names. --- .../fsfw_hal/common/gpio/gpioDefinitions.h | 54 +++- .../fsfw_hal/linux/gpio/LinuxLibgpioIF.cpp | 242 ++++++++++++------ hal/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.h | 37 ++- 3 files changed, 235 insertions(+), 98 deletions(-) diff --git a/hal/src/fsfw_hal/common/gpio/gpioDefinitions.h b/hal/src/fsfw_hal/common/gpio/gpioDefinitions.h index 688d9c9b..c6f21195 100644 --- a/hal/src/fsfw_hal/common/gpio/gpioDefinitions.h +++ b/hal/src/fsfw_hal/common/gpio/gpioDefinitions.h @@ -9,12 +9,13 @@ using gpioId_t = uint16_t; namespace gpio { -enum Levels { +enum Levels: uint8_t { LOW = 0, - HIGH = 1 + HIGH = 1, + NONE = 99 }; -enum Direction { +enum Direction: uint8_t { IN = 0, OUT = 1 }; @@ -24,16 +25,18 @@ enum GpioOperation { WRITE }; -enum GpioTypes { +enum class GpioTypes { NONE, GPIO_REGULAR_BY_CHIP, GPIO_REGULAR_BY_LABEL, + GPIO_REGULAR_BY_LINE_NAME, CALLBACK }; static constexpr gpioId_t NO_GPIO = -1; -using gpio_cb_t = void (*) (gpioId_t gpioId, gpio::GpioOperation gpioOp, int value, void* args); +using gpio_cb_t = void (*) (gpioId_t gpioId, gpio::GpioOperation gpioOp, gpio::Levels value, + void* args); } @@ -57,7 +60,7 @@ public: GpioBase() = default; GpioBase(gpio::GpioTypes gpioType, std::string consumer, gpio::Direction direction, - int initValue): + gpio::Levels initValue): gpioType(gpioType), consumer(consumer),direction(direction), initValue(initValue) {} virtual~ GpioBase() {}; @@ -66,15 +69,21 @@ public: gpio::GpioTypes gpioType = gpio::GpioTypes::NONE; std::string consumer; gpio::Direction direction = gpio::Direction::IN; - int initValue = 0; + gpio::Levels initValue = gpio::Levels::NONE; }; class GpiodRegularBase: public GpioBase { public: GpiodRegularBase(gpio::GpioTypes gpioType, std::string consumer, gpio::Direction direction, - int initValue, int lineNum): GpioBase(gpioType, consumer, direction, initValue), - lineNum(lineNum) { + gpio::Levels initValue, int lineNum): + GpioBase(gpioType, consumer, direction, initValue), lineNum(lineNum) { } + + // line number will be configured at a later point for the open by line name configuration + GpiodRegularBase(gpio::GpioTypes gpioType, std::string consumer, gpio::Direction direction, + gpio::Levels initValue): GpioBase(gpioType, consumer, direction, initValue) { + } + int lineNum = 0; struct gpiod_line* lineHandle = nullptr; }; @@ -87,7 +96,7 @@ public: } GpiodRegularByChip(std::string chipname_, int lineNum_, std::string consumer_, - gpio::Direction direction_, int initValue_) : + gpio::Direction direction_, gpio::Levels initValue_) : GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_CHIP, consumer_, direction_, initValue_, lineNum_), chipname(chipname_){ @@ -105,7 +114,7 @@ public: class GpiodRegularByLabel: public GpiodRegularBase { public: GpiodRegularByLabel(std::string label_, int lineNum_, std::string consumer_, - gpio::Direction direction_, int initValue_) : + gpio::Direction direction_, gpio::Levels initValue_) : GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_LABEL, consumer_, direction_, initValue_, lineNum_), label(label_) { @@ -120,9 +129,30 @@ public: std::string label; }; +/** + * @brief Passing this GPIO configuration to the GPIO IF object will try to open the GPIO by its + * line name. This line name can be set in the device tree and must be unique. Otherwise + * the driver will open the first line with the given name. + */ +class GpiodRegularByLineName: public GpiodRegularBase { +public: + GpiodRegularByLineName(std::string lineName_, std::string consumer_, gpio::Direction direction_, + gpio::Levels initValue_) : + GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME, consumer_, direction_, + initValue_), lineName(lineName_) { + } + + GpiodRegularByLineName(std::string lineName_, std::string consumer_) : + GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME, consumer_, + gpio::Direction::IN, gpio::LOW), lineName(lineName_) { + } + + std::string lineName; +}; + class GpioCallback: public GpioBase { public: - GpioCallback(std::string consumer, gpio::Direction direction_, int initValue_, + GpioCallback(std::string consumer, gpio::Direction direction_, gpio::Levels initValue_, gpio::gpio_cb_t callback, void* callbackArgs): GpioBase(gpio::GpioTypes::CALLBACK, consumer, direction_, initValue_), callback(callback), callbackArgs(callbackArgs) {} diff --git a/hal/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.cpp b/hal/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.cpp index 15c3d118..020ba964 100644 --- a/hal/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.cpp +++ b/hal/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.cpp @@ -1,8 +1,9 @@ -#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h" +#include "LinuxLibgpioIF.h" + #include "fsfw_hal/common/gpio/gpioDefinitions.h" #include "fsfw_hal/common/gpio/GpioCookie.h" -#include +#include "fsfw/serviceinterface/ServiceInterface.h" #include #include @@ -66,6 +67,14 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) { configureGpioByLabel(gpioConfig.first, *regularGpio); break; } + case(gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME):{ + auto regularGpio = dynamic_cast(gpioConfig.second); + if(regularGpio == nullptr) { + return GPIO_INVALID_INSTANCE; + } + configureGpioByLineName(gpioConfig.first, *regularGpio); + break; + } case(gpio::GpioTypes::CALLBACK): { auto gpioCallback = dynamic_cast(gpioConfig.second); if(gpioCallback->callback == nullptr) { @@ -84,13 +93,13 @@ ReturnValue_t LinuxLibgpioIF::configureGpioByLabel(gpioId_t gpioId, std::string& label = gpioByLabel.label; struct gpiod_chip* chip = gpiod_chip_open_by_label(label.c_str()); if (chip == nullptr) { - sif::warning << "LinuxLibgpioIF::configureRegularGpio: Failed to open gpio from gpio " + sif::warning << "LinuxLibgpioIF::configureGpioByLabel: Failed to open gpio from gpio " << "group with label " << label << ". Gpio ID: " << gpioId << std::endl; return RETURN_FAILED; } std::string failOutput = "label: " + label; - return configureRegularGpio(gpioId, gpioByLabel.gpioType, chip, gpioByLabel, failOutput); + return configureRegularGpio(gpioId, chip, gpioByLabel, failOutput); } ReturnValue_t LinuxLibgpioIF::configureGpioByChip(gpioId_t gpioId, @@ -98,16 +107,41 @@ ReturnValue_t LinuxLibgpioIF::configureGpioByChip(gpioId_t gpioId, std::string& chipname = gpioByChip.chipname; struct gpiod_chip* chip = gpiod_chip_open_by_name(chipname.c_str()); if (chip == nullptr) { - sif::warning << "LinuxLibgpioIF::configureRegularGpio: Failed to open chip " + sif::warning << "LinuxLibgpioIF::configureGpioByChip: Failed to open chip " << chipname << ". Gpio ID: " << gpioId << std::endl; return RETURN_FAILED; } std::string failOutput = "chipname: " + chipname; - return configureRegularGpio(gpioId, gpioByChip.gpioType, chip, gpioByChip, failOutput); + return configureRegularGpio(gpioId, chip, gpioByChip, failOutput); } -ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, gpio::GpioTypes gpioType, - struct gpiod_chip* chip, GpiodRegularBase& regularGpio, std::string failOutput) { +ReturnValue_t LinuxLibgpioIF::configureGpioByLineName(gpioId_t gpioId, + GpiodRegularByLineName &gpioByLineName) { + std::string& lineName = gpioByLineName.lineName; + char chipname[MAX_CHIPNAME_LENGTH]; + unsigned int lineOffset; + + int result = gpiod_ctxless_find_line(lineName.c_str(), chipname, MAX_CHIPNAME_LENGTH, + &lineOffset); + if (result != LINE_FOUND) { + parseFindeLineResult(result, lineName); + return RETURN_FAILED; + } + + gpioByLineName.lineNum = static_cast(lineOffset); + + struct gpiod_chip* chip = gpiod_chip_open_by_name(chipname); + if (chip == nullptr) { + sif::warning << "LinuxLibgpioIF::configureGpioByLineName: Failed to open chip " + << chipname << ". second->gpioType; - if(gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_CHIP or - gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_LABEL) { + if (gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_CHIP + or gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_LABEL + or gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME) { auto regularGpio = dynamic_cast(gpioMapIter->second); if(regularGpio == nullptr) { return GPIO_TYPE_FAILURE; @@ -187,7 +222,7 @@ ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) { return GPIO_INVALID_INSTANCE; } gpioCallback->callback(gpioMapIter->first, gpio::GpioOperation::WRITE, - 1, gpioCallback->callbackArgs); + gpio::Levels::HIGH, gpioCallback->callbackArgs); return RETURN_OK; } return GPIO_TYPE_FAILURE; @@ -196,13 +231,18 @@ ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) { ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId) { gpioMapIter = gpioMap.find(gpioId); if (gpioMapIter == gpioMap.end()) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "LinuxLibgpioIF::pullLow: Unknown GPIO ID " << gpioId << std::endl; +#else + sif::printWarning("LinuxLibgpioIF::pullLow: Unknown GPIO ID %d\n", gpioId); +#endif return UNKNOWN_GPIO_ID; } auto& gpioType = gpioMapIter->second->gpioType; - if(gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_CHIP or - gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_LABEL) { + if (gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_CHIP + or gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_LABEL + or gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME) { auto regularGpio = dynamic_cast(gpioMapIter->second); if(regularGpio == nullptr) { return GPIO_TYPE_FAILURE; @@ -215,7 +255,7 @@ ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId) { return GPIO_INVALID_INSTANCE; } gpioCallback->callback(gpioMapIter->first, gpio::GpioOperation::WRITE, - 0, gpioCallback->callbackArgs); + gpio::Levels::LOW, gpioCallback->callbackArgs); return RETURN_OK; } return GPIO_TYPE_FAILURE; @@ -225,8 +265,13 @@ ReturnValue_t LinuxLibgpioIF::driveGpio(gpioId_t gpioId, GpiodRegularBase& regularGpio, gpio::Levels logicLevel) { int result = gpiod_line_set_value(regularGpio.lineHandle, logicLevel); if (result < 0) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID " << gpioId << " to logic level " << logicLevel << std::endl; +#else + sif::printWarning("LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID %d to " + "logic level %d\n", gpioId, logicLevel); +#endif return DRIVE_GPIO_FAILURE; } @@ -236,12 +281,18 @@ ReturnValue_t LinuxLibgpioIF::driveGpio(gpioId_t gpioId, ReturnValue_t LinuxLibgpioIF::readGpio(gpioId_t gpioId, int* gpioState) { gpioMapIter = gpioMap.find(gpioId); if (gpioMapIter == gpioMap.end()){ +#if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "LinuxLibgpioIF::readGpio: Unknown GPIOD ID " << gpioId << std::endl; +#else + sif::printWarning("LinuxLibgpioIF::readGpio: Unknown GPIOD ID %d\n", gpioId); +#endif return UNKNOWN_GPIO_ID; } + auto gpioType = gpioMapIter->second->gpioType; - if(gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_CHIP or - gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_LABEL) { + if (gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_CHIP + or gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_LABEL + or gpioType == gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME) { auto regularGpio = dynamic_cast(gpioMapIter->second); if(regularGpio == nullptr) { return GPIO_TYPE_FAILURE; @@ -249,10 +300,14 @@ ReturnValue_t LinuxLibgpioIF::readGpio(gpioId_t gpioId, int* gpioState) { *gpioState = gpiod_line_get_value(regularGpio->lineHandle); } else { - + auto gpioCallback = dynamic_cast(gpioMapIter->second); + if(gpioCallback->callback == nullptr) { + return GPIO_INVALID_INSTANCE; + } + gpioCallback->callback(gpioMapIter->first, gpio::GpioOperation::READ, + gpio::Levels::NONE, gpioCallback->callbackArgs); + return RETURN_OK; } - - return RETURN_OK; } @@ -262,13 +317,14 @@ ReturnValue_t LinuxLibgpioIF::checkForConflicts(GpioMap& mapToAdd){ for(auto& gpioConfig: mapToAdd) { switch(gpioConfig.second->gpioType) { case(gpio::GpioTypes::GPIO_REGULAR_BY_CHIP): - case(gpio::GpioTypes::GPIO_REGULAR_BY_LABEL): { + case(gpio::GpioTypes::GPIO_REGULAR_BY_LABEL): + case(gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME): { auto regularGpio = dynamic_cast(gpioConfig.second); if(regularGpio == nullptr) { return GPIO_TYPE_FAILURE; } - /* Check for conflicts and remove duplicates if necessary */ - result = checkForConflictsRegularGpio(gpioConfig.first, *regularGpio, mapToAdd); + // Check for conflicts and remove duplicates if necessary + result = checkForConflictsById(gpioConfig.first, gpioConfig.second->gpioType, mapToAdd); if(result != HasReturnvaluesIF::RETURN_OK) { status = result; } @@ -279,66 +335,108 @@ ReturnValue_t LinuxLibgpioIF::checkForConflicts(GpioMap& mapToAdd){ if(callbackGpio == nullptr) { return GPIO_TYPE_FAILURE; } - /* Check for conflicts and remove duplicates if necessary */ - result = checkForConflictsCallbackGpio(gpioConfig.first, callbackGpio, mapToAdd); + // Check for conflicts and remove duplicates if necessary + result = checkForConflictsById(gpioConfig.first, + gpioConfig.second->gpioType, mapToAdd); if(result != HasReturnvaluesIF::RETURN_OK) { status = result; } break; } default: { - +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "Invalid GPIO type detected for GPIO ID " << gpioConfig.first + << std::endl; +#else + sif::printWarning("Invalid GPIO type detected for GPIO ID %d\n", gpioConfig.first); +#endif + status = GPIO_TYPE_FAILURE; } } } return status; } - -ReturnValue_t LinuxLibgpioIF::checkForConflictsRegularGpio(gpioId_t gpioIdToCheck, - GpiodRegularBase& gpioToCheck, GpioMap& mapToAdd) { - /* Cross check with private map */ +ReturnValue_t LinuxLibgpioIF::checkForConflictsById(gpioId_t gpioIdToCheck, + gpio::GpioTypes expectedType, GpioMap& mapToAdd) { + // Cross check with private map gpioMapIter = gpioMap.find(gpioIdToCheck); if(gpioMapIter != gpioMap.end()) { auto& gpioType = gpioMapIter->second->gpioType; - if(gpioType != gpio::GpioTypes::GPIO_REGULAR_BY_CHIP and - gpioType != gpio::GpioTypes::GPIO_REGULAR_BY_LABEL) { - sif::warning << "LinuxLibgpioIF::checkForConflicts: ID already exists for different " - "GPIO type" << gpioIdToCheck << ". Removing duplicate." << std::endl; - mapToAdd.erase(gpioIdToCheck); - return HasReturnvaluesIF::RETURN_OK; + bool eraseDuplicateDifferentType = false; + switch(expectedType) { + case(gpio::GpioTypes::NONE): { + break; } - auto ownRegularGpio = dynamic_cast(gpioMapIter->second); - if(ownRegularGpio == nullptr) { - return GPIO_TYPE_FAILURE; + case(gpio::GpioTypes::GPIO_REGULAR_BY_CHIP): + case(gpio::GpioTypes::GPIO_REGULAR_BY_LABEL): + case(gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME): { + if(gpioType == gpio::GpioTypes::NONE or gpioType == gpio::GpioTypes::CALLBACK) { + eraseDuplicateDifferentType = true; + } + break; + } + case(gpio::GpioTypes::CALLBACK): { + if(gpioType != gpio::GpioTypes::CALLBACK) { + eraseDuplicateDifferentType = true; + } + } + } + if(eraseDuplicateDifferentType) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "LinuxLibgpioIF::checkForConflicts: ID already exists for " + "different GPIO type " << gpioIdToCheck << + ". Removing duplicate from map to add" << std::endl; +#else + sif::printWarning("LinuxLibgpioIF::checkForConflicts: ID already exists for " + "different GPIO type %d. Removing duplicate from map to add\n", gpioIdToCheck); +#endif + mapToAdd.erase(gpioIdToCheck); + return GPIO_DUPLICATE_DETECTED; } - /* Remove element from map to add because a entry for this GPIO - already exists */ - sif::warning << "LinuxLibgpioIF::checkForConflictsRegularGpio: Duplicate GPIO definition" - << " detected. Duplicate will be removed from map to add." << std::endl; + // Remove element from map to add because a entry for this GPIO already exists +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "LinuxLibgpioIF::checkForConflictsRegularGpio: Duplicate GPIO " + "definition with ID " << gpioIdToCheck << " detected. " << + "Duplicate will be removed from map to add" << std::endl; +#else + sif::printWarning("LinuxLibgpioIF::checkForConflictsRegularGpio: Duplicate GPIO definition " + "with ID %d detected. Duplicate will be removed from map to add\n", gpioIdToCheck); +#endif mapToAdd.erase(gpioIdToCheck); + return GPIO_DUPLICATE_DETECTED; } return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t LinuxLibgpioIF::checkForConflictsCallbackGpio(gpioId_t gpioIdToCheck, - GpioCallback *callbackGpio, GpioMap& mapToAdd) { - /* Cross check with private map */ - gpioMapIter = gpioMap.find(gpioIdToCheck); - if(gpioMapIter != gpioMap.end()) { - if(gpioMapIter->second->gpioType != gpio::GpioTypes::CALLBACK) { - sif::warning << "LinuxLibgpioIF::checkForConflicts: ID already exists for different " - "GPIO type" << gpioIdToCheck << ". Removing duplicate." << std::endl; - mapToAdd.erase(gpioIdToCheck); - return HasReturnvaluesIF::RETURN_OK; - } - - /* Remove element from map to add because a entry for this GPIO - already exists */ - sif::warning << "LinuxLibgpioIF::checkForConflictsRegularGpio: Duplicate GPIO definition" - << " detected. Duplicate will be removed from map to add." << std::endl; - mapToAdd.erase(gpioIdToCheck); +void LinuxLibgpioIF::parseFindeLineResult(int result, std::string& lineName) { + switch (result) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + case LINE_NOT_EXISTS: + case LINE_ERROR: { + sif::warning << "LinuxLibgpioIF::parseFindeLineResult: Line with name " << lineName << + " does not exist" << std::endl; + break; } - return HasReturnvaluesIF::RETURN_OK; + default: { + sif::warning << "LinuxLibgpioIF::parseFindeLineResult: Unknown return code for line " + "with name " << lineName << std::endl; + break; + } +#else + case LINE_NOT_EXISTS: + case LINE_ERROR: { + sif::printWarning("LinuxLibgpioIF::parseFindeLineResult: Line with name %s " + "does not exist\n", lineName); + break; + } + default: { + sif::printWarning("LinuxLibgpioIF::parseFindeLineResult: Unknown return code for line " + "with name %s\n", lineName); + break; + } +#endif + } + } diff --git a/hal/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.h b/hal/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.h index 31e4a7e8..cc32bd70 100644 --- a/hal/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.h +++ b/hal/src/fsfw_hal/linux/gpio/LinuxLibgpioIF.h @@ -1,19 +1,19 @@ #ifndef LINUX_GPIO_LINUXLIBGPIOIF_H_ #define LINUX_GPIO_LINUXLIBGPIOIF_H_ -#include "../../common/gpio/GpioIF.h" -#include -#include +#include "fsfw/returnvalues/FwClassIds.h" +#include "fsfw_hal/common/gpio/GpioIF.h" +#include "fsfw/objectmanager/SystemObject.h" class GpioCookie; class GpiodRegularIF; /** - * @brief This class implements the GpioIF for a linux based system. The - * implementation is based on the libgpiod lib which requires linux 4.8 - * or higher. - * @note The Petalinux SDK from Xilinx supports libgpiod since Petalinux - * 2019.1. + * @brief This class implements the GpioIF for a linux based system. + * @details + * This implementation is based on the libgpiod lib which requires Linux 4.8 or higher. + * @note + * The Petalinux SDK from Xilinx supports libgpiod since Petalinux 2019.1. */ class LinuxLibgpioIF : public GpioIF, public SystemObject { public: @@ -28,6 +28,8 @@ public: HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 3); static constexpr ReturnValue_t GPIO_INVALID_INSTANCE = HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 4); + static constexpr ReturnValue_t GPIO_DUPLICATE_DETECTED = + HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 5); LinuxLibgpioIF(object_id_t objectId); virtual ~LinuxLibgpioIF(); @@ -38,7 +40,13 @@ public: ReturnValue_t readGpio(gpioId_t gpioId, int* gpioState) override; private: - /* Holds the information and configuration of all used GPIOs */ + + static const size_t MAX_CHIPNAME_LENGTH = 11; + static const int LINE_NOT_EXISTS = 0; + static const int LINE_ERROR = -1; + static const int LINE_FOUND = 1; + + // Holds the information and configuration of all used GPIOs GpioUnorderedMap gpioMap; GpioUnorderedMapIter gpioMapIter; @@ -53,8 +61,10 @@ private: ReturnValue_t configureGpioByLabel(gpioId_t gpioId, GpiodRegularByLabel& gpioByLabel); ReturnValue_t configureGpioByChip(gpioId_t gpioId, GpiodRegularByChip& gpioByChip); - ReturnValue_t configureRegularGpio(gpioId_t gpioId, gpio::GpioTypes gpioType, - struct gpiod_chip* chip, GpiodRegularBase& regularGpio, std::string failOutput); + ReturnValue_t configureGpioByLineName(gpioId_t gpioId, + GpiodRegularByLineName &gpioByLineName); + ReturnValue_t configureRegularGpio(gpioId_t gpioId, struct gpiod_chip* chip, + GpiodRegularBase& regularGpio, std::string failOutput); /** * @brief This function checks if GPIOs are already registered and whether @@ -67,16 +77,15 @@ private: */ ReturnValue_t checkForConflicts(GpioMap& mapToAdd); - ReturnValue_t checkForConflictsRegularGpio(gpioId_t gpiodId, GpiodRegularBase& regularGpio, + ReturnValue_t checkForConflictsById(gpioId_t gpiodId, gpio::GpioTypes type, GpioMap& mapToAdd); - ReturnValue_t checkForConflictsCallbackGpio(gpioId_t gpiodId, GpioCallback* regularGpio, - GpioMap& mapToAdd); /** * @brief Performs the initial configuration of all GPIOs specified in the GpioMap mapToAdd. */ ReturnValue_t configureGpios(GpioMap& mapToAdd); + void parseFindeLineResult(int result, std::string& lineName); }; #endif /* LINUX_GPIO_LINUXLIBGPIOIF_H_ */ From 113c992f999681bc973dd4b5ac867dd737b27db4 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 17 Oct 2021 22:56:00 +0200 Subject: [PATCH 46/49] use char* instead --- src/fsfw/tcdistribution/PUSDistributor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsfw/tcdistribution/PUSDistributor.cpp b/src/fsfw/tcdistribution/PUSDistributor.cpp index 1a5f713d..284a14c9 100644 --- a/src/fsfw/tcdistribution/PUSDistributor.cpp +++ b/src/fsfw/tcdistribution/PUSDistributor.cpp @@ -29,7 +29,7 @@ PUSDistributor::TcMqMapIter PUSDistributor::selectDestination() { tcStatus = checker.checkPacket(currentPacket); if(tcStatus != HasReturnvaluesIF::RETURN_OK) { #if FSFW_VERBOSE_LEVEL >= 1 - std::string keyword; + const char* keyword = nullptr; if(tcStatus == TcPacketCheck::INCORRECT_CHECKSUM) { keyword = "checksum"; } From afe8fe6605d81b7d597e802b1b1ac980c3642014 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 18 Oct 2021 13:58:18 +0200 Subject: [PATCH 47/49] assign correct init value --- src/fsfw/tcdistribution/PUSDistributor.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/fsfw/tcdistribution/PUSDistributor.cpp b/src/fsfw/tcdistribution/PUSDistributor.cpp index 284a14c9..adab58c8 100644 --- a/src/fsfw/tcdistribution/PUSDistributor.cpp +++ b/src/fsfw/tcdistribution/PUSDistributor.cpp @@ -29,7 +29,7 @@ PUSDistributor::TcMqMapIter PUSDistributor::selectDestination() { tcStatus = checker.checkPacket(currentPacket); if(tcStatus != HasReturnvaluesIF::RETURN_OK) { #if FSFW_VERBOSE_LEVEL >= 1 - const char* keyword = nullptr; + const char* keyword = "unnamed error"; if(tcStatus == TcPacketCheck::INCORRECT_CHECKSUM) { keyword = "checksum"; } @@ -45,9 +45,6 @@ PUSDistributor::TcMqMapIter PUSDistributor::selectDestination() { else if(tcStatus == TcPacketCheck::INCOMPLETE_PACKET) { keyword = "incomplete packet"; } - else { - keyword = "unnamed error"; - } #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "PUSDistributor::handlePacket: Packet format invalid, " << keyword << " error" << std::endl; From cee42f9b70a4fc8b2bf2b593a0de6118a7173505 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Mon, 18 Oct 2021 14:34:11 +0200 Subject: [PATCH 48/49] one } was on the wrong side of an #endif --- src/fsfw/tmtcpacket/pus/tm/TmPacketStoredBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredBase.cpp b/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredBase.cpp index 20a8ed89..523fb619 100644 --- a/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredBase.cpp +++ b/src/fsfw/tmtcpacket/pus/tm/TmPacketStoredBase.cpp @@ -118,7 +118,7 @@ void TmPacketStoredBase::handleStoreFailure(const char *const packetType, Return "%d too large\n", packetType, sizeToReserve); break; } -#endif #endif } +#endif } From a077a1b5877032bedabe931ecdbc1a1048c3e333 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 18 Oct 2021 15:07:00 +0200 Subject: [PATCH 49/49] improved constexpr macros --- src/fsfw/tmtcpacket/SpacePacket.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/fsfw/tmtcpacket/SpacePacket.h b/src/fsfw/tmtcpacket/SpacePacket.h index dad8b95e..677ba023 100644 --- a/src/fsfw/tmtcpacket/SpacePacket.h +++ b/src/fsfw/tmtcpacket/SpacePacket.h @@ -71,12 +71,20 @@ protected: namespace spacepacket { -constexpr uint16_t getTcSpacePacketIdFromApid(uint16_t apid) { - return (0x18 << 8) | (((apid >> 8) & 0x07) << 8) | (apid & 0x00ff); +constexpr uint16_t getSpacePacketIdFromApid(bool isTc, uint16_t apid, + bool secondaryHeaderFlag = true) { + return (((isTc << 5) & 0x10) | ((secondaryHeaderFlag << 4) & 0x08) | + ((apid >> 8) & 0x07)) << 8 | (apid & 0x00ff); } -constexpr uint16_t getTmSpacePacketIdFromApid(uint16_t apid) { - return (0x08 << 8) | (((apid >> 8) & 0x07) << 8) | (apid & 0x00ff); +constexpr uint16_t getTcSpacketIdFromApid(uint16_t apid, + bool secondaryHeaderFlag = true) { + return getSpacePacketIdFromApid(true, apid, secondaryHeaderFlag); +} + +constexpr uint16_t getTmSpacketIdFromApid(uint16_t apid, + bool secondaryHeaderFlag = true) { + return getSpacePacketIdFromApid(false, apid, secondaryHeaderFlag); } }