diff --git a/framework.mk b/framework.mk index cb3e4f22..f2107a4c 100644 --- a/framework.mk +++ b/framework.mk @@ -28,11 +28,11 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/objectmanager/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/*.cpp) # select the OS -ifeq ($(OS),rtems) +ifeq ($(OS_FSFW),rtems) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/rtems/*.cpp) -else ifeq ($(OS),linux) +else ifeq ($(OS_FSFW),linux) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/linux/*.cpp) -else ifeq ($(OS),freeRTOS) +else ifeq ($(OS_FSFW),freeRTOS) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/FreeRTOS/*.cpp) else $(error invalid OS specified, valid OS are rtems, linux, freeRTOS) diff --git a/ipc/FwMessageTypes.h b/ipc/FwMessageTypes.h index 07e3d245..b59319aa 100644 --- a/ipc/FwMessageTypes.h +++ b/ipc/FwMessageTypes.h @@ -14,8 +14,9 @@ enum FW_MESSAGE_TYPE { MONITORING, MEMORY, PARAMETER, + FILE_SYSTEM_MESSAGE, FW_MESSAGES_COUNT, - FILE_SYSTEM_MESSAGE + }; } diff --git a/ipc/QueueFactory.h b/ipc/QueueFactory.h index 9a883fd8..09259ae3 100644 --- a/ipc/QueueFactory.h +++ b/ipc/QueueFactory.h @@ -18,7 +18,7 @@ public: */ static QueueFactory* instance(); - MessageQueueIF* createMessageQueue(size_t messageDepth = 3, + MessageQueueIF* createMessageQueue(uint32_t messageDepth = 3, size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE); void deleteMessageQueue(MessageQueueIF* queue); diff --git a/osal/FreeRTOS/QueueFactory.cpp b/osal/FreeRTOS/QueueFactory.cpp index a4ee5cf3..372d0d41 100644 --- a/osal/FreeRTOS/QueueFactory.cpp +++ b/osal/FreeRTOS/QueueFactory.cpp @@ -26,7 +26,7 @@ QueueFactory::QueueFactory() { QueueFactory::~QueueFactory() { } -MessageQueueIF* QueueFactory::createMessageQueue(size_t messageDepth, +MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) { return new MessageQueue(messageDepth, maxMessageSize); } diff --git a/osal/linux/QueueFactory.cpp b/osal/linux/QueueFactory.cpp index 2bacb815..268d0b99 100644 --- a/osal/linux/QueueFactory.cpp +++ b/osal/linux/QueueFactory.cpp @@ -28,7 +28,7 @@ QueueFactory::QueueFactory() { QueueFactory::~QueueFactory() { } -MessageQueueIF* QueueFactory::createMessageQueue(size_t messageDepth, +MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) { return new MessageQueue(messageDepth, maxMessageSize); } diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 2a97ab90..5c80862c 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -1,11 +1,58 @@ #include #include #include +#include // to be implemented by bsp -extern "C" void printChar(const char*); +extern "C" void printChar(const char*, bool errStream); + +#ifndef UT699 + +ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, + bool addCrToPreamble, bool buffered , bool errStream, uint16_t port): + isActive(true), logMessage(setMessage), + addCrToPreamble(addCrToPreamble), buffered(buffered), + errStream(errStream) { + if(buffered) { + // Set pointers if the stream is buffered. + setp( buf, buf + BUF_SIZE ); + } + preamble.reserve(MAX_PREAMBLE_SIZE); + preamble.resize(MAX_PREAMBLE_SIZE); +} + +void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { + char array[BUF_SIZE]; + uint32_t length = end - begin; + if (length > sizeof(array)) { + length = sizeof(array); + } + memcpy(array, begin, length); + + for(; begin != end; begin++){ + if(errStream) { + printChar(begin, true); + } + else { + printChar(begin, false); + } + } +} + +#endif int ServiceInterfaceBuffer::overflow(int c) { + if(not buffered and this->isActive) { + if (c != Traits::eof()) { + if(errStream) { + printChar(reinterpret_cast(&c), true); + } + else { + printChar(reinterpret_cast(&c), false); + } + } + return 0; + } // Handle output putChars(pbase(), pptr()); if (c != Traits::eof()) { @@ -20,53 +67,63 @@ int ServiceInterfaceBuffer::overflow(int c) { } int ServiceInterfaceBuffer::sync(void) { - if (this->isActive) { - Clock::TimeOfDay_t loggerTime; - Clock::getDateAndTime(&loggerTime); - std::string preamble; - if(addCrToPreamble) { - preamble += "\r"; + if(not this->isActive and not buffered) { + if(not buffered) { + setp(buf, buf + BUF_SIZE - 1); } - preamble += log_message + ": | " + zero_padded(loggerTime.hour, 2) - + ":" + zero_padded(loggerTime.minute, 2) + ":" - + zero_padded(loggerTime.second, 2) + "." - + zero_padded(loggerTime.usecond/1000, 3) + " | "; - // Write log_message and time - this->putChars(preamble.c_str(), preamble.c_str() + preamble.size()); - // Handle output - this->putChars(pbase(), pptr()); + return 0; } + if(not buffered) { + return 0; + } + + size_t preambleSize = 0; + auto preamble = getPreamble(&preambleSize); + // Write logMessage and time + this->putChars(preamble.data(), preamble.data() + preambleSize); + // Handle output + this->putChars(pbase(), pptr()); // This tells that buffer is empty again setp(buf, buf + BUF_SIZE - 1); return 0; } - - -#ifndef UT699 - -ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, - uint16_t port, bool addCrToPreamble) { - this->addCrToPreamble = addCrToPreamble; - this->log_message = set_message; - this->isActive = true; - setp( buf, buf + BUF_SIZE ); +bool ServiceInterfaceBuffer::isBuffered() const { + return buffered; } -void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { - char array[BUF_SIZE]; - uint32_t length = end - begin; - if (length > sizeof(array)) { - length = sizeof(array); +std::string ServiceInterfaceBuffer::getPreamble(size_t * preambleSize) { + Clock::TimeOfDay_t loggerTime; + Clock::getDateAndTime(&loggerTime); + size_t currentSize = 0; + char* parsePosition = &preamble[0]; + if(addCrToPreamble) { + preamble[0] = '\r'; + currentSize += 1; + parsePosition += 1; } - memcpy(array, begin, length); - - for(; begin != end; begin++){ - printChar(begin); + int32_t charCount = sprintf(parsePosition, + "%s: | %02" SCNu32 ":%02" SCNu32 ":%02" SCNu32 ".%03" SCNu32 " | ", + this->logMessage.c_str(), loggerTime.hour, + loggerTime.minute, + loggerTime.second, + loggerTime.usecond /1000); + if(charCount < 0) { + printf("ServiceInterfaceBuffer: Failure parsing preamble\r\n"); + return ""; } - + if(charCount > MAX_PREAMBLE_SIZE) { + printf("ServiceInterfaceBuffer: Char count too large for maximum " + "preamble size"); + return ""; + } + currentSize += charCount; + if(preambleSize != nullptr) { + *preambleSize = currentSize; + } + return preamble; } -#endif + #ifdef UT699 diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index a2bc4f4b..39ea25c2 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -1,67 +1,71 @@ #ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ #define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ +#include #include #include -#include #include #ifndef UT699 + +/** + * @brief This is the underlying stream buffer which implements the + * streambuf class and overloads the overflow() and sync() methods + * @details + * This class is used to modify the output of the stream, for example by adding. + * It also calls the char printing function which is implemented in the + * board supply package (BSP). + */ class ServiceInterfaceBuffer: - public std::basic_streambuf> { + public std::streambuf { friend class ServiceInterfaceStream; public: - ServiceInterfaceBuffer(std::string set_message, uint16_t port, - bool addCrToPreamble); + static constexpr uint8_t MAX_PREAMBLE_SIZE = 40; + + ServiceInterfaceBuffer(std::string setMessage, bool addCrToPreamble, + bool buffered, bool errStream, uint16_t port); + protected: bool isActive; - // This is called when buffer becomes full. If - // buffer is not used, then this is called every - // time when characters are put to stream. + //! This is called when buffer becomes full. If + //! buffer is not used, then this is called every + //! time when characters are put to stream. int overflow(int c = Traits::eof()) override; - // This function is called when stream is flushed, - // for example when std::endl is put to stream. + //! This function is called when stream is flushed, + //! for example when std::endl is put to stream. int sync(void) override; + bool isBuffered() const; private: - // For additional message information - std::string log_message; + //! For additional message information + std::string logMessage; + std::string preamble; // For EOF detection typedef std::char_traits Traits; - // This is useful for some terminal programs which do not have - // implicit carriage return with newline characters. + + //! This is useful for some terminal programs which do not have + //! implicit carriage return with newline characters. bool addCrToPreamble; - // Work in buffer mode. It is also possible to work without buffer. + //! Specifies whether the stream operates in buffered or unbuffered mode. + bool buffered; + //! This specifies to print to stderr and work in unbuffered mode. + bool errStream; + + //! Needed for buffered mode. static size_t const BUF_SIZE = 128; char buf[BUF_SIZE]; - // In this function, the characters are parsed. + //! In this function, the characters are parsed. void putChars(char const* begin, char const* end); - template - std::string zero_padded(const T& num, uint8_t width) { - std::ostringstream string_to_pad; - string_to_pad << std::setw(width) << std::setfill('0') << num; - std::string result = string_to_pad.str(); - if (result.length() > width) - { - result.erase(0, result.length() - width); - } - return result; - } + std::string getPreamble(size_t * preambleSize = nullptr); }; + #endif - - - - - - - #ifdef UT699 class ServiceInterfaceBuffer: public std::basic_streambuf > { diff --git a/serviceinterface/ServiceInterfaceStream.cpp b/serviceinterface/ServiceInterfaceStream.cpp index 40f52f1f..76481ed1 100644 --- a/serviceinterface/ServiceInterfaceStream.cpp +++ b/serviceinterface/ServiceInterfaceStream.cpp @@ -1,11 +1,32 @@ #include +ServiceInterfaceStream::ServiceInterfaceStream(std::string setMessage, + bool addCrToPreamble, bool buffered, bool errStream, uint16_t port) : + std::ostream(&streambuf), + streambuf(setMessage, addCrToPreamble, buffered, errStream, port) {} + void ServiceInterfaceStream::setActive( bool myActive) { - this->buf.isActive = myActive; + this->streambuf.isActive = myActive; } -ServiceInterfaceStream::ServiceInterfaceStream(std::string set_message, - bool addCrToPreamble, uint16_t port) : - std::basic_ostream>(&buf), - buf(set_message, port, addCrToPreamble) { +std::string ServiceInterfaceStream::getPreamble() { + return streambuf.getPreamble(); +} + +void ServiceInterfaceStream::print(std::string error, + bool withPreamble, bool withNewline, bool flush) { + if(not streambuf.isBuffered() and withPreamble) { + *this << getPreamble() << error; + } + else { + *this << error; + } + + if(withNewline) { + *this << "\n"; + } + // if mode is non-buffered, no need to flush. + if(flush and streambuf.isBuffered()) { + this->flush(); + } } diff --git a/serviceinterface/ServiceInterfaceStream.h b/serviceinterface/ServiceInterfaceStream.h index a445dced..9e19c228 100644 --- a/serviceinterface/ServiceInterfaceStream.h +++ b/serviceinterface/ServiceInterfaceStream.h @@ -3,29 +3,56 @@ #include #include -#include -#include #include -// Unfortunately, there must be a forward declaration of log_fe -// (MUST be defined in main), to let the system know where to write to. -namespace sif { -extern std::ostream debug; -extern std::ostream info; -extern std::ostream warning; -extern std::ostream error; -} - - -class ServiceInterfaceStream : - public std::basic_ostream> { -protected: - ServiceInterfaceBuffer buf; +/** + * Generic service interface stream which can be used like std::cout or + * std::cerr but has additional capability. Add preamble and timestamp + * to output. Can be run in buffered or unbuffered mode. + */ +class ServiceInterfaceStream : public std::ostream { public: - ServiceInterfaceStream( std::string set_message, - bool addCrToPreamble = false, uint16_t port = 1234); + /** + * This constructor is used by specifying the preamble message. + * Optionally, the output can be directed to stderr and a CR character + * can be prepended to the preamble. + * @param setMessage message of preamble. + * @param addCrToPreamble Useful for applications like Puttty. + * @param buffered specify whether to use buffered mode. + * @param errStream specify which output stream to use (stderr or stdout). + */ + ServiceInterfaceStream(std::string setMessage, + bool addCrToPreamble = false, bool buffered = true, + bool errStream = false, uint16_t port = 1234); + + //! An inactive stream will not print anything. void setActive( bool ); + + /** + * This can be used to retrieve the preamble in case it should be printed in + * the unbuffered mode. + * @return Preamle consisting of log message and timestamp. + */ + std::string getPreamble(); + + /** + * This prints an error with a preamble. Useful if using the unbuffered + * mode. Flushes in default mode (prints immediately). + */ + void print(std::string error, bool withPreamble = true, + bool withNewline = true, bool flush = true); + +protected: + ServiceInterfaceBuffer streambuf; }; +// Forward declaration of interface streams. These should be instantiated in +// main. They can then be used like std::cout or std::cerr. +namespace sif { +extern ServiceInterfaceStream debug; +extern ServiceInterfaceStream info; +extern ServiceInterfaceStream warning; +extern ServiceInterfaceStream error; +} #endif /* FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ */ diff --git a/storagemanager/LocalPool.h b/storagemanager/LocalPool.h index 2d61dea5..bb94a3be 100644 --- a/storagemanager/LocalPool.h +++ b/storagemanager/LocalPool.h @@ -24,7 +24,6 @@ * The local pool is NOT thread-safe. * @author Bastian Baetz */ - template class LocalPool: public SystemObject, public StorageManagerIF { public: @@ -48,9 +47,10 @@ public: * number of elements for each pool is determined. * The position of these values correspond to those in * element_sizes. - * @param registered Register the pool in object manager or not. Default is false (local pool). - * @param spillsToHigherPools - * A variable to determine whether higher n pools are used if the store is full. + * @param registered Register the pool in object manager or not. + * Default is false (local pool). + * @param spillsToHigherPools A variable to determine whether + * higher n pools are used if the store is full. */ LocalPool(object_id_t setObjectId, const uint16_t element_sizes[NUMBER_OF_POOLS], @@ -117,7 +117,7 @@ private: /** * @brief store represents the actual memory pool. * @details It is an array of pointers to memory, which was allocated with - * a \c new call on construction. + * a @c new call on construction. */ uint8_t* store[NUMBER_OF_POOLS]; /** diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index c74e95c0..7c2e8a71 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -12,7 +12,7 @@ * with a lock. * @author Bastian Baetz */ -template +template class PoolManager : public LocalPool { public: PoolManager(object_id_t setObjectId, @@ -27,6 +27,7 @@ public: ReturnValue_t deleteData(store_address_t) override; ReturnValue_t deleteData(uint8_t* buffer, size_t size, store_address_t* storeId = nullptr) override; + protected: ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault) override; diff --git a/storagemanager/PoolManager.tpp b/storagemanager/PoolManager.tpp index 9fb11776..a35b810c 100644 --- a/storagemanager/PoolManager.tpp +++ b/storagemanager/PoolManager.tpp @@ -48,4 +48,3 @@ inline ReturnValue_t PoolManager::deleteData(uint8_t* buffer, } #endif - diff --git a/storagemanager/StorageManagerIF.h b/storagemanager/StorageManagerIF.h index d5ac5818..f8aee819 100644 --- a/storagemanager/StorageManagerIF.h +++ b/storagemanager/StorageManagerIF.h @@ -11,7 +11,6 @@ using AccessorPair = std::pair; using ConstAccessorPair = std::pair; - /** * @brief This class provides an interface for intermediate data storage. * @details The Storage manager classes shall be used to store larger chunks of @@ -80,6 +79,7 @@ public: virtual ReturnValue_t deleteData(uint8_t* buffer, size_t size, store_address_t* storeId = nullptr) = 0; + /** * @brief Access the data by supplying a store ID. * @details @@ -100,6 +100,7 @@ public: virtual ReturnValue_t getData(store_address_t storeId, ConstStorageAccessor& constAccessor) = 0; + /** * @brief getData returns an address to data and the size of the data * for a given packet_id.