From f2f07252fe81882f7099cdef918dd5d38f405d23 Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Tue, 20 Aug 2019 16:00:03 +0200 Subject: [PATCH 01/10] cpu/esp32: bootloader versions with and w/o colors For the implementation of the colored log output, two versions of the bootloader are introduced, one version with colored log output and one version without colors. --- cpu/esp32/Makefile.include | 10 ++++++++-- cpu/esp32/bin/bootloader.elf | Bin 154316 -> 0 bytes ...otloader.bin => bootloader_with_colors.bin} | Bin cpu/esp32/bin/bootloader_without_colors.bin | Bin 0 -> 20320 bytes 4 files changed, 8 insertions(+), 2 deletions(-) delete mode 100755 cpu/esp32/bin/bootloader.elf rename cpu/esp32/bin/{bootloader.bin => bootloader_with_colors.bin} (100%) create mode 100644 cpu/esp32/bin/bootloader_without_colors.bin diff --git a/cpu/esp32/Makefile.include b/cpu/esp32/Makefile.include index 230d586f54..fa89e7ba7a 100644 --- a/cpu/esp32/Makefile.include +++ b/cpu/esp32/Makefile.include @@ -134,6 +134,12 @@ ifeq ($(QEMU), 1) CFLAGS += -DQEMU endif +ifneq (,$(filter esp_log_color,$(USEMODULE))) + BOOTLOADER_BIN = bootloader_with_colors.bin +else + BOOTLOADER_BIN = bootloader_without_colors.bin +endif + # LINKFLAGS += -Wl,--verbose LINKFLAGS += -L$(ESP32_SDK_DIR)/components/esp32 @@ -185,7 +191,7 @@ ifeq ($(QEMU), 1) FLASHER = dd FFLAGS += if=/dev/zero bs=1M count=4 | tr "\\000" "\\377" > tmp.bin && cat tmp.bin | FFLAGS += head -c $$((0x1000)) | - FFLAGS += cat - $(RIOTCPU)/$(CPU)/bin/bootloader.bin tmp.bin | + FFLAGS += cat - $(RIOTCPU)/$(CPU)/bin/$(BOOTLOADER_BIN) tmp.bin | FFLAGS += head -c $$((0x8000)) | FFLAGS += cat - $(BINDIR)/partitions.bin tmp.bin | FFLAGS += head -c $$((0x10000)) | @@ -199,7 +205,7 @@ else FFLAGS += --chip esp32 -p $(PROG_DEV) -b $(PROGRAMMER_SPEED) FFLAGS += --before default_reset --after hard_reset write_flash FFLAGS += -z -fm $(FLASH_MODE) -fs detect -ff $(FLASH_FREQ) - FFLAGS += 0x1000 $(RIOTCPU)/$(CPU)/bin/bootloader.bin + FFLAGS += 0x1000 $(RIOTCPU)/$(CPU)/bin/$(BOOTLOADER_BIN) FFLAGS += 0x8000 $(BINDIR)/partitions.bin FFLAGS += 0x10000 $(FLASHFILE).bin endif diff --git a/cpu/esp32/bin/bootloader.elf b/cpu/esp32/bin/bootloader.elf deleted file mode 100755 index 7edfd36320b59bc6ecfa334d4953bd7fb4cb8370..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 154316 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 PeGjg|Zbz_vY3uvH2TSo` diff --git a/cpu/esp32/bin/bootloader.bin b/cpu/esp32/bin/bootloader_with_colors.bin similarity index 100% rename from cpu/esp32/bin/bootloader.bin rename to cpu/esp32/bin/bootloader_with_colors.bin diff --git a/cpu/esp32/bin/bootloader_without_colors.bin b/cpu/esp32/bin/bootloader_without_colors.bin new file mode 100644 index 0000000000000000000000000000000000000000..e7b39fa35c7021a49adb59967b9471721c18d475 GIT binary patch literal 20320 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 literal 0 HcmV?d00001 From a3058291b74110ac33f49c9e854c69e66f56188d Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Tue, 20 Aug 2019 16:17:01 +0200 Subject: [PATCH 02/10] cpu/esp32: colored log output Log module of ESP32 supports colored log outputs when module `esp_log_color` is enabled. The generation of colored log outputs is realized by a extending the bunch of macros with an additional letter indicating the type of log message, --- cpu/esp32/Makefile.include | 1 + cpu/esp32/include/esp_common_log.h | 90 +++++++++++++++++++++--------- 2 files changed, 66 insertions(+), 25 deletions(-) diff --git a/cpu/esp32/Makefile.include b/cpu/esp32/Makefile.include index fa89e7ba7a..6007d97654 100644 --- a/cpu/esp32/Makefile.include +++ b/cpu/esp32/Makefile.include @@ -59,6 +59,7 @@ PSEUDOMODULES += esp_hw_counter PSEUDOMODULES += esp_i2c_sw PSEUDOMODULES += esp_i2c_hw PSEUDOMODULES += esp_idf_newlib +PSEUDOMODULES += esp_log_color PSEUDOMODULES += esp_spi_ram PSEUDOMODULES += esp_spiffs PSEUDOMODULES += esp_wifi_any diff --git a/cpu/esp32/include/esp_common_log.h b/cpu/esp32/include/esp_common_log.h index 5d5d8ab63f..2610c09854 100644 --- a/cpu/esp32/include/esp_common_log.h +++ b/cpu/esp32/include/esp_common_log.h @@ -26,48 +26,88 @@ extern "C" { #endif +#include +#include + #include "log.h" -#define LOG_TAG(level, tag, ...) do { \ - if ((level) <= LOG_LEVEL) log_write_tagged(level, tag, __VA_ARGS__); } while (0U) +extern uint32_t system_get_time_ms (void); + +#if MODULE_ESP_LOG_COLOR + +#define LOG_COLOR_RED "31" +#define LOG_COLOR_GREEN "32" +#define LOG_COLOR_BROWN "33" +#define LOG_COLOR(COLOR) "\033[0;" COLOR "m" +#define LOG_RESET_COLOR "\033[0m" +#define LOG_COLOR_E LOG_COLOR(LOG_COLOR_RED) +#define LOG_COLOR_W LOG_COLOR(LOG_COLOR_BROWN) +#define LOG_COLOR_I LOG_COLOR(LOG_COLOR_GREEN) +#define LOG_COLOR_D +#define LOG_COLOR_V + +#else /* MODULE_ESP_LOG_COLOR */ + +#define LOG_COLOR_E +#define LOG_COLOR_W +#define LOG_COLOR_I +#define LOG_COLOR_D +#define LOG_COLOR_V +#define LOG_RESET_COLOR + +#endif /* MODULE_ESP_LOG_COLOR */ + +#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%d) [%s] " format LOG_RESET_COLOR + +#define LOG_TAG(level, letter, tag, format, ...) \ + do { \ + if ((unsigned)level <= (unsigned)LOG_LEVEL) { \ + printf(LOG_FORMAT(letter, format), system_get_time_ms(), tag, ##__VA_ARGS__); \ + } \ + } while(0) + +#define LOG_TAG_EARLY(level, letter, tag, format, ...) \ + do { \ + if (LOG_LEVEL >= level) { \ + ets_printf(LOG_FORMAT(letter, format), system_get_time_ms(), tag, ##__VA_ARGS__); \ + } \ + } while(0) /** * Override LOG_* definitions with a tagged version. By default the function - * name is used tag. + * name is used as tag. */ +#ifndef MODULE_LOG_PRINTFNOFORMAT #undef LOG_ERROR #undef LOG_INFO #undef LOG_WARNING #undef LOG_DEBUG -#define LOG_ERROR(fmt, ...) LOG_TAG(LOG_ERROR , __func__, fmt, ##__VA_ARGS__) -#define LOG_WARNING(fmt, ...) LOG_TAG(LOG_WARNING, __func__, fmt, ##__VA_ARGS__) -#define LOG_INFO(fmt, ...) LOG_TAG(LOG_INFO , __func__, fmt, ##__VA_ARGS__) -#define LOG_DEBUG(fmt, ...) LOG_TAG(LOG_DEBUG , __func__, fmt, ##__VA_ARGS__) +#define LOG_ERROR(format, ...) LOG_TAG(LOG_ERROR , E, __func__, format, ##__VA_ARGS__) +#define LOG_WARNING(format, ...) LOG_TAG(LOG_WARNING, W, __func__, format, ##__VA_ARGS__) +#define LOG_INFO(format, ...) LOG_TAG(LOG_INFO , I, __func__, format, ##__VA_ARGS__) +#define LOG_DEBUG(format, ...) LOG_TAG(LOG_DEBUG , D, __func__, format, ##__VA_ARGS__) +#endif /** Tagged LOG_* definitions */ -#define LOG_TAG_ERROR(tag, fmt, ...) LOG_TAG(LOG_ERROR , tag, fmt, ##__VA_ARGS__) -#define LOG_TAG_WARNING(tag, fmt, ...) LOG_TAG(LOG_WARNING, tag, fmt, ##__VA_ARGS__) -#define LOG_TAG_INFO(tag, fmt, ...) LOG_TAG(LOG_INFO , tag, fmt, ##__VA_ARGS__) -#define LOG_TAG_DEBUG(tag, fmt, ...) LOG_TAG(LOG_DEBUG , tag, fmt, ##__VA_ARGS__) +#define LOG_TAG_ERROR(tag, format, ...) LOG_TAG(LOG_ERROR , E, tag, format, ##__VA_ARGS__) +#define LOG_TAG_WARNING(tag, format, ...) LOG_TAG(LOG_WARNING, W, tag, format, ##__VA_ARGS__) +#define LOG_TAG_INFO(tag, format, ...) LOG_TAG(LOG_INFO , I, tag, format, ##__VA_ARGS__) +#define LOG_TAG_DEBUG(tag, format, ...) LOG_TAG(LOG_DEBUG , D, tag, format, ##__VA_ARGS__) /** definitions for source code compatibility with ESP-IDF */ -#define ESP_EARLY_LOGE(tag, fmt, ...) LOG_TAG(LOG_ERROR , tag, fmt "\n", ##__VA_ARGS__) -#define ESP_EARLY_LOGW(tag, fmt, ...) LOG_TAG(LOG_WARNING, tag, fmt "\n", ##__VA_ARGS__) -#define ESP_EARLY_LOGI(tag, fmt, ...) LOG_TAG(LOG_INFO , tag, fmt "\n", ##__VA_ARGS__) -/* -#define ESP_EARLY_LOGI(tag, fmt, ...) ets_printf("I (%u) %s: " fmt "\n", \ - system_get_time_ms(), tag, ##__VA_ARGS__) -*/ -#define ESP_LOGE(tag, fmt, ...) LOG_TAG(LOG_ERROR , tag, fmt "\n", ##__VA_ARGS__) -#define ESP_LOGW(tag, fmt, ...) LOG_TAG(LOG_WARNING, tag, fmt "\n", ##__VA_ARGS__) -#define ESP_LOGI(tag, fmt, ...) LOG_TAG(LOG_INFO , tag, fmt "\n", ##__VA_ARGS__) +#define ESP_EARLY_LOGE(tag, format, ...) LOG_TAG_EARLY(LOG_ERROR , E, tag, format "\n", ##__VA_ARGS__) +#define ESP_EARLY_LOGW(tag, format, ...) LOG_TAG_EARLY(LOG_WARNING, W, tag, format "\n", ##__VA_ARGS__) +#define ESP_EARLY_LOGI(tag, format, ...) LOG_TAG_EARLY(LOG_INFO , I, tag, format "\n", ##__VA_ARGS__) +#define ESP_LOGE(tag, format, ...) LOG_TAG(LOG_ERROR , E, tag, format "\n", ##__VA_ARGS__) +#define ESP_LOGW(tag, format, ...) LOG_TAG(LOG_WARNING, W, tag, format "\n", ##__VA_ARGS__) +#define ESP_LOGI(tag, format, ...) LOG_TAG(LOG_INFO , I, tag, format "\n", ##__VA_ARGS__) #if ENABLE_DEBUG -#define ESP_EARLY_LOGD(tag, fmt, ...) LOG_TAG(LOG_DEBUG, tag, fmt "\n", ##__VA_ARGS__) -#define ESP_EARLY_LOGV(tag, fmt, ...) LOG_TAG(LOG_ALL , tag, fmt "\n", ##__VA_ARGS__) -#define ESP_LOGD(tag, fmt, ...) LOG_TAG(LOG_DEBUG, tag, fmt "\n", ##__VA_ARGS__) -#define ESP_LOGV(tag, fmt, ...) LOG_TAG(LOG_ALL , tag, fmt "\n", ##__VA_ARGS__) +#define ESP_EARLY_LOGD(tag, format, ...) LOG_TAG_EARLY(LOG_DEBUG, D, tag, format "\n", ##__VA_ARGS__) +#define ESP_EARLY_LOGV(tag, format, ...) LOG_TAG_EARLY(LOG_ALL , V, tag, format "\n", ##__VA_ARGS__) +#define ESP_LOGD(tag, format, ...) LOG_TAG(LOG_DEBUG, D, tag, format "\n", ##__VA_ARGS__) +#define ESP_LOGV(tag, format, ...) LOG_TAG(LOG_ALL , V, tag, format "\n", ##__VA_ARGS__) #else /* ENABLE_DEBUG */ From 327b9fd32e579bae43c9efdc9b55072b797d8e11 Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Tue, 20 Aug 2019 16:21:36 +0200 Subject: [PATCH 03/10] cpu/esp32: introduce module esp_log_tagged ESP32 log output was always tagged with additional information by default. The tag consists the type of the log message, the system time in ms, and the module or function in which the log message is generated. By introducing module `esp_log_tagged`, these additional information are disabled by default and can be enabled by using module `esp_log_tagged`. --- cpu/esp32/Makefile.include | 1 + cpu/esp32/include/esp_common_log.h | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/cpu/esp32/Makefile.include b/cpu/esp32/Makefile.include index 6007d97654..445b93f10e 100644 --- a/cpu/esp32/Makefile.include +++ b/cpu/esp32/Makefile.include @@ -60,6 +60,7 @@ PSEUDOMODULES += esp_i2c_sw PSEUDOMODULES += esp_i2c_hw PSEUDOMODULES += esp_idf_newlib PSEUDOMODULES += esp_log_color +PSEUDOMODULES += esp_log_tagged PSEUDOMODULES += esp_spi_ram PSEUDOMODULES += esp_spiffs PSEUDOMODULES += esp_wifi_any diff --git a/cpu/esp32/include/esp_common_log.h b/cpu/esp32/include/esp_common_log.h index 2610c09854..82c5b66d21 100644 --- a/cpu/esp32/include/esp_common_log.h +++ b/cpu/esp32/include/esp_common_log.h @@ -57,6 +57,8 @@ extern uint32_t system_get_time_ms (void); #endif /* MODULE_ESP_LOG_COLOR */ +#if MODULE_ESP_LOG_TAGGED + #define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%d) [%s] " format LOG_RESET_COLOR #define LOG_TAG(level, letter, tag, format, ...) \ @@ -73,6 +75,28 @@ extern uint32_t system_get_time_ms (void); } \ } while(0) +#else /* MODULE_ESP_LOG_TAGGED */ + +#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter format LOG_RESET_COLOR + +#define LOG_TAG(level, letter, tag, format, ...) \ + do { \ + (void)tag; \ + if ((unsigned)level <= (unsigned)LOG_LEVEL) { \ + printf(LOG_FORMAT(letter, format), ##__VA_ARGS__); \ + } \ + } while (0U) + +#define LOG_TAG_EARLY(level, letter, tag, format, ...) \ + do { \ + (void)tag; \ + if ((unsigned)level <= (unsigned)LOG_LEVEL) { \ + ets_printf(LOG_FORMAT(letter, format), ##__VA_ARGS__); \ + } \ + } while (0U) + +#endif /* MODULE_ESP_LOG_TAGGED */ + /** * Override LOG_* definitions with a tagged version. By default the function * name is used as tag. From 9a4cdc7e93b9d38540486d1a057c36318f07c7b0 Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Tue, 20 Aug 2019 16:23:42 +0200 Subject: [PATCH 04/10] cpu/esp32: log_module implementation The implementation of `log_module` for ESP32 was changed from functions to a macro-based implementation to be able to use the bunch of macros for colored and tagget log output generation. --- cpu/esp32/include/log_module.h | 43 +++++++++------ cpu/esp32/log_module.c | 99 ---------------------------------- 2 files changed, 28 insertions(+), 114 deletions(-) delete mode 100644 cpu/esp32/log_module.c diff --git a/cpu/esp32/include/log_module.h b/cpu/esp32/include/log_module.h index 60229f7134..7f5bf2e083 100644 --- a/cpu/esp32/include/log_module.h +++ b/cpu/esp32/include/log_module.h @@ -23,22 +23,35 @@ extern "C" { #endif -/** - * @brief log_write overridden function - * - * @param[in] level (unused) - * @param[in] format String that the function will print - */ -void log_write(unsigned level, const char *format, ...); +#include +#include "esp_common_log.h" -/** - * @brief log_write overridden function, tagged version - * - * @param[in] level Level of the message - * @param[in] tag Additional information like function or module - * @param[in] format String that the function will print - */ -void log_write_tagged(unsigned level, const char *tag, const char *format, ...); +#ifdef MODULE_LOG_PRINTFNOFORMAT + +static inline void log_write(unsigned level, const char *format, ...) { + (void)level; + puts(format); +} + +#else /* MODULE_LOG_PRINTFNOFORMAT */ + +#define log_write(level, ...) \ + do { \ + if (level == LOG_ERROR) { \ + LOG_TAG(LOG_ERROR, E, __func__, ##__VA_ARGS__); \ + } \ + else if (level == LOG_WARNING) { \ + LOG_TAG(LOG_WARNING, W, __func__, ##__VA_ARGS__); \ + } \ + else if (level == LOG_INFO) { \ + LOG_TAG(LOG_INFO, D, __func__, ##__VA_ARGS__); \ + } \ + else if (level == LOG_DEBUG) { \ + LOG_TAG(LOG_DEBUG, E, __func__, ##__VA_ARGS__); \ + } \ + } while (0U); + +#endif /* MODULE_LOG_PRINTFNOFORMAT */ #ifdef __cplusplus } diff --git a/cpu/esp32/log_module.c b/cpu/esp32/log_module.c deleted file mode 100644 index b90b26850f..0000000000 --- a/cpu/esp32/log_module.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32 - * @{ - * - * @file - * @brief Log module to realize consistent log messages - * - * @author Gunar Schorcht - */ - -#include -#include - -#include "rom/ets_sys.h" - -#include "cpu_conf.h" -#include "log.h" -#include "syscalls.h" - -char _printf_buf[PRINTF_BUFSIZ]; -bool _new_line = true; - -void log_write(unsigned level, const char *format, ...) -{ - if (level == LOG_NONE) { - return; - } - - if (_new_line) { - /* if we are in new line, we print the prefix */ - char lc = 'U'; - switch (level) { - case LOG_ERROR : lc = 'E'; break; - case LOG_WARNING: lc = 'W'; break; - case LOG_INFO : lc = 'I'; break; - case LOG_DEBUG : lc = 'D'; break; - case LOG_ALL : lc = 'V'; break; - } - ets_printf("%c (%u) ", lc, system_get_time_ms()); - } - - va_list arglist; - va_start(arglist, format); - - int ret = vsnprintf(_printf_buf, PRINTF_BUFSIZ, format, arglist); - - if (ret > 0) { - ets_printf (_printf_buf); - } - - va_end(arglist); - - _new_line = (strrchr(format, '\n') != NULL); -} - -void log_write_tagged(unsigned level, const char *tag, const char *format, ...) -{ - if (level == LOG_NONE) { - return; - } - - if (_new_line) { - /* if we are in new line, we print the prefix */ - char lc = 'U'; - switch (level) { - case LOG_ERROR : lc = 'E'; break; - case LOG_WARNING: lc = 'W'; break; - case LOG_INFO : lc = 'I'; break; - case LOG_DEBUG : lc = 'D'; break; - case LOG_ALL : lc = 'V'; break; - } - #if LOG_TAG_IN_BRACKETS - ets_printf("%c (%u) [%10s]: ", lc, system_get_time_ms(), tag); - #else - ets_printf("%c (%u) %10s: ", lc, system_get_time_ms(), tag); - #endif - } - - va_list arglist; - va_start(arglist, format); - - int ret = vsnprintf(_printf_buf, PRINTF_BUFSIZ, format, arglist); - - if (ret > 0) { - ets_printf (_printf_buf); - } - - va_end(arglist); - - _new_line = (strrchr(format, '\n') != NULL); -} From 1f940b07283f33f203efcb0c9d6d8d371ede15a5 Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Tue, 20 Aug 2019 16:28:12 +0200 Subject: [PATCH 05/10] cpu/esp32: map log outputs from SDK libraries Log outputs generated by binary ESP32 SDK libraries are mapped to the ESP32's log module which supports colored and tagged log outpus. Tagged log outputs from SDK libraries are handled accordingly. --- cpu/esp32/vendor/esp-idf/esp_funcs.c | 39 +++++++----- .../vendor/esp-idf/include/log/esp_log.h | 61 +++++++++---------- 2 files changed, 53 insertions(+), 47 deletions(-) diff --git a/cpu/esp32/vendor/esp-idf/esp_funcs.c b/cpu/esp32/vendor/esp-idf/esp_funcs.c index 204eaea107..c2f83ef031 100644 --- a/cpu/esp32/vendor/esp-idf/esp_funcs.c +++ b/cpu/esp32/vendor/esp-idf/esp_funcs.c @@ -86,6 +86,22 @@ uint32_t IRAM_ATTR esp_log_timestamp(void) return system_get_time() / USEC_PER_MSEC; } + +#if MODULE_ESP_LOG_TAGGED +#define ESP_LOG_PREFIX(letter, tag) \ + printf(LOG_COLOR_ ## letter #letter " (%d) [%s] ", \ + system_get_time_ms(), tag) +#else +#define ESP_LOG_PREFIX(letter, tag) \ + printf(LOG_COLOR_ ## letter "[%s] ", tag) +#endif + +#if MODULE_ESP_LOG_COLOR +#define ESP_LOG_SUFFIX() printf(LOG_RESET_COLOR) +#else +#define ESP_LOG_SUFFIX() +#endif + /* * provided by: /path/to/esp-idf/component/log/log.c */ @@ -97,23 +113,16 @@ void IRAM_ATTR esp_log_write(esp_log_level_t level, } char _printf_buf[PRINTF_BUFSIZ]; - const char* prefix = (strchr (format, ':') + 2); - char lc = 'U'; switch (level) { case LOG_NONE : return; - case LOG_ERROR : lc = 'E'; break; - case LOG_WARNING: lc = 'W'; break; - case LOG_INFO : lc = 'I'; break; - case LOG_DEBUG : lc = 'D'; break; - case LOG_ALL : lc = 'V'; break; + case LOG_ERROR : ESP_LOG_PREFIX(E, tag); break; + case LOG_WARNING: ESP_LOG_PREFIX(W, tag); break; + case LOG_INFO : ESP_LOG_PREFIX(I, tag); break; + case LOG_DEBUG : ESP_LOG_PREFIX(D, tag); break; + case LOG_ALL : ESP_LOG_PREFIX(V, tag); break; } - #ifdef LOG_TAG_IN_BRACKETS - ets_printf("%c (%u) [%10s]: ", lc, system_get_time_ms(), tag); - #else - ets_printf("%c (%u) %10s: ", lc, system_get_time_ms(), tag); - #endif va_list arglist; va_start(arglist, format); @@ -124,11 +133,13 @@ void IRAM_ATTR esp_log_write(esp_log_level_t level, int ret = vsnprintf(_printf_buf, PRINTF_BUFSIZ, prefix, arglist); + va_end(arglist); + if (ret > 0) { - ets_printf (_printf_buf); + printf ("%s", _printf_buf); } - va_end(arglist); + ESP_LOG_SUFFIX(); } /* diff --git a/cpu/esp32/vendor/esp-idf/include/log/esp_log.h b/cpu/esp32/vendor/esp-idf/include/log/esp_log.h index 7743c05a7a..f7a5a2e1a7 100644 --- a/cpu/esp32/vendor/esp-idf/include/log/esp_log.h +++ b/cpu/esp32/vendor/esp-idf/include/log/esp_log.h @@ -318,41 +318,36 @@ void esp_log_write(esp_log_level_t level, const char* tag, const char* format, . #include "esp_common.h" -#if 0 /* TODO */ - -#define LOG_FORMAT(letter, format) #letter " (%d) %s: " format "\n" - -#define ESP_LOG_LEVEL(level, tag, format, ...) do { \ - if ((esp_log_level_t)level==ESP_LOG_ERROR ) { \ - esp_log_write(ESP_LOG_ERROR, tag, LOG_FORMAT(E, format), \ - esp_log_timestamp(), tag, ##__VA_ARGS__); \ - } \ - else if ((esp_log_level_t)level==ESP_LOG_WARN ) { \ - esp_log_write(ESP_LOG_WARN, tag, LOG_FORMAT(W, format), \ - esp_log_timestamp(), tag, ##__VA_ARGS__); \ - } \ - else if ((esp_log_level_t)level==ESP_LOG_DEBUG ) { \ - esp_log_write(ESP_LOG_DEBUG, tag, LOG_FORMAT(D, format), \ - esp_log_timestamp(), tag, ##__VA_ARGS__); \ - } \ - else if ((esp_log_level_t)level==ESP_LOG_VERBOSE ) { \ - esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), \ - esp_log_timestamp(), tag, ##__VA_ARGS__); \ - } \ - else { \ - esp_log_write(ESP_LOG_INFO, tag, LOG_FORMAT(I, format), \ - esp_log_timestamp(), tag, ##__VA_ARGS__); \ - } \ - } while(0) - -#define ESP_LOG_LEVEL_LOCAL(level, tag, format, ...) do { \ - if ( LOG_LOCAL_LEVEL >= level ) ESP_LOG_LEVEL(level, tag, format, ##__VA_ARGS__); \ - } while(0) - -#else -#define ESP_LOG_LEVEL_LOCAL(level, tag, format, ...) +#ifndef LOG_LOCAL_LEVEL +#define LOG_LOCAL_LEVEL (esp_log_level_t)LOG_LEVEL #endif +#define ESP_LOG_LEVEL(level, tag, format, ...) \ + do { \ + if ((esp_log_level_t)level==ESP_LOG_ERROR ) { \ + LOG_TAG(level, E, tag, format, ##__VA_ARGS__); \ + } \ + else if ((esp_log_level_t)level==ESP_LOG_WARN ) { \ + LOG_TAG(level, W, tag, format, ##__VA_ARGS__); \ + } \ + else if ((esp_log_level_t)level==ESP_LOG_INFO ) { \ + LOG_TAG(level, I, tag, format, ##__VA_ARGS__); \ + } \ + else if ((esp_log_level_t)level==ESP_LOG_DEBUG ) { \ + LOG_TAG(level, D, tag, format, ##__VA_ARGS__); \ + } \ + else if ((esp_log_level_t)level==ESP_LOG_VERBOSE ) { \ + LOG_TAG(level, V, tag, format, ##__VA_ARGS__); \ + } \ + } while(0) + +#define ESP_LOG_LEVEL_LOCAL(level, tag, format, ...) \ + do { \ + if ( LOG_LOCAL_LEVEL >= level ) { \ + ESP_LOG_LEVEL(level, tag, format, ##__VA_ARGS__); \ + } \ + } while(0) + #endif /* RIOT_VERSION */ #ifdef __cplusplus From 5d51c03af908f190df2c2c9b8cb2a2029cf7006b Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Tue, 20 Aug 2019 16:52:58 +0200 Subject: [PATCH 06/10] cpu/esp32: replace ets_printf by printf Wherever possible, ets_printf is replaced by newlib printf. --- cpu/esp32/periph/adc.c | 7 +++---- cpu/esp32/periph/dac.c | 7 +++---- cpu/esp32/periph/i2c_hw.c | 4 ++-- cpu/esp32/periph/i2c_sw.c | 4 ++-- cpu/esp32/periph/pwm.c | 7 +++---- cpu/esp32/periph/spi.c | 12 ++++++------ cpu/esp32/periph/uart.c | 4 ++-- cpu/esp32/tools.c | 16 ++++++++-------- cpu/esp32/vendor/esp-idf/esp_funcs.c | 10 +++++----- 9 files changed, 34 insertions(+), 37 deletions(-) diff --git a/cpu/esp32/periph/adc.c b/cpu/esp32/periph/adc.c index e511fe54e6..8dd816de5d 100644 --- a/cpu/esp32/periph/adc.c +++ b/cpu/esp32/periph/adc.c @@ -26,7 +26,6 @@ #include "adc_ctrl.h" #include "esp_common.h" #include "gpio_arch.h" -#include "rom/ets_sys.h" #include "soc/rtc_io_struct.h" #include "soc/rtc_cntl_struct.h" #include "soc/sens_reg.h" @@ -271,11 +270,11 @@ static void _adc_module_init(void) void adc_print_config(void) { - ets_printf("\tADC\t\tpins=[ "); + printf("\tADC\t\tpins=[ "); #if defined(ADC_GPIOS) for (unsigned i = 0; i < ADC_NUMOF; i++) { - ets_printf("%d ", adc_channels[i]); + printf("%d ", adc_channels[i]); } #endif /* defined(ADC_GPIOS) */ - ets_printf("]\n"); + printf("]\n"); } diff --git a/cpu/esp32/periph/dac.c b/cpu/esp32/periph/dac.c index bc569b3c31..c8d24a3dc7 100644 --- a/cpu/esp32/periph/dac.c +++ b/cpu/esp32/periph/dac.c @@ -26,7 +26,6 @@ #include "adc_ctrl.h" #include "esp_common.h" #include "gpio_arch.h" -#include "rom/ets_sys.h" #include "soc/rtc_io_struct.h" #include "soc/rtc_cntl_struct.h" #include "soc/sens_reg.h" @@ -136,11 +135,11 @@ static bool _dac_conf_check(void) void dac_print_config(void) { - ets_printf("\tDAC\t\tpins=[ "); + printf("\tDAC\t\tpins=[ "); #if defined(DAC_GPIOS) for (unsigned i = 0; i < DAC_NUMOF; i++) { - ets_printf("%d ", dac_channels[i]); + printf("%d ", dac_channels[i]); } #endif /* defined(DAC_GPIOS) */ - ets_printf("]\n"); + printf("]\n"); } diff --git a/cpu/esp32/periph/i2c_hw.c b/cpu/esp32/periph/i2c_hw.c index 4a2f379278..0ae20be194 100644 --- a/cpu/esp32/periph/i2c_hw.c +++ b/cpu/esp32/periph/i2c_hw.c @@ -869,8 +869,8 @@ static void _i2c_reset_hw (i2c_t dev) void i2c_print_config(void) { for (unsigned dev = 0; dev < I2C_NUMOF; dev++) { - ets_printf("\tI2C_DEV(%d)\tscl=%d sda=%d\n", - dev, i2c_config[dev].scl, i2c_config[dev].sda); + printf("\tI2C_DEV(%u)\tscl=%d sda=%d\n", + dev, i2c_config[dev].scl, i2c_config[dev].sda); } } diff --git a/cpu/esp32/periph/i2c_sw.c b/cpu/esp32/periph/i2c_sw.c index d8b8463cfa..568b004871 100644 --- a/cpu/esp32/periph/i2c_sw.c +++ b/cpu/esp32/periph/i2c_sw.c @@ -700,8 +700,8 @@ static /* IRAM */ int _i2c_read_byte(_i2c_bus_t* bus, uint8_t *byte, bool ack) void i2c_print_config(void) { for (unsigned dev = 0; dev < I2C_NUMOF; dev++) { - ets_printf("\tI2C_DEV(%d)\tscl=%d sda=%d\n", - dev, i2c_config[dev].scl, i2c_config[dev].sda); + printf("\tI2C_DEV(%u)\tscl=%d sda=%d\n", + dev, i2c_config[dev].scl, i2c_config[dev].sda); } } diff --git a/cpu/esp32/periph/pwm.c b/cpu/esp32/periph/pwm.c index 3bbe6a4e60..1e78ad143d 100644 --- a/cpu/esp32/periph/pwm.c +++ b/cpu/esp32/periph/pwm.c @@ -32,7 +32,6 @@ #include "gpio_arch.h" #include "driver/periph_ctrl.h" -#include "rom/ets_sys.h" #include "soc/gpio_struct.h" #include "soc/gpio_sig_map.h" #include "soc/mcpwm_reg.h" @@ -437,11 +436,11 @@ static bool _pwm_configuration(void) void pwm_print_config(void) { for (unsigned pwm = 0; pwm < PWM_NUMOF; pwm++) { - ets_printf("\tPWM_DEV(%d)\tchannels=[ ", pwm); + printf("\tPWM_DEV(%d)\tchannels=[ ", pwm); for (int i = 0; i < _pwm_hw[pwm].gpio_num; i++) { - ets_printf("%d ", _pwm_hw[pwm].gpios[i]); + printf("%d ", _pwm_hw[pwm].gpios[i]); } - ets_printf("]\n"); + printf("]\n"); } } diff --git a/cpu/esp32/periph/spi.c b/cpu/esp32/periph/spi.c index 2af333f6d1..b16a651f96 100644 --- a/cpu/esp32/periph/spi.c +++ b/cpu/esp32/periph/spi.c @@ -125,7 +125,7 @@ void IRAM_ATTR spi_init (spi_t bus) _spi[bus].signal_miso = VSPIQ_IN_IDX; break; default: LOG_TAG_ERROR("spi", "invalid SPI interface controller " - "used for SPI_DEV(%d)\n"); + "used for SPI_DEV(%d)\n", bus); break; } return; @@ -361,11 +361,11 @@ static const char* _spi_names[] = { "CSPI", "FSPI", "HSPI", "VSPI" }; void spi_print_config(void) { for (unsigned bus = 0; bus < SPI_NUMOF; bus++) { - ets_printf("\tSPI_DEV(%d)\t%s ", bus, _spi_names[spi_config[bus].ctrl]); - ets_printf("sck=%d " , spi_config[bus].sck); - ets_printf("miso=%d ", spi_config[bus].miso); - ets_printf("mosi=%d ", spi_config[bus].mosi); - ets_printf("cs=%d\n" , spi_config[bus].cs); + printf("\tSPI_DEV(%u)\t%s ", bus, _spi_names[spi_config[bus].ctrl]); + printf("sck=%d " , spi_config[bus].sck); + printf("miso=%d ", spi_config[bus].miso); + printf("mosi=%d ", spi_config[bus].mosi); + printf("cs=%d\n" , spi_config[bus].cs); } } diff --git a/cpu/esp32/periph/uart.c b/cpu/esp32/periph/uart.c index 6e5d4d2522..d0b5fcb2e6 100644 --- a/cpu/esp32/periph/uart.c +++ b/cpu/esp32/periph/uart.c @@ -205,8 +205,8 @@ void uart_system_init (void) void uart_print_config(void) { for (unsigned uart = 0; uart < UART_NUMOF; uart++) { - ets_printf("\tUART_DEV(%d)\ttxd=%d rxd=%d\n", uart, - uart_config[uart].txd, uart_config[uart].rxd); + printf("\tUART_DEV(%u)\ttxd=%d rxd=%d\n", uart, + uart_config[uart].txd, uart_config[uart].rxd); } } diff --git a/cpu/esp32/tools.c b/cpu/esp32/tools.c index 513e3abd90..23f8878e79 100644 --- a/cpu/esp32/tools.c +++ b/cpu/esp32/tools.c @@ -43,18 +43,18 @@ void esp_hexdump (const void* addr, uint32_t num, char width, uint8_t per_line) while (count < num) { if (count % per_line == 0) { - ets_printf ("%08" PRIx32 ": ", (uint32_t)((uint8_t*)addr+count*size)); + printf ("%08" PRIx32 ": ", (uint32_t)((uint8_t*)addr+count*size)); } switch (width) { - case 'b': ets_printf("%02" PRIx8 " ", addr8[count++]); break; - case 'h': ets_printf("%04" PRIx16 " ", addr16[count++]); break; - case 'w': ets_printf("%08" PRIx32 " ", addr32[count++]); break; - case 'g': ets_printf("%016" PRIx64 " ", addr64[count++]); break; - default : ets_printf("."); count++; break; + case 'b': printf("%02" PRIx8 " ", addr8[count++]); break; + case 'h': printf("%04" PRIx16 " ", addr16[count++]); break; + case 'w': printf("%08" PRIx32 " ", addr32[count++]); break; + case 'g': printf("%016" PRIx64 " ", addr64[count++]); break; + default : printf("."); count++; break; } if (count % per_line == 0) { - ets_printf ("\n"); + printf ("\n"); } } - ets_printf ("\n"); + printf ("\n"); } diff --git a/cpu/esp32/vendor/esp-idf/esp_funcs.c b/cpu/esp32/vendor/esp-idf/esp_funcs.c index c2f83ef031..16c343f9c3 100644 --- a/cpu/esp32/vendor/esp-idf/esp_funcs.c +++ b/cpu/esp32/vendor/esp-idf/esp_funcs.c @@ -165,11 +165,11 @@ void spi_ram_init(void) _spi_ram_initialized = true; } else { - ets_printf("Failed to init external SPI RAM\n"); + ESP_EARLY_LOGE("spi_ram", "Failed to init external SPI RAM\n"); _spi_ram_initialized = false; } #else - ets_printf("External SPI RAM functions not enabled\n"); + ESP_EARLY_LOGI("spi_ram", "External SPI RAM functions not enabled\n"); #endif } @@ -189,14 +189,14 @@ void spi_ram_heap_init(void) #if CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC esp_err_t r=esp_spiram_add_to_heapalloc(); if (r != ESP_OK) { - ets_printf("External SPI RAM could not be added to heap!\n"); + ESP_EARLY_LOGE("spi_ram", "External SPI RAM could not be added to heap!\n"); abort(); } #if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL r=esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL); if (r != ESP_OK) { - ets_printf("Could not reserve internal/DMA pool!\n"); + ESP_EARLY_LOGE("spi_ram", "Could not reserve internal/DMA pool!\n"); abort(); } #endif /* CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL */ @@ -208,7 +208,7 @@ void spi_ram_heap_init(void) #endif /* CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC */ #else /* CONFIG_SPIRAM_SUPPORT */ - ets_printf("External SPI RAM functions not enabled\n"); + ESP_EARLY_LOGI("spi_ram", "External SPI RAM functions not enabled\n"); #endif /* CONFIG_SPIRAM_SUPPORT */ } From 4503f45abb0d72f0399f40cdf5db9559bc00859d Mon Sep 17 00:00:00 2001 From: Schorcht Date: Tue, 20 Aug 2019 18:22:35 +0200 Subject: [PATCH 07/10] cpu/esp32: esp_log_color renamed to esp_log_colored --- cpu/esp32/Makefile.include | 4 ++-- cpu/esp32/include/esp_common_log.h | 6 +++--- cpu/esp32/vendor/esp-idf/esp_funcs.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cpu/esp32/Makefile.include b/cpu/esp32/Makefile.include index 445b93f10e..ebe94326db 100644 --- a/cpu/esp32/Makefile.include +++ b/cpu/esp32/Makefile.include @@ -59,7 +59,7 @@ PSEUDOMODULES += esp_hw_counter PSEUDOMODULES += esp_i2c_sw PSEUDOMODULES += esp_i2c_hw PSEUDOMODULES += esp_idf_newlib -PSEUDOMODULES += esp_log_color +PSEUDOMODULES += esp_log_colored PSEUDOMODULES += esp_log_tagged PSEUDOMODULES += esp_spi_ram PSEUDOMODULES += esp_spiffs @@ -136,7 +136,7 @@ ifeq ($(QEMU), 1) CFLAGS += -DQEMU endif -ifneq (,$(filter esp_log_color,$(USEMODULE))) +ifneq (,$(filter esp_log_colored,$(USEMODULE))) BOOTLOADER_BIN = bootloader_with_colors.bin else BOOTLOADER_BIN = bootloader_without_colors.bin diff --git a/cpu/esp32/include/esp_common_log.h b/cpu/esp32/include/esp_common_log.h index 82c5b66d21..ecfc71a681 100644 --- a/cpu/esp32/include/esp_common_log.h +++ b/cpu/esp32/include/esp_common_log.h @@ -33,7 +33,7 @@ extern "C" { extern uint32_t system_get_time_ms (void); -#if MODULE_ESP_LOG_COLOR +#if MODULE_ESP_LOG_COLORED #define LOG_COLOR_RED "31" #define LOG_COLOR_GREEN "32" @@ -46,7 +46,7 @@ extern uint32_t system_get_time_ms (void); #define LOG_COLOR_D #define LOG_COLOR_V -#else /* MODULE_ESP_LOG_COLOR */ +#else /* MODULE_ESP_LOG_COLORED */ #define LOG_COLOR_E #define LOG_COLOR_W @@ -55,7 +55,7 @@ extern uint32_t system_get_time_ms (void); #define LOG_COLOR_V #define LOG_RESET_COLOR -#endif /* MODULE_ESP_LOG_COLOR */ +#endif /* MODULE_ESP_LOG_COLORED */ #if MODULE_ESP_LOG_TAGGED diff --git a/cpu/esp32/vendor/esp-idf/esp_funcs.c b/cpu/esp32/vendor/esp-idf/esp_funcs.c index 16c343f9c3..b7914693f5 100644 --- a/cpu/esp32/vendor/esp-idf/esp_funcs.c +++ b/cpu/esp32/vendor/esp-idf/esp_funcs.c @@ -96,7 +96,7 @@ uint32_t IRAM_ATTR esp_log_timestamp(void) printf(LOG_COLOR_ ## letter "[%s] ", tag) #endif -#if MODULE_ESP_LOG_COLOR +#if MODULE_ESP_LOG_COLORED #define ESP_LOG_SUFFIX() printf(LOG_RESET_COLOR) #else #define ESP_LOG_SUFFIX() From f500dcbf02188161e3816714232bb1c5b1e410b6 Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Wed, 21 Aug 2019 00:29:10 +0200 Subject: [PATCH 08/10] cpu/esp32: colored and tagged log output docu --- cpu/esp32/doc.txt | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/cpu/esp32/doc.txt b/cpu/esp32/doc.txt index 2309647866..418cf41ae8 100644 --- a/cpu/esp32/doc.txt +++ b/cpu/esp32/doc.txt @@ -114,6 +114,8 @@ Module | Default | Short description [esp_hw_counter](#esp32_timers) | not used | use hardware counters for RIOT timers [esp_i2c_hw](#esp32_i2c_interfaces) | not used | use the i2C hardware implementation [esp_idf_heap](#esp32_esp_idf_heap_implementation) | not used | enable ESP-IDF heap implementation +[esp_log_colored](#esp32_esp_log_module) | not used | enable colored log output +[esp_log_tagged](#esp32_esp_log_module) | not used | add additional information to the log output [esp_now](#esp32_esp_now_network_interface) | not used | enable the ESP-NOW network device [esp_spi_ram](#esp32_spi_ram) | not used | enable SPI RAM [esp_spiffs](#esp32_spiffs_device) | not used | enable SPIFFS for on-board flash memory @@ -395,6 +397,8 @@ esp_eth | Enable the Ethernet MAC (EMAC) interface as `netdev` network device, s esp_gdb | Enable the compilation with debug information for debugging with [QEMU and GDB](#esp32_qemu_mode_and_gdb) (```QEMU=1```) or via [JTAG interface with OpenOCD](#esp32_jtag_debugging). esp_i2c_hw | Use the hardware I2C implementation, see section [I2C Interfaces](#esp32_i2c_interfaces). esp_idf_heap | Use the ESP-IDF heap implementation, see section [ESP-IDF Heap Implementation](#esp32_esp_idf_heap_implementation). +esp_log_colored | Enable colored log output, see section [Log output](#esp32_esp_log_module). +esp_log_tagged | Add additional information to the log output, see section [Log output](#esp32_esp_log_module). esp_now | Enable the built-in WiFi module with the ESP-NOW protocol as `netdev` network device, see section [ESP-NOW Network Interface](#esp32_esp_now_network_interface). esp_spiffs | Enable the optional SPIFFS drive in on-board flash memory, see section [SPIFFS Device](#esp32_spiffs_device). esp_spi_ram | Enable the optional SPI RAM, see section [SPI RAM Modules](#esp32_spi_ram). @@ -421,6 +425,41 @@ The flash mode determines whether 2 data lines (```dio``` and ```dout```) or 4 d For more information about these flash modes, refer the documentation of [esptool.py](https://github.com/espressif/esptool/wiki/SPI-Flash-Modes). +## Log output  [[TOC](#esp32_toc)] + +The RIOT port for ESP32 implements a log module with a bunch of macros +to generate log output according to the interface as defined in +[system logging header](http://doc.riot-os.org/log_8h.html). These macros +support colored and tagged log output. + +The colored log output is enabled by module `esp_log_colored`. If colored log +output is enabled, log messages are displayed in color according to their type: +Error messages are displayed in red, warnings in yellow, information +messages in green and all other message types in standard color. + +When the `esp_log_tagged` module is used, all log messages are tagged with +additional information: the type of message, the system time in ms, and the +module or function in which the log message is generated. For example: + +``` +I (663) [main_trampoline] main(): This is RIOT! (Version: 2019.10-devel-437-gf506a) +``` + +Either the `LOG_*` macros as defined in +[system logging header](http://doc.riot-os.org/log_8h.html) or the tagged +version `LOG_TAG_*` of these macros can be used to produce tagged log output. +If the `LOG_*` macros are used, the function which generates the log message +is used in the tag while a `tag` parameter is used for the `LOG_TAG_*` macros. +For example, +``` +LOG_ERROR("error message"); +``` +generates a log message in which the name of the calling function is used as +tag. With +``` +LOG_TAG_ERROR("mod", "error message"); +``` +a log message with string `mod` in the tag is generated. ## ESP-IDF Heap Implementation  [[TOC](#esp32_toc)] From 4af78c31ef014133c10c93ceb989a532b3b1564b Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Sun, 10 Nov 2019 13:53:18 +0100 Subject: [PATCH 09/10] cpu/esp32: enable colored output with log_color --- cpu/esp32/Makefile.dep | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cpu/esp32/Makefile.dep b/cpu/esp32/Makefile.dep index 4f9704264c..07cfa48ad0 100644 --- a/cpu/esp32/Makefile.dep +++ b/cpu/esp32/Makefile.dep @@ -92,6 +92,10 @@ ifneq (,$(filter shell,$(USEMODULE))) USEMODULE += xtimer endif +ifneq (,$(filter log_color,$(USEMODULE))) + USEMODULE += esp_log_colored +endif + # if SPI RAM is enabled, ESP-IDF heap and quot flash mode have to be used ifneq (,$(filter esp_spi_ram,$(USEMODULE))) USEMODULE += esp_idf_heap From 6fb7c50d4863436f2dd0e653fb6620a65063c748 Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Wed, 20 Nov 2019 06:46:42 +0100 Subject: [PATCH 10/10] cpu/esp32: colored output modifications For compatibility with module log_color and the esp8266 esp_log_colored implementation. --- cpu/esp32/include/esp_common_log.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/cpu/esp32/include/esp_common_log.h b/cpu/esp32/include/esp_common_log.h index ecfc71a681..5cb179ef81 100644 --- a/cpu/esp32/include/esp_common_log.h +++ b/cpu/esp32/include/esp_common_log.h @@ -32,18 +32,15 @@ extern "C" { #include "log.h" extern uint32_t system_get_time_ms (void); +extern int ets_printf(const char *fmt, ...); #if MODULE_ESP_LOG_COLORED -#define LOG_COLOR_RED "31" -#define LOG_COLOR_GREEN "32" -#define LOG_COLOR_BROWN "33" -#define LOG_COLOR(COLOR) "\033[0;" COLOR "m" #define LOG_RESET_COLOR "\033[0m" -#define LOG_COLOR_E LOG_COLOR(LOG_COLOR_RED) -#define LOG_COLOR_W LOG_COLOR(LOG_COLOR_BROWN) -#define LOG_COLOR_I LOG_COLOR(LOG_COLOR_GREEN) -#define LOG_COLOR_D +#define LOG_COLOR_E "\033[1;31m" +#define LOG_COLOR_W "\033[1;33m" +#define LOG_COLOR_I "\033[1m" +#define LOG_COLOR_D "\033[0;32m" #define LOG_COLOR_V #else /* MODULE_ESP_LOG_COLORED */ @@ -65,6 +62,7 @@ extern uint32_t system_get_time_ms (void); do { \ if ((unsigned)level <= (unsigned)LOG_LEVEL) { \ printf(LOG_FORMAT(letter, format), system_get_time_ms(), tag, ##__VA_ARGS__); \ + fflush(stdout); \ } \ } while(0) @@ -84,6 +82,7 @@ extern uint32_t system_get_time_ms (void); (void)tag; \ if ((unsigned)level <= (unsigned)LOG_LEVEL) { \ printf(LOG_FORMAT(letter, format), ##__VA_ARGS__); \ + fflush(stdout); \ } \ } while (0U)