From 64523cd45c768a71f3cf8d7dcfd802ef82b34e65 Mon Sep 17 00:00:00 2001 From: Phillip Johnston Date: Wed, 27 May 2020 08:57:40 -0700 Subject: [PATCH 1/5] Update ArduinoLogger to address usage on ESP8266, which defines printf We'll use the ESP built-in support instead of the printf library. Some lambda trickery is required to get the library working with the built-in ets_vprintf, since they only provide a callback and no private data. --- src/ArduinoLogger.h | 34 +++++++++++++++++++++++-- src/internal/lambda.h | 59 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 src/internal/lambda.h diff --git a/src/ArduinoLogger.h b/src/ArduinoLogger.h index 56e3a36..1a61629 100644 --- a/src/ArduinoLogger.h +++ b/src/ArduinoLogger.h @@ -1,11 +1,20 @@ #ifndef ARDUINO_LOGGER_H_ #define ARDUINO_LOGGER_H_ +#ifdef ESP8266 +#include +#include +#else #include +#endif #if !defined(__AVR__) #include #endif +#ifdef ESP8266 +void _putchar(char c); +#endif + /// Logging is disabled #define LOG_LEVEL_OFF 0 /// Indicates the system is unusable, or an error that is unrecoverable @@ -270,11 +279,31 @@ class LoggerBase #endif } +#ifdef ESP8266 + /// Prints directly to the log with no extra characters added to the message. + void print(const char* format, ...) noexcept + { + // We need to capture this with a lambda to call log_putc, + // Then decay that into a function pointer for a callback + auto f = [this](char c) { log_putc(c); }; + void (*callback)(char) = Lambda::ptr(f); + + va_list va; + va_start(va, format); + ets_vprintf(callback, format, va); + va_end(va); + + if(echo_) + { + ets_vprintf(ets_putc, format, va); + } + } +#else /// Prints directly to the log with no extra characters added to the message. template void print(const Args&... args) noexcept { - fctprintf(&LoggerBase::log_putc_bounce, this, args...); + fctprintf(&LoggerBase::log_putc_bounce, this, format, args...); if(echo_) { @@ -282,6 +311,7 @@ class LoggerBase printf(args...); } } +#endif /** Add data to the log buffer * @@ -301,7 +331,7 @@ class LoggerBase log_customprefix(); - // Send the primary log statement + // Send the primary log statementets_vprintf print(fmt, args...); } } diff --git a/src/internal/lambda.h b/src/internal/lambda.h new file mode 100644 index 0000000..1d4657a --- /dev/null +++ b/src/internal/lambda.h @@ -0,0 +1,59 @@ +#ifndef LAMBDA_HELPERS_H_ +#define LAMBDA_HELPERS_H_ + +/** Lambda Helper: Decay to Function Pointer + * + * When you need to convert a lambda with captures to a C pointer, + * such as when a callback interface doesn't provide a variable for private data + * which can store a `this` pointer, use this helper. + * + * @code + * int a = 100; + * auto b = [&](void*) {return ++a;}; + * + * // Converting lambda with captures to a C pointer + * void (*f1)(void*) = Lambda::ptr(b); + * f1(nullptr); + * printf("%d\n", a); // 101 + * + * // In case return value should be used + * int (*f3)(void*) = Lambda::ptr(b); + * printf("%d\n", f3(nullptr)); // 103 + * + * // In case data is used + * auto b2 = [&](void* data) {return *(int*)(data) + a;}; + * int (*f4)(void*) = Lambda::ptr(b2); + * int data = 5; + * printf("%d\n", f4(&data)); // 108 + * @endcode + * + * Source: https://stackoverflow.com/questions/7852101/c-lambda-with-captures-as-a-function-pointer + */ +struct Lambda +{ + template + static Tret lambda_ptr_exec(char data) + { + return (Tret)(*(T*)fn())(data); + } + + template + static Tfp ptr(T& t) + { + fn(&t); + return (Tfp)lambda_ptr_exec; + } + + template + static void* fn(void* new_fn = nullptr) + { + static void* fn; + if(new_fn != nullptr) + { + fn = new_fn; + } + return fn; + } +}; + +#endif // LAMBDA_HELPERS_H_ From 5431f6e4b5016ce80d5f7d34c352c8b49c3a45cd Mon Sep 17 00:00:00 2001 From: Phillip Johnston Date: Wed, 27 May 2020 08:59:36 -0700 Subject: [PATCH 2/5] Add notes mentioning support for ESP8266 with native printf support --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7bb1f08..0b4d122 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Flexible logging library for the Arduino SDK. This library allows the same loggi ## Dependencies -This library requires the following Arduino library to be installed on your system: +This library requires the following Arduino library to be installed on your system if you are using a non-ESP8266 setup: * [embeddedartistry/arduino-printf](https://github.com/embeddedartistry/arduino-printf) @@ -280,7 +280,7 @@ These settings can be changed in the build system, but it is easiest to define t By default, the logging library does not echo logging calls to the serial console. You can change the default setting at compile-time using the `LOG_ECHO_EN_DEFAULT` definition. -The logging library will print the output using the `printf` function. To change that output, see the instructions in the [embeddedartistry/arduino-printf](https://github.com/embeddedartistry/arduino-printf) library. +The logging library will print the output using the `printf` function. To change that output, see the instructions in the [embeddedartistry/arduino-printf](https://github.com/embeddedartistry/arduino-printf) library. If you are using the ESP8266, we use the built-in `printf` support instead of the external library. The setting can be changed in your build system or by defining the desired value in `platform_logger.h` before including the necessary logging library header. From 989d09684f86074c82d106a050e9d90fcf212ee5 Mon Sep 17 00:00:00 2001 From: Phillip Johnston Date: Wed, 27 May 2020 09:08:52 -0700 Subject: [PATCH 3/5] Generalize support beyond ESP8266 --- README.md | 4 ++-- src/ArduinoLogger.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0b4d122..b530407 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Flexible logging library for the Arduino SDK. This library allows the same loggi ## Dependencies -This library requires the following Arduino library to be installed on your system if you are using a non-ESP8266 setup: +This library requires the following Arduino library to be installed on your system if you are using a non-ESP8266/ESP32 setup: * [embeddedartistry/arduino-printf](https://github.com/embeddedartistry/arduino-printf) @@ -280,7 +280,7 @@ These settings can be changed in the build system, but it is easiest to define t By default, the logging library does not echo logging calls to the serial console. You can change the default setting at compile-time using the `LOG_ECHO_EN_DEFAULT` definition. -The logging library will print the output using the `printf` function. To change that output, see the instructions in the [embeddedartistry/arduino-printf](https://github.com/embeddedartistry/arduino-printf) library. If you are using the ESP8266, we use the built-in `printf` support instead of the external library. +The logging library will print the output using the `printf` function. To change that output, see the instructions in the [embeddedartistry/arduino-printf](https://github.com/embeddedartistry/arduino-printf) library. If you are using the ESP8266 or ESP32, we use the built-in `printf` support instead of the external library. The setting can be changed in your build system or by defining the desired value in `platform_logger.h` before including the necessary logging library header. diff --git a/src/ArduinoLogger.h b/src/ArduinoLogger.h index 1a61629..4d0bf2f 100644 --- a/src/ArduinoLogger.h +++ b/src/ArduinoLogger.h @@ -1,7 +1,7 @@ #ifndef ARDUINO_LOGGER_H_ #define ARDUINO_LOGGER_H_ -#ifdef ESP8266 +#ifdef __XTENSA__ #include #include #else @@ -11,7 +11,7 @@ #include #endif -#ifdef ESP8266 +#ifdef __XTENSA__ void _putchar(char c); #endif @@ -279,7 +279,7 @@ class LoggerBase #endif } -#ifdef ESP8266 +#ifdef __XTENSA__ /// Prints directly to the log with no extra characters added to the message. void print(const char* format, ...) noexcept { From 8d847a395cc98acfe4870e74b2126b1f3af17920 Mon Sep 17 00:00:00 2001 From: Phillip Johnston Date: Wed, 27 May 2020 09:09:10 -0700 Subject: [PATCH 4/5] Resolve compilation failure in CircularBufferLogger.h with ESP8266 --- src/CircularBufferLogger.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/CircularBufferLogger.h b/src/CircularBufferLogger.h index b88edca..75b8473 100644 --- a/src/CircularBufferLogger.h +++ b/src/CircularBufferLogger.h @@ -61,7 +61,11 @@ class CircularLogBufferLogger final : public LoggerBase { while(!log_buffer_.empty()) { +#ifdef __XTENSA__ + ets_putc(log_buffer_.pop_front()); +#else _putchar(log_buffer_.pop_front()); +#endif } } From 6892dc7e9cd95eda030b7ff276ce53b375a603ff Mon Sep 17 00:00:00 2001 From: Phillip Johnston Date: Wed, 27 May 2020 09:11:25 -0700 Subject: [PATCH 5/5] Address compilation error in non-ESP8266 case --- src/ArduinoLogger.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoLogger.h b/src/ArduinoLogger.h index 4d0bf2f..cb0c70a 100644 --- a/src/ArduinoLogger.h +++ b/src/ArduinoLogger.h @@ -303,7 +303,7 @@ class LoggerBase template void print(const Args&... args) noexcept { - fctprintf(&LoggerBase::log_putc_bounce, this, format, args...); + fctprintf(&LoggerBase::log_putc_bounce, this, args...); if(echo_) {