Fixed ISerialBus interface and added device and register address fields so that future i2c and SPI devices can be addressed, to. Added i2c HAL. Tested, working.

The update on the interface required FunctionStatus and the logger to be updated, too
This commit is contained in:
Matthias Mitscherlich
2024-03-11 17:00:07 +01:00
parent a0d13f08c1
commit d5e389f1bd
11 changed files with 137 additions and 530 deletions
+1 -2
View File
@@ -5,13 +5,12 @@ idf_component_register(
SRCS # list the source files of this component
"main.cpp"
# "old/src/bmp280.cpp"
"hal/src/i2c.cpp"
"hal/src/gpio.cpp"
"hal/src/uart.cpp"
"platform/src/logger.cpp"
# "old/src/i2c.cpp"
# "old/src/wifi.cpp"
# "old/src/logger.cpp"
# "old/src/led_strip_encoder.c"
# "old/src/ledmatrix.cpp"
# "old/src/clock.cpp"
+1
View File
@@ -58,6 +58,7 @@ typedef enum
//!< instance is already initialized
FUNCTION_STATUS_UNDEFINED_VALUE = 4, //!< The function failed because an undefined value was used
//!< This most probably happened when checking an enum
FUNCTION_STATUS_NOT_IMPLEMENTED = 5, //!< The required functionality is not (yet) implemented
// Interfaces/Busses
FUNCTION_STATUS_NOT_OPEN = 10, //!< The Interface cannot be used because it has not been opened
FUNCTION_STATUS_ALREADY_OPEN = 11, //!< The interface cannot be opened because it is already open
+4 -2
View File
@@ -45,6 +45,8 @@
// Constant and macro definitions
// --------------------------------------------------------------------------------------------------------------------
#define NO_DEVICE_ADDRESS (255)
#define NO_REGISTER_ADDRESS (255)
// --------------------------------------------------------------------------------------------------------------------
// Type definitions.
@@ -70,9 +72,9 @@ class ISerialBus
FunctionStatus close() {status = CLOSED; return FUNCTION_STATUS_OK;}
virtual FunctionStatus read(T* buffer, uint32_t length, uint32_t* actualLength) = 0;
virtual FunctionStatus read(T deviceAddress, T registerAddress, T* buffer, uint32_t length, uint32_t* actualLength) = 0;
virtual FunctionStatus write(T* buffer, uint32_t length) = 0;
virtual FunctionStatus write(T deviceAddress, T registerAddress, T* buffer, uint32_t length) = 0;
@@ -1,5 +1,5 @@
// --------------------------------------------------------------------------------------------------------------------
/// \file gpio.h
/// \file i2c.h
/// \brief File description
// --------------------------------------------------------------------------------------------------------------------
//
@@ -13,8 +13,18 @@
// --------------------------------------------------------------------------------------------------------------------
#ifndef MAIN_INC_GPIO_H_
#define MAIN_INC_GPIO_H_
#ifndef MAIN_HAL_INC_I2C_H_
#define MAIN_HAL_INC_I2C_H_
/**
* i2c implementation
* \defgroup i2c
* \brief {group_description}
* \addtogroup {Layer}
*
* Detailed description
* @{
*/
@@ -29,55 +39,58 @@
// ProjectIncludes
// All include files that are provided by the project
#include "ISerialBus.h"
#include "driver/i2c.h"
// --------------------------------------------------------------------------------------------------------------------
// Constant and macro definitions
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Type definitions.
// --------------------------------------------------------------------------------------------------------------------
typedef enum
{
GPIO_DIRECTION_INPUT = 0,
GPIO_DIRECTION_OUTPUT = 1
} GPIO_Direction_t;
typedef enum
{
GPIO_VALUE_LOW = 0,
GPIO_VALUE_HIGH = 1
} GPIO_Value_t;
// --------------------------------------------------------------------------------------------------------------------
// Function declarations
// --------------------------------------------------------------------------------------------------------------------
class GPIO
class i2c : public ISerialBus<uint8_t>
{
// -----------------------------------------------------------------------------------------------------------------
// Public Section
// -----------------------------------------------------------------------------------------------------------------
public:
// Class Constructor
i2c(i2c_port_t* port);
~i2c();
GPIO(int number, GPIO_Direction_t direction);
FunctionStatus read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, uint32_t length, uint32_t* actualLength);
bool SetOutput(GPIO_Value_t value);
FunctionStatus write(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, uint32_t length);
GPIO_Value_t GetInput(void);
// -----------------------------------------------------------------------------------------------------------------
// Protected Section
// -----------------------------------------------------------------------------------------------------------------
protected:
// -----------------------------------------------------------------------------------------------------------------
// Private Section
// -----------------------------------------------------------------------------------------------------------------
private:
int number;
void intWrite(uint8_t slaveAddress, uint8_t registerAddress, uint8_t* data, uint8_t length);
void intRead(uint8_t slaveAddress, uint8_t registerAddress, uint8_t* data, uint8_t length);
GPIO_Direction_t direction;
i2c_port_t* port;
GPIO_Value_t value = GPIO_VALUE_LOW;
};
/** @} */
#endif /* MAIN_INC_GPIO_H_ */
#endif /* MAIN_HAL_INC_I2C_H_ */
+2 -2
View File
@@ -67,9 +67,9 @@ class uart : public ISerialBus<uint8_t>
uart(uart_port_t* uartPort);
~uart();
FunctionStatus read(uint8_t* buffer, uint32_t length, uint32_t* actualLength);
FunctionStatus read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, uint32_t length, uint32_t* actualLength);
FunctionStatus write(uint8_t* buffer, uint32_t length);
FunctionStatus write(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, uint32_t length);
// -----------------------------------------------------------------------------------------------------------------
// Protected Section
@@ -1,5 +1,5 @@
// --------------------------------------------------------------------------------------------------------------------
/// \file gpio.cpp
/// \file i2c.cpp
/// \brief Description
// --------------------------------------------------------------------------------------------------------------------
//
@@ -17,16 +17,13 @@
// Include files
// --------------------------------------------------------------------------------------------------------------------
#include <gpio.h>
#include "driver/gpio.h"
#include <i2c.h>
// --------------------------------------------------------------------------------------------------------------------
// Constant and macro definitions
// --------------------------------------------------------------------------------------------------------------------
#define I2C_MASTER_TIMEOUT_MS 1000
// --------------------------------------------------------------------------------------------------------------------
// Type definitions
@@ -49,58 +46,68 @@
// Function definitions
// --------------------------------------------------------------------------------------------------------------------
GPIO::GPIO(int number, GPIO_Direction_t direction)
{
this->number = number;
this->direction = direction;
//zero-initialize the config structure.
gpio_config_t io_conf = {};
//disable interrupt
io_conf.intr_type = GPIO_INTR_DISABLE;
//set as output mode
io_conf.mode = (this->direction == GPIO_DIRECTION_OUTPUT) ? GPIO_MODE_OUTPUT : GPIO_MODE_INPUT;
//bit mask of the pins that you want to set
io_conf.pin_bit_mask = (1ULL << this->number);
//disable pull-down mode
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
//disable pull-up mode
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
//configure GPIO with the given settings
ESP_ERROR_CHECK(gpio_config(&io_conf));
i2c::i2c(i2c_port_t* port) : port {port}
{
}
i2c::~i2c()
{
}
bool GPIO::SetOutput(GPIO_Value_t value)
FunctionStatus i2c::write(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, uint32_t length)
{
bool returnValue = false;
FunctionStatus returnValue = FUNCTION_STATUS_OK;
if (this->direction == GPIO_DIRECTION_OUTPUT)
if (status == OPEN)
{
ESP_ERROR_CHECK(gpio_set_level((gpio_num_t)this->number, (uint32_t)value));
this->value = value;
returnValue = true;
intWrite(deviceAddress, registerAddress, buffer, length);
}
else
{
returnValue = false;
returnValue = FUNCTION_STATUS_NOT_OPEN;
}
return returnValue;
}
GPIO_Value_t GPIO::GetInput(void)
FunctionStatus i2c::read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, uint32_t length, uint32_t* actualLength)
{
if (gpio_get_level((gpio_num_t)this->number))
FunctionStatus returnValue = FUNCTION_STATUS_OK;
if (status == OPEN)
{
this->value = GPIO_VALUE_HIGH;
intRead(deviceAddress, registerAddress, buffer, length);
*actualLength = length;
}
else
{
this->value = GPIO_VALUE_LOW;
returnValue = FUNCTION_STATUS_NOT_OPEN;
}
return this->value;
return returnValue;
}
void i2c::intWrite(uint8_t slaveAddress, uint8_t registerAddress, uint8_t* data, uint8_t length)
{
uint8_t buffer[length + 1];
buffer[0] = registerAddress;
for (int i = 0; i < length; i++)
{
buffer[i+1] = data[i];
}
ESP_ERROR_CHECK(i2c_master_write_to_device(*port, slaveAddress, buffer, sizeof(buffer), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS));
}
void i2c::intRead(uint8_t slaveAddress, uint8_t registerAddress, uint8_t* data, uint8_t length)
{
ESP_ERROR_CHECK(i2c_master_write_read_device(*port, slaveAddress, &registerAddress, 1, data, length, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS));
}
+13 -3
View File
@@ -57,13 +57,23 @@ uart::~uart()
}
FunctionStatus uart::write(uint8_t* buffer, uint32_t length)
FunctionStatus uart::write(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, uint32_t length)
{
FunctionStatus returnValue = FUNCTION_STATUS_OK;
if (status == OPEN)
{
uart_write_bytes(*this->port, (const void*)buffer, length);
// For UART devices it is allowed to ignore the device or register address if it is requested as such
// The common case is that both addresses are ignorable since UARTs are mostly not used this way, so this
// implementation contains a shortcut and will immediatly write the buffer to the bus
if ((deviceAddress == NO_DEVICE_ADDRESS) && (registerAddress == NO_REGISTER_ADDRESS))
{
uart_write_bytes(*this->port, (const void*)buffer, length);
}
else
{
returnValue = FUNCTION_STATUS_NOT_IMPLEMENTED;
}
}
else
{
@@ -73,7 +83,7 @@ FunctionStatus uart::write(uint8_t* buffer, uint32_t length)
return returnValue;
}
FunctionStatus uart::read(uint8_t* buffer, uint32_t length, uint32_t* actualLength)
FunctionStatus uart::read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, uint32_t length, uint32_t* actualLength)
{
FunctionStatus returnValue = FUNCTION_STATUS_OK;
+34 -9
View File
@@ -29,6 +29,7 @@
// HAL includes
#include "gpio.h"
#include "i2c.h"
#include "uart.h"
// Platform includes
@@ -47,8 +48,6 @@
// File-scope variables
// --------------------------------------------------------------------------------------------------------------------
static uart_port_t uartPort = UART_NUM_0;
static TaskHandle_t loggerTaskHandle;
// --------------------------------------------------------------------------------------------------------------------
// Function declarations
@@ -72,10 +71,10 @@ extern "C" void app_main(void)
ret = nvs_flash_init();
}
//--------------------------------------------
// -----------------------------------------------------------------------------------------------------------------
// UART
//
const uart_config_t uartConfig =
uart_config_t uartConfig =
{
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
@@ -85,16 +84,17 @@ extern "C" void app_main(void)
.rx_flow_ctrl_thresh = 0,
.source_clk = UART_SCLK_DEFAULT
};
static uart_port_t debugUart = UART_NUM_0;
ESP_ERROR_CHECK(uart_param_config(debugUart, &uartConfig));
ESP_ERROR_CHECK(uart_set_pin(debugUart, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
ESP_ERROR_CHECK(uart_driver_install(debugUart, 1024, 1024, 0, NULL, 0));
ESP_ERROR_CHECK(uart_param_config(uartPort, &uartConfig));
ESP_ERROR_CHECK(uart_set_pin(uartPort, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
ESP_ERROR_CHECK(uart_driver_install(uartPort, 1024, 1024, 0, NULL, 0));
uart uartDebug = uart(&uartPort);
uart uartDebug = uart(&debugUart);
uartDebug.open();
// -----------------------------------------------------------------------------------------------------------------
// System-wide Debug Logger
//
logger debugLogger = logger(16, uartDebug);
// Call the logger executable within a dedicated task and forget about it afterwards
@@ -107,6 +107,31 @@ extern "C" void app_main(void)
LOGGER_PRINT("Release: %d.%d \n\r", MAJORRELEASE, MINORRELEASE);
LOGGER_PRINT("Compiled on %s at %s\n\r\n\r\n\r", __DATE__, __TIME__);
// -----------------------------------------------------------------------------------------------------------------
// I2C Masterbus for sensoring peripherals
//
i2c_port_t i2c_master_port = I2C_NUM_0;
i2c_config_t i2cConfig = {
.mode = I2C_MODE_MASTER,
.sda_io_num = (int)4,
.scl_io_num = (int)5,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master = 400000,
.clk_flags = 0
};
ESP_ERROR_CHECK(i2c_param_config(i2c_master_port, &i2cConfig));
ESP_ERROR_CHECK(i2c_driver_install(i2c_master_port, i2cConfig.mode, 0, 0, 0));
i2c i2cSensor = i2c(&i2c_master_port);
i2cSensor.open();
uint8_t i2cData[2] = {0x12, 0x34};
i2cSensor.write(0x40, 0x00, i2cData, 2);
gpio debugIO = gpio(2, gpio::Direction_t::GPIO_DIRECTION_OUTPUT, gpio::Value_t::GPIO_VALUE_LOW);
-196
View File
@@ -1,196 +0,0 @@
// --------------------------------------------------------------------------------------------------------------------
/// \file logger.h
/// \brief File description
// --------------------------------------------------------------------------------------------------------------------
//
// vbchaos software design
//
// --------------------------------------------------------------------------------------------------------------------
/// $Revision: $
/// $Author: $
/// $Date: $
// (c) 2023 vbchaos
// --------------------------------------------------------------------------------------------------------------------
#ifndef MAIN_INC_LOGGER_H_
#define MAIN_INC_LOGGER_H_
/**
* Logger implementation
* \defgroup Logger
* \brief Implementation of a non-blocking logger for debug purpose
* \ingroup Platform
*
* A non-blocking logger that implements its own task with very low (unimportant)
* priority
* @{
*/
// --------------------------------------------------------------------------------------------------------------------
// Include files
// --------------------------------------------------------------------------------------------------------------------
// CompilerIncludes
// All include files that are provided by the compiler directly
#include <stdbool.h>
#include <stdint.h>
// ProjectIncludes
// All include files that are provided by the project
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "driver/uart_select.h"
// --------------------------------------------------------------------------------------------------------------------
// Constant and macro definitions
// --------------------------------------------------------------------------------------------------------------------
/**
* Logs an error
* \memberof Logger
*/
#define LOGGER_ERROR(...) \
Logger::Logger_log(__FILE__, __func__, __LINE__, LOGTYPE_ERROR, ##__VA_ARGS__)
/**
* Logs a success
* \memberof Logger
*/
#define LOGGER_SUCCESS(...) \
Logger::Logger_log(__FILE__, __func__, __LINE__, LOGTYPE_SUCCESS, ##__VA_ARGS__)
/**
* Logs an error
* \memberof Logger
*/
#define LOGGER_WARNING(...) \
Logger::Logger_log(__FILE__, __func__, __LINE__, LOGTYPE_WARNING, ##__VA_ARGS__)
/**
* Logs an error
* \memberof Logger
*/
#define LOGGER_INFO(...) \
Logger::Logger_log(__FILE__, __func__, __LINE__, LOGTYPE_INFO, ##__VA_ARGS__)
/**
* Logs an error
* \memberof Logger
*/
#define LOGGER_DEBUG(...) \
Logger::Logger_log(__FILE__, __func__, __LINE__, LOGTYPE_DEBUG, ##__VA_ARGS__)
/**
* Logs an error
* \memberof Logger
*/
#define LOGGER_PRINT(...) \
Logger::Logger_log("", "", 0, LOGTYPE_PRINT, ##__VA_ARGS__)
/**
* Logs an error
* \memberof Logger
*/
#define LOGGER_ERROR_ISR(...) \
Logger::Logger_logISR(__FILE__, __func__, __LINE__, LOGTYPE_ERROR, ##__VA_ARGS__)
/**
* Logs a success
* \memberof Logger
*/
#define LOGGER_SUCCESS_ISR(...) \
Logger::Logger_logISR(__FILE__, __func__, __LINE__, LOGTYPE_ERROR, ##__VA_ARGS__)
/**
* Logs an error
* \memberof Logger
*/
#define LOGGER_WARNING_ISR(...) \
Logger::Logger_logISR(__FILE__, __func__, __LINE__, LOGTYPE_WARNING, ##__VA_ARGS__)
/**
* Logs an error
* \memberof Logger
*/
#define LOGGER_INFO_ISR(...) \
Logger::Logger_logISR(__FILE__, __func__, __LINE__, LOGTYPE_INFO, ##__VA_ARGS__)
/**
* Logs an error
* \memberof Logger
*/
#define LOGGER_DEBUG_ISR(a, ...) \
Logger::Logger_logISR(a, __FILE__, __func__, __LINE__, LOGTYPE_DEBUG, ##__VA_ARGS__)
/**
* Logs an error
* \memberof Logger
*/
#define LOGGER_PRINT_ISR(a, ...) \
Logger::Logger_logISR(a, "", "", 0, LOGTYPE_PRINT, ##__VA_ARGS__)
// --------------------------------------------------------------------------------------------------------------------
// Type definitions.
// --------------------------------------------------------------------------------------------------------------------
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;
struct LogQueueItem
{
char fileName[32];
char functionName[32];
char context[128];
int lineNumber;
LogType logType;
};
// --------------------------------------------------------------------------------------------------------------------
// Function declarations
// --------------------------------------------------------------------------------------------------------------------
class Logger
{
public:
static uart_port_t uartPort;
static int queuesize;
static QueueHandle_t logQueue;
Logger(int queuesize, uart_port_t uartPort);
static void Logger_log(const char* fileName, const char* functionName, int lineNumber, LogType logType, const char* format, ...);
static void Logger_logISR(struct Logger* self, const char* fileName, const char* functionName, int lineNumber, LogType logType, const char* context);
private:
static TaskHandle_t logTaskHandle;
static void loggerTask(void* parameters);
static void composeLogQueueItem(struct LogQueueItem* logQueueItem, const char* fileName, const char* functionName,
int lineNumber, LogType logType, const char* context);
};
/** @} */
#endif /* MAIN_INC_LOGGER_H_ */
-254
View File
@@ -1,254 +0,0 @@
// --------------------------------------------------------------------------------------------------------------------
/// \file logger.cpp
/// \brief Description
// --------------------------------------------------------------------------------------------------------------------
//
// vbchaos software design
//
// --------------------------------------------------------------------------------------------------------------------
/// $Revision: $
/// $Author: $
/// $Date: $
// (c) 2023 vbchaos
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Include files
// --------------------------------------------------------------------------------------------------------------------
#include <string.h>
#include <stdarg.h>
#include "logger.h"
// --------------------------------------------------------------------------------------------------------------------
// Constant and macro definitions
// --------------------------------------------------------------------------------------------------------------------
#define ENABLE_SERIAL_LOGGING
//#undef ENABLE_SERIAL_LOGGING
// --------------------------------------------------------------------------------------------------------------------
// Type definitions
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// File-scope variables
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Function declarations
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Function definitions
// --------------------------------------------------------------------------------------------------------------------
TaskHandle_t Logger::logTaskHandle = NULL;
uart_port_t Logger::uartPort = 0;
QueueHandle_t Logger::logQueue = NULL;
int Logger::queuesize = 0;
Logger::Logger(int queuesize, uart_port_t uartPort)
{
Logger::uartPort = uartPort;
Logger::queuesize = queuesize;
logQueue = xQueueCreate(queuesize, sizeof(struct LogQueueItem));
xTaskCreate(loggerTask, (const char*)"loggerTask", 3072, NULL, 3, &logTaskHandle);
}
void Logger::Logger_log(const char* fileName, const char* functionName, int lineNumber, LogType logType, const char* format, ...)
{
#if defined(ENABLE_SERIAL_LOGGING)
static int nrLostMessages = 0;
static bool overflowRecovery = false;
int nrOfMessages;
struct LogQueueItem logQueueItem;
va_list ap;
nrOfMessages = uxQueueMessagesWaiting(Logger::logQueue);
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");
(void)xQueueSend(logQueue, &logQueueItem, 0);
overflowRecovery = true;
nrLostMessages = 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", nrLostMessages);
composeLogQueueItem(&logQueueItem, __FILE__, __func__, __LINE__, LOGTYPE_WARNING, str);
(void)xQueueSend(logQueue, &logQueueItem, 0);
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);
(void)xQueueSend(logQueue, &logQueueItem, 0);
}
else
{
// Count number of lost messages
++nrLostMessages;
}
#endif
}
void Logger_logISR(struct Logger* self, const char* fileName, const char* functionName, int lineNumber, LogType logType, const char* context)
{
#if defined(ENABLE_LOGGING)
if (self->initialized)
{
struct LogQueueItem logQueueItem;
portBASE_TYPE higherPriorityTaskWoken = pdFALSE;
composeLogQueueItem(&logQueueItem, fileName, functionName, lineNumber, logType, context);
if(xQueueSendFromISR(self->logQueue, &logQueueItem, &higherPriorityTaskWoken) != pdTRUE)
{
// Queue failed
}
portEND_SWITCHING_ISR(higherPriorityTaskWoken);
}
#endif
}
#if defined(ENABLE_SERIAL_LOGGING)
void Logger::composeLogQueueItem(struct LogQueueItem* logQueueItem, const char* fileName, const char* functionName,
int lineNumber, LogType logType, const char* context)
{
const size_t fileNameSize = sizeof(logQueueItem->fileName) / sizeof(logQueueItem->fileName[0]);
const size_t functionNameSize = sizeof(logQueueItem->functionName) / sizeof(logQueueItem->functionName[0]);
const size_t contextSize = sizeof(logQueueItem->context) / sizeof(logQueueItem->context[0]);
logQueueItem->logType = logType;
strncpy(&(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.
strncpy(&(logQueueItem->fileName[0]), &fileName[fileNameIndex], fileNameSize);
strncpy(&(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::loggerTask(void* parameters)
{
while(true)
{
struct LogQueueItem logQueueItem;
xQueueReceive(logQueue, &logQueueItem, portMAX_DELAY);
if(logQueueItem.logType == LOGTYPE_PRINT)
{
// Raw print
#if defined(ENABLE_SERIAL_LOGGING)
uart_write_bytes(uartPort, logQueueItem.context, strlen(logQueueItem.context));
#endif
}
else
{
#if defined(ENABLE_SERIAL_LOGGING)
char str[256];
char* vt100Prefix = "";
const char* vt100Postfix = "\033[0m";
#endif
#if defined(ENABLE_SERIAL_LOGGING)
if(logQueueItem.logType == LOGTYPE_INFO)
{
vt100Prefix = "\033[33m";
}
else if(logQueueItem.logType == LOGTYPE_WARNING)
{
vt100Prefix = "\033[35m";
}
else if(logQueueItem.logType == LOGTYPE_ERROR)
{
vt100Prefix = "\033[31m";
}
else if(logQueueItem.logType == LOGTYPE_SUCCESS)
{
vt100Prefix = "\033[32m";
}
#endif
unsigned int seconds = 0;
#if defined(ENABLE_SERIAL_LOGGING)
// Formatted print
snprintf(str, sizeof(str) / sizeof(str[0]), "%s[%s] %09d %s, %s, %d: %s%s\n\r",
vt100Prefix,
(logQueueItem.logType == LOGTYPE_DEBUG) ? "DBG" :
(logQueueItem.logType == LOGTYPE_INFO) ? "INF" :
(logQueueItem.logType == LOGTYPE_SUCCESS) ? "SCS" :
(logQueueItem.logType == LOGTYPE_WARNING) ? "WRN" : "ERR",
seconds,
logQueueItem.fileName,
logQueueItem.functionName,
logQueueItem.lineNumber,
logQueueItem.context,
vt100Postfix);
#endif
#if defined(ENABLE_SERIAL_LOGGING)
uart_write_bytes(uartPort, str, strlen(str));
#endif
}
}
vTaskDelete(NULL);
}
+2 -2
View File
@@ -194,7 +194,7 @@ void logger::task()
// Raw print
#if defined(ENABLE_SERIAL_LOGGING)
port.write((uint8_t*)logQueueItem.context.c_str(), logQueueItem.context.length() + 1);
port.write(NO_DEVICE_ADDRESS, NO_REGISTER_ADDRESS, (uint8_t*)logQueueItem.context.c_str(), logQueueItem.context.length() + 1);
#endif
}
@@ -217,7 +217,7 @@ void logger::task()
+ logQueueItem.context + " "
+ it->vt100Postfix;
port.write((uint8_t*)outputString.c_str(), outputString.length() + 1);
port.write(NO_DEVICE_ADDRESS, NO_REGISTER_ADDRESS, (uint8_t*)outputString.c_str(), outputString.length() + 1);
#endif
}