Started with a blank main file

- Added GPIO handling
- Added a logger class with additional static debug log handling

Tested, functional
This commit is contained in:
Matthias Mitscherlich
2024-03-11 15:45:48 +01:00
parent 4b31b6c618
commit a0d13f08c1
10 changed files with 1067 additions and 4 deletions
+178
View File
@@ -0,0 +1,178 @@
// --------------------------------------------------------------------------------------------------------------------
/// \file logger.h
/// \brief File description
// --------------------------------------------------------------------------------------------------------------------
//
// vbchaos software design
//
// --------------------------------------------------------------------------------------------------------------------
/// $Revision: $
/// $Author: $
/// $Date: $
// (c) 2023 vbchaos
// --------------------------------------------------------------------------------------------------------------------
#ifndef MAIN_PLATFORM_INC_LOGGER_H_
#define MAIN_PLATFORM_INC_LOGGER_H_
/**
* logger implementation
* \defgroup logger
* \brief {group_description}
* \addtogroup {Layer}
*
* Detailed description
* @{
*/
// --------------------------------------------------------------------------------------------------------------------
// Include files
// --------------------------------------------------------------------------------------------------------------------
// CompilerIncludes
// All include files that are provided by the compiler directly
#include <stdint.h>
#include <list>
#include <string>
#include <cstring>
// ProjectIncludes
// All include files that are provided by the project
#include <ISerialBus.h>
// --------------------------------------------------------------------------------------------------------------------
// Constant and macro definitions
// --------------------------------------------------------------------------------------------------------------------
#define ENABLE_SERIAL_LOGGING
#if defined(ENABLE_SERIAL_LOGGING)
#define LOGGER_LOG(severity,...) \
debugLogger.log(__FILE__, __func__, __LINE__, severity, ##__VA_ARGS__)
#else
#define LOGGER_LOG(severity, message)
#endif
/**
* Logs an print message
* \memberof Logger
*/
#define LOGGER_PRINT(...) LOGGER_LOG(logger::LogType::LOGTYPE_PRINT, ##__VA_ARGS__)
/**
* Logs an debug message
* \memberof Logger
*/
#define LOGGER_DEBUG(...) LOGGER_LOG(logger::LogType::LOGTYPE_DEBUG, ##__VA_ARGS__)
/**
* Logs an info message
* \memberof Logger
*/
#define LOGGER_INFO(...) LOGGER_LOG(logger::LogType::LOGTYPE_INFO, ##__VA_ARGS__)
/**
* Logs an warning message
* \memberof Logger
*/
#define LOGGER_WARNING(...) LOGGER_LOG(logger::LogType::LOGTYPE_WARNING, ##__VA_ARGS__)
/**
* Logs an success message
* \memberof Logger
*/
#define LOGGER_SUCCESS(...) LOGGER_LOG(logger::LogType::LOGTYPE_SUCCESS, ##__VA_ARGS__)
/**
* Logs an error message
* \memberof Logger
*/
#define LOGGER_ERROR(...) LOGGER_LOG(logger::LogType::LOGTYPE_ERROR, ##__VA_ARGS__)
// --------------------------------------------------------------------------------------------------------------------
// Type definitions.
// --------------------------------------------------------------------------------------------------------------------
class logger;
extern logger debugLogger;
// --------------------------------------------------------------------------------------------------------------------
// Function declarations
// --------------------------------------------------------------------------------------------------------------------
class logger
{
// -----------------------------------------------------------------------------------------------------------------
// Public Section
// -----------------------------------------------------------------------------------------------------------------
public:
typedef enum
{
LOGTYPE_PRINT, /**< Raw print */
LOGTYPE_DEBUG, /**< Debug information only; will not be stored on SD-card */
LOGTYPE_INFO, /**< Informational messages of important events */
LOGTYPE_WARNING, /**< Recoverable fault */
LOGTYPE_SUCCESS, /**< A specific success message */
LOGTYPE_ERROR /**< Unrecoverable fault */
} LogType;
// Class Constructor
logger(uint32_t queuesize, ISerialBus<uint8_t>& serialPort);
FunctionStatus log(const char* fileName, const char* functionName, int lineNumber, LogType logType, const char* format, ...);
// The Logger task - should be called by the system scheduler regularly
void task();
// -----------------------------------------------------------------------------------------------------------------
// Protected Section
// -----------------------------------------------------------------------------------------------------------------
protected:
// -----------------------------------------------------------------------------------------------------------------
// Private Section
// -----------------------------------------------------------------------------------------------------------------
private:
struct LogQueueItem
{
std::string fileName;
std::string functionName;
std::string context;
uint32_t lineNumber;
LogType logType;
};
struct typeParameters
{
LogType logType;
std::string vt100Prefix;
std::string logPrefix;
std::string vt100Postfix;
};
void composeTypeParameterList(void);
void composeLogQueueItem(struct LogQueueItem* logQueueItem, std::string fileName, std::string functionName,
int lineNumber, LogType logType, std::string context);
std::list<struct typeParameters> typeParameterList;
std::list<struct LogQueueItem> queue;
ISerialBus<uint8_t>& port;
uint32_t queuesize;
uint32_t numberOfLostMessages;
};
/** @} */
#endif /* MAIN_PLATFORM_INC_LOGGER_H_ */
+224
View File
@@ -0,0 +1,224 @@
// --------------------------------------------------------------------------------------------------------------------
/// \file logger.cpp
/// \brief Description
// --------------------------------------------------------------------------------------------------------------------
//
// vbchaos software design
//
// --------------------------------------------------------------------------------------------------------------------
/// $Revision: $
/// $Author: $
/// $Date: $
// (c) 2023 vbchaos
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Include files
// --------------------------------------------------------------------------------------------------------------------
#include <logger.h>
#include <algorithm>
#include <cstdio>
#include <cstdarg>
// --------------------------------------------------------------------------------------------------------------------
// Constant and macro definitions
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Type definitions
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// File-scope variables
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Function declarations
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Function definitions
// --------------------------------------------------------------------------------------------------------------------
logger::logger(uint32_t queuesize, ISerialBus<uint8_t>& serialPort) : port {serialPort}, queuesize {queuesize}
{
numberOfLostMessages = 0;
// Compose the debug type level list
composeTypeParameterList();
}
FunctionStatus logger::log(const char* fileName, const char* functionName, int lineNumber, LogType logType, const char* format, ...)
{
FunctionStatus returnValue = FUNCTION_STATUS_OK;
#if defined(ENABLE_SERIAL_LOGGING)
bool overflowRecovery = false;
int nrOfMessages;
struct LogQueueItem logQueueItem;
va_list ap;
nrOfMessages = queue.size();
if((nrOfMessages == queuesize - 1) && !overflowRecovery)
{
// Queue almost full, only one entry left. Log a warning instead
composeLogQueueItem(&logQueueItem, __FILE__, __func__, __LINE__, LOGTYPE_WARNING, "Log queue overflow");
queue.push_back(logQueueItem);
overflowRecovery = true;
numberOfLostMessages = 1;
}
else if((nrOfMessages == 0) && overflowRecovery)
{
// Queue empty again after an overflow
char str[128];
snprintf(str, sizeof(str) / sizeof(str[0]), "%d messages lost", (unsigned int)numberOfLostMessages);
composeLogQueueItem(&logQueueItem, __FILE__, __func__, __LINE__, LOGTYPE_WARNING, str);
queue.push_back(logQueueItem);
overflowRecovery = false;
}
else if(!overflowRecovery)
{
// Normal behaviour, queue not full
char str[128];
va_start(ap, format);
vsnprintf(str, sizeof(str) / sizeof(str[0]), format, ap);
va_end(ap);
composeLogQueueItem(&logQueueItem, fileName, functionName, lineNumber, logType, str);
queue.push_back(logQueueItem);
}
else
{
// Count number of lost messages
++numberOfLostMessages;
}
#endif
return returnValue;
}
void logger::composeTypeParameterList(void)
{
typeParameterList.clear();
// Add Debug information
typeParameterList.push_back({LOGTYPE_DEBUG, "\033[33m", "DBG", "\033[0m"});
// Add Warning information
typeParameterList.push_back({LOGTYPE_WARNING, "\033[35m", "WRN", "\033[0m"});
// Add Error information
typeParameterList.push_back({LOGTYPE_ERROR, "\033[31m", "ERR", "\033[0m"});
// Add Success information
typeParameterList.push_back({LOGTYPE_SUCCESS, "\033[32m", "SCS", "\033[0m"});
// Add Information information
typeParameterList.push_back({LOGTYPE_INFO, "\033[33m", "INF", "\033[0m"});
// Add Print information
typeParameterList.push_back({LOGTYPE_PRINT, "", "DBG", "\033[0m"});
}
#if defined(ENABLE_SERIAL_LOGGING)
void logger::composeLogQueueItem(struct LogQueueItem* logQueueItem, std::string fileName, std::string functionName,
int lineNumber, LogType logType, std::string context)
{
logQueueItem->logType = logType;
logQueueItem->context = context;
// strncpy((char*)&(logQueueItem->context[0]), context, contextSize);
// logQueueItem->context[contextSize - 1] = '\0';
if(logType != LOGTYPE_PRINT)
{
int fileNameIndex = 0;
// If filename starts with "src/", strip this part
if((fileName[0] == 's') &&
(fileName[1] == 'r') &&
(fileName[2] == 'c') &&
(fileName[3] == '/'))
{
fileNameIndex = 4;
}
// It is known that the strncpy use can potentially truncate the source string, meaning
// that the target string size is smaller then the original string
// This is not a problem in this particular case, so the compiler warning is disabled
// for this situation
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-truncation"
// All logtypes except LOGTYPE_PRINT need filename, functionname and linenumber.
logQueueItem->fileName = fileName;
logQueueItem->functionName = functionName;
// strncpy((char*)&(logQueueItem->fileName[0]), &fileName[fileNameIndex], fileNameSize);
// strncpy((char*)&(logQueueItem->functionName[0]), functionName, functionNameSize);
#pragma GCC diagnostic pop
logQueueItem->lineNumber = lineNumber;
// Fix terminating null byte in strncpy in case string to be copied is too long
// logQueueItem->fileName[fileNameSize - 1] = '\0';
// logQueueItem->functionName[functionNameSize - 1] = '\0';
}
}
#endif
void logger::task()
{
struct LogQueueItem logQueueItem;
// Check if there is anything in the queue
// If queue is empty, return to scheduler
if (queue.empty())
{
return;
}
// Get the first log item from queue
logQueueItem = queue.front();
// Remove the item from the queue
this->queue.pop_front();
if(logQueueItem.logType == LOGTYPE_PRINT)
{
// Raw print
#if defined(ENABLE_SERIAL_LOGGING)
port.write((uint8_t*)logQueueItem.context.c_str(), logQueueItem.context.length() + 1);
#endif
}
else
{
unsigned int seconds = 0;
#if defined(ENABLE_SERIAL_LOGGING)
// Formatted print
// Find the correct Log level type
auto it = std::find_if(typeParameterList.begin(), typeParameterList.end(), [&logQueueItem](const struct typeParameters& obj) {return obj.logType == logQueueItem.logType;});
std::string outputString = it->vt100Prefix + " "
+ it->vt100Prefix + " "
+ std::to_string(seconds) + " "
+ logQueueItem.fileName + " "
+ logQueueItem.functionName + " "
+ "(line " + std::to_string(logQueueItem.lineNumber) + "): "
+ logQueueItem.context + " "
+ it->vt100Postfix;
port.write((uint8_t*)outputString.c_str(), outputString.length() + 1);
#endif
}
}