mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
feat(log): Use esp_log func in all LOG macros
This commit is contained in:
committed by
BOT
parent
a29589e266
commit
a5bc08fb55
@@ -13,7 +13,11 @@ endif()
|
||||
|
||||
set(srcs "src/${system_target}/log_timestamp.c"
|
||||
"src/log_timestamp_common.c"
|
||||
"src/${system_target}/log_lock.c")
|
||||
"src/${system_target}/log_lock.c"
|
||||
"src/${system_target}/util.c"
|
||||
"src/log_print.c"
|
||||
"src/log.c")
|
||||
|
||||
set(priv_requires "")
|
||||
|
||||
if(NOT non_os_build)
|
||||
|
||||
@@ -1,5 +1,51 @@
|
||||
menu "Log"
|
||||
|
||||
choice LOG_VERSION
|
||||
prompt "Log version"
|
||||
default LOG_VERSION_1
|
||||
help
|
||||
Select the log version to be used by the ESP log component.
|
||||
|
||||
- "V1": This version integrates log formatting into the format string provided by the user.
|
||||
Logs are processed and formatted during compile time, leading to a larger binary file.
|
||||
Example: ESP_LOGI("boot", "chip revision: v%d.%d", major, minor);
|
||||
Output: I (56) boot: chip revision: v3.0
|
||||
Note: Log strings are stored in Flash with added formatting characters.
|
||||
Format string on flash: "[0;32mI (%lu) %s: chip revision: v%d.%d [0m"
|
||||
|
||||
- "V2": This version centralizes log formatting within the esp_log() function.
|
||||
User-supplied format strings are stored without added formatting, reducing binary size.
|
||||
Example: ESP_LOGI("boot", "chip revision: v%d.%d", major, minor);
|
||||
Output: I (56) boot: chip revision: v3.0
|
||||
Note: This version supports runtime configuration of formatting and is more flexible,
|
||||
logging from constrained environments (ex.: ISR, Startup, Cache disabled).
|
||||
It may consumes a bit more stack and affect performance.
|
||||
Format string on flash: "chip revision: v%d.%d"
|
||||
|
||||
Use V1 for minimal stack usage and simpler implementation.
|
||||
Use V2 for smaller binary sizes, more flexible log formatting, and advanced features like disabling
|
||||
colors or timestamps.
|
||||
|
||||
config LOG_VERSION_1
|
||||
bool "V1"
|
||||
help
|
||||
Select this option to use Log V1. Recommended for projects with strict stack constraints
|
||||
or that prioritize performance over flexibility.
|
||||
|
||||
config LOG_VERSION_2
|
||||
bool "V2"
|
||||
help
|
||||
Select this option to use Log V2. Recommended for projects that require smaller binaries,
|
||||
runtime log formatting configuration, or advanced logging features.
|
||||
endchoice
|
||||
|
||||
config LOG_VERSION
|
||||
int
|
||||
default 1 if LOG_VERSION_1
|
||||
default 2 if LOG_VERSION_2
|
||||
help
|
||||
This configuration sets the log version number based on the chosen log version.
|
||||
|
||||
orsource "./Kconfig.level"
|
||||
|
||||
orsource "./Kconfig.format"
|
||||
|
||||
@@ -3,10 +3,23 @@ menu "Format"
|
||||
config LOG_COLORS
|
||||
bool "Color"
|
||||
default n
|
||||
select LOG_COLORS_SUPPORT if LOG_VERSION_2
|
||||
help
|
||||
Enable ANSI terminal color codes.
|
||||
Enable ANSI terminal color codes. Logs (info, errors, warnings) will contain color codes.
|
||||
In order to view these, your terminal program must support ANSI color codes.
|
||||
|
||||
config LOG_COLORS_SUPPORT
|
||||
bool "Allow enabling color output at run time"
|
||||
depends on LOG_VERSION_2
|
||||
default n
|
||||
help
|
||||
Enables support for color codes in the esp_log() function. If CONFIG_LOG_COLORS is enabled, this option
|
||||
is always active. If CONFIG_LOG_COLORS is disabled, this option allows you to still handle color codes
|
||||
in specific files by defining ESP_LOG_COLOR_DISABLED as 0 before including esp_log.h.
|
||||
|
||||
Note that enabling this option may slightly increase IRAM usage due to additional color handling
|
||||
functionality. It provides flexibility to manage color output even when CONFIG_LOG_COLORS is turned off.
|
||||
|
||||
choice LOG_TIMESTAMP_SOURCE
|
||||
prompt "Timestamp"
|
||||
default LOG_TIMESTAMP_SOURCE_RTOS
|
||||
@@ -43,14 +56,30 @@ menu "Format"
|
||||
|
||||
config LOG_TIMESTAMP_SOURCE_RTOS
|
||||
bool "Milliseconds Since Boot"
|
||||
select LOG_TIMESTAMP_SUPPORT if LOG_VERSION_2
|
||||
|
||||
config LOG_TIMESTAMP_SOURCE_SYSTEM
|
||||
bool "System Time (HH:MM:SS.sss)"
|
||||
select LOG_TIMESTAMP_SUPPORT if LOG_VERSION_2
|
||||
|
||||
config LOG_TIMESTAMP_SOURCE_SYSTEM_FULL
|
||||
bool "System Time (YY-MM-DD HH:MM:SS.sss)"
|
||||
depends on NO_SYMBOL # hide it now, turn it on final MR
|
||||
select LOG_TIMESTAMP_SUPPORT if LOG_VERSION_2
|
||||
depends on LOG_VERSION_2
|
||||
|
||||
endchoice # LOG_TIMESTAMP_SOURCE
|
||||
|
||||
config LOG_TIMESTAMP_SUPPORT
|
||||
bool "Allow enabling timestamp output at run time"
|
||||
depends on LOG_VERSION_2
|
||||
default y
|
||||
help
|
||||
Enables support for timestamp in the esp_log() function.
|
||||
If CONFIG_LOG_TIMESTAMP_SOURCE_NONE, this option allows you to still handle timestamp
|
||||
in specific files by defining ESP_LOG_TIMESTAMP_DISABLED as 0 before including esp_log.h.
|
||||
|
||||
Note that enabling this option may slightly increase IRAM usage due to additional timestamp handling
|
||||
functionality. It provides flexibility to manage timestamp output even when
|
||||
CONFIG_LOG_TIMESTAMP_SOURCE_NONE.
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -393,15 +393,117 @@ TEST_CASE("esp_log_util_cvt")
|
||||
TEST_CASE("esp_log_timestamp_str")
|
||||
{
|
||||
char buffer[64];
|
||||
bool critical = true;
|
||||
uint64_t timestamp_ms = esp_log_timestamp64(critical);
|
||||
esp_log_timestamp_str(critical, timestamp_ms, buffer);
|
||||
bool constrained_env = true;
|
||||
uint64_t timestamp_ms = esp_log_timestamp64(constrained_env);
|
||||
esp_log_timestamp_str(constrained_env, timestamp_ms, buffer);
|
||||
const std::regex test_print(EARLY_TIMESTAMP, std::regex::ECMAScript);
|
||||
CHECK(regex_search(string(buffer), test_print) == true);
|
||||
|
||||
critical = false;
|
||||
timestamp_ms = esp_log_timestamp64(critical);
|
||||
esp_log_timestamp_str(critical, timestamp_ms, buffer);
|
||||
constrained_env = false;
|
||||
timestamp_ms = esp_log_timestamp64(constrained_env);
|
||||
esp_log_timestamp_str(constrained_env, timestamp_ms, buffer);
|
||||
const std::regex test_print2(TIMESTAMP, std::regex::ECMAScript);
|
||||
CHECK(regex_search(string(buffer), test_print2) == true);
|
||||
}
|
||||
|
||||
TEST_CASE("esp_log with formatting")
|
||||
{
|
||||
PrintFixture fix(ESP_LOG_INFO);
|
||||
|
||||
esp_log_config_t config = {
|
||||
.opts = {
|
||||
.log_level = ESP_LOG_NONE,
|
||||
.constrained_env = false,
|
||||
.require_formatting = true,
|
||||
.dis_color = false,
|
||||
.dis_timestamp = false,
|
||||
.reserved = 0,
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 0; i <= 10; i++) {
|
||||
if (5 <= i && i < 7) {
|
||||
config.opts.log_level = ESP_LOG_INFO;
|
||||
} else if (7 <= i && i < 9) {
|
||||
config.opts.log_level = ESP_LOG_WARN;
|
||||
} else if (9 <= i) {
|
||||
config.opts.log_level = ESP_LOG_ERROR;
|
||||
};
|
||||
|
||||
esp_log(config, TEST_TAG, "Temp = %dC", i);
|
||||
|
||||
if (5 <= i && i < 7) {
|
||||
const std::regex test_print("I \\(" TIMESTAMP "\\) test: Temp = [0-9]+C", std::regex::ECMAScript);
|
||||
CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true);
|
||||
} else if (7 <= i && i < 9) {
|
||||
const std::regex test_print("W \\(" TIMESTAMP "\\) test: Temp = [0-9]+C", std::regex::ECMAScript);
|
||||
CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true);
|
||||
} else if (9 <= i) {
|
||||
const std::regex test_print("E \\(" TIMESTAMP "\\) test: Temp = [0-9]+C", std::regex::ECMAScript);
|
||||
CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true);
|
||||
} else {
|
||||
const std::regex test_print("", std::regex::ECMAScript);
|
||||
CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true);
|
||||
}
|
||||
fix.reset_buffer();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("esp_log without formatting")
|
||||
{
|
||||
PrintFixture fix(ESP_LOG_INFO);
|
||||
|
||||
esp_log_config_t config = {
|
||||
.opts = {
|
||||
.log_level = ESP_LOG_NONE,
|
||||
.constrained_env = false,
|
||||
.require_formatting = false, // print just text
|
||||
.dis_color = false,
|
||||
.dis_timestamp = false,
|
||||
.reserved = 0,
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 0; i <= 10; i++) {
|
||||
if (5 <= i && i < 7) {
|
||||
config.opts.log_level = ESP_LOG_INFO;
|
||||
} else if (7 <= i && i < 9) {
|
||||
config.opts.log_level = ESP_LOG_WARN;
|
||||
} else if (9 <= i) {
|
||||
config.opts.log_level = ESP_LOG_ERROR;
|
||||
};
|
||||
|
||||
esp_log(config, TEST_TAG, "Temp = %dC\n", i);
|
||||
|
||||
if (i >= 5) {
|
||||
const std::regex test_print("Temp = [0-9]+C", std::regex::ECMAScript);
|
||||
CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true);
|
||||
} else {
|
||||
const std::regex test_print("", std::regex::ECMAScript);
|
||||
CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true);
|
||||
}
|
||||
fix.reset_buffer();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("esp_log TAG can be NULL")
|
||||
{
|
||||
PrintFixture fix(ESP_LOG_INFO);
|
||||
|
||||
esp_log_config_t config = {
|
||||
.opts = {
|
||||
.log_level = ESP_LOG_ERROR,
|
||||
.constrained_env = false,
|
||||
.require_formatting = true,
|
||||
.dis_color = false,
|
||||
.dis_timestamp = false,
|
||||
.reserved = 0,
|
||||
}
|
||||
};
|
||||
|
||||
esp_log(config, NULL, "Temp = %dC", 120);
|
||||
|
||||
const std::regex test_print("E \\(" TIMESTAMP "\\) Temp = 120C", std::regex::ECMAScript);
|
||||
CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true);
|
||||
fix.reset_buffer();
|
||||
}
|
||||
|
||||
+211
-151
@@ -11,6 +11,7 @@
|
||||
#include <inttypes.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_log_config.h"
|
||||
#include "esp_log_level.h"
|
||||
#include "esp_log_color.h"
|
||||
#include "esp_log_buffer.h"
|
||||
@@ -22,197 +23,256 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Logs a formatted message using the provided log message configs and a variable argument list.
|
||||
*
|
||||
* @param config Configuration and level of the log message.
|
||||
* @param tag The tag string used to indicate the component from which to log.
|
||||
* It is also used to check whether logging is enabled for that tag (depends on CONFIG_LOG_TAG_LEVEL_IMPL).
|
||||
* If NULL then the tag is not printed.
|
||||
* @param format The format string for the log message.
|
||||
* @param ... Optional arguments to be formatted according to the format string.
|
||||
*/
|
||||
void esp_log(esp_log_config_t config, const char* tag, const char* format, ...);
|
||||
|
||||
/**
|
||||
* @brief Logs a formatted message using the provided log message configs and a variable argument list.
|
||||
*
|
||||
* @param config Configuration and level of the log message.
|
||||
* @param tag The tag string used to indicate the component from which to log.
|
||||
* It is also used to check whether logging is enabled for that tag (depends on CONFIG_LOG_TAG_LEVEL_IMPL).
|
||||
* If NULL then the tag is not printed.
|
||||
* @param format The format string for the log message.
|
||||
* @param args List of arguments.
|
||||
*/
|
||||
void esp_log_va(esp_log_config_t config, const char *tag, const char *format, va_list args);
|
||||
|
||||
/// macro to output logs in startup code, before heap allocator and syscalls have been initialized.
|
||||
/// Log at ``ESP_LOG_ERROR`` level. @see ``printf``,``ESP_LOGE``,``ESP_DRAM_LOGE``
|
||||
|
||||
/**
|
||||
* In the future, we want to become compatible with clang.
|
||||
* Hence, we provide two versions of the following macros which are using variadic arguments.
|
||||
* The first one is using the GNU extension \#\#__VA_ARGS__. The second one is using the C++20 feature __VA_OPT__(,).
|
||||
* The first one is using the GNU extension ``##__VA_ARGS__``. The second one is using the C++20 feature ``__VA_OPT__(,)``.
|
||||
* This allows users to compile their code with standard C++20 enabled instead of the GNU extension.
|
||||
* Below C++20, we haven't found any good alternative to using \#\#__VA_ARGS__.
|
||||
* Below C++20, we haven't found any good alternative to using ``##__VA_ARGS__``.
|
||||
*/
|
||||
#if defined(__cplusplus) && (__cplusplus > 201703L)
|
||||
#define ESP_EARLY_LOGE( tag, format, ... ) ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_ERROR, E __VA_OPT__(,) __VA_ARGS__)
|
||||
/// macro to output logs in startup code at ``ESP_LOG_WARN`` level. @see ``ESP_EARLY_LOGE``,``ESP_LOGE``, ``printf``
|
||||
#define ESP_EARLY_LOGW( tag, format, ... ) ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_WARN, W __VA_OPT__(,) __VA_ARGS__)
|
||||
/// macro to output logs in startup code at ``ESP_LOG_INFO`` level. @see ``ESP_EARLY_LOGE``,``ESP_LOGE``, ``printf``
|
||||
#define ESP_EARLY_LOGI( tag, format, ... ) ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_INFO, I __VA_OPT__(,) __VA_ARGS__)
|
||||
/// macro to output logs in startup code at ``ESP_LOG_DEBUG`` level. @see ``ESP_EARLY_LOGE``,``ESP_LOGE``, ``printf``
|
||||
#define ESP_EARLY_LOGD( tag, format, ... ) ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_DEBUG, D __VA_OPT__(,) __VA_ARGS__)
|
||||
/// macro to output logs in startup code at ``ESP_LOG_VERBOSE`` level. @see ``ESP_EARLY_LOGE``,``ESP_LOGE``, ``printf``
|
||||
#define ESP_EARLY_LOGV( tag, format, ... ) ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_VERBOSE, V __VA_OPT__(,) __VA_ARGS__)
|
||||
#else // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
#define ESP_EARLY_LOGE( tag, format, ... ) ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_ERROR, E, ##__VA_ARGS__)
|
||||
/// macro to output logs in startup code at ``ESP_LOG_WARN`` level. @see ``ESP_EARLY_LOGE``,``ESP_LOGE``, ``printf``
|
||||
#define ESP_EARLY_LOGW( tag, format, ... ) ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_WARN, W, ##__VA_ARGS__)
|
||||
/// macro to output logs in startup code at ``ESP_LOG_INFO`` level. @see ``ESP_EARLY_LOGE``,``ESP_LOGE``, ``printf``
|
||||
#define ESP_EARLY_LOGI( tag, format, ... ) ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_INFO, I, ##__VA_ARGS__)
|
||||
/// macro to output logs in startup code at ``ESP_LOG_DEBUG`` level. @see ``ESP_EARLY_LOGE``,``ESP_LOGE``, ``printf``
|
||||
#define ESP_EARLY_LOGD( tag, format, ... ) ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_DEBUG, D, ##__VA_ARGS__)
|
||||
/// macro to output logs in startup code at ``ESP_LOG_VERBOSE`` level. @see ``ESP_EARLY_LOGE``,``ESP_LOGE``, ``printf``
|
||||
#define ESP_EARLY_LOGV( tag, format, ... ) ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_VERBOSE, V, ##__VA_ARGS__)
|
||||
#endif // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
/** @cond */
|
||||
#define ESP_EARLY_LOGE(tag, format, ...) do { ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_ERROR, E __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define ESP_EARLY_LOGW(tag, format, ...) do { ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_WARN, W __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define ESP_EARLY_LOGI(tag, format, ...) do { ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_INFO, I __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define ESP_EARLY_LOGD(tag, format, ...) do { ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_DEBUG, D __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define ESP_EARLY_LOGV(tag, format, ...) do { ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_VERBOSE, V __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
|
||||
#define ESP_LOG_EARLY_IMPL(tag, format, log_level, log_tag_letter, ...) do { \
|
||||
if (_ESP_LOG_EARLY_ENABLED(log_level)) { \
|
||||
esp_rom_printf(LOG_FORMAT(log_tag_letter, format), esp_log_timestamp(), tag, ##__VA_ARGS__); \
|
||||
}} while(0)
|
||||
|
||||
#if !NON_OS_BUILD
|
||||
#if defined(__cplusplus) && (__cplusplus > 201703L)
|
||||
#define ESP_LOGE( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_ERROR, tag, format __VA_OPT__(,) __VA_ARGS__)
|
||||
#define ESP_LOGW( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_WARN, tag, format __VA_OPT__(,) __VA_ARGS__)
|
||||
#define ESP_LOGI( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_INFO, tag, format __VA_OPT__(,) __VA_ARGS__)
|
||||
#define ESP_LOGD( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_DEBUG, tag, format __VA_OPT__(,) __VA_ARGS__)
|
||||
#define ESP_LOGV( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_VERBOSE, tag, format __VA_OPT__(,) __VA_ARGS__)
|
||||
#else // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
#define ESP_LOGE( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_ERROR, tag, format, ##__VA_ARGS__)
|
||||
#define ESP_LOGW( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_WARN, tag, format, ##__VA_ARGS__)
|
||||
#define ESP_LOGI( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_INFO, tag, format, ##__VA_ARGS__)
|
||||
#define ESP_LOGD( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_DEBUG, tag, format, ##__VA_ARGS__)
|
||||
#define ESP_LOGV( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_VERBOSE, tag, format, ##__VA_ARGS__)
|
||||
#endif // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
#if ESP_LOG_VERSION == 1 && NON_OS_BUILD
|
||||
#define ESP_LOGE(tag, format, ...) do { ESP_EARLY_LOGE(tag, format __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define ESP_LOGW(tag, format, ...) do { ESP_EARLY_LOGW(tag, format __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define ESP_LOGI(tag, format, ...) do { ESP_EARLY_LOGI(tag, format __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define ESP_LOGD(tag, format, ...) do { ESP_EARLY_LOGD(tag, format __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define ESP_LOGV(tag, format, ...) do { ESP_EARLY_LOGV(tag, format __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#else
|
||||
#define ESP_LOGE(tag, format, ...) do { ESP_LOG_LEVEL_LOCAL(ESP_LOG_ERROR, tag, format __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define ESP_LOGW(tag, format, ...) do { ESP_LOG_LEVEL_LOCAL(ESP_LOG_WARN, tag, format __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define ESP_LOGI(tag, format, ...) do { ESP_LOG_LEVEL_LOCAL(ESP_LOG_INFO, tag, format __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define ESP_LOGD(tag, format, ...) do { ESP_LOG_LEVEL_LOCAL(ESP_LOG_DEBUG, tag, format __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define ESP_LOGV(tag, format, ...) do { ESP_LOG_LEVEL_LOCAL(ESP_LOG_VERBOSE, tag, format __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#endif
|
||||
|
||||
#define ESP_DRAM_LOGE(tag, format, ...) do { ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_ERROR, E __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define ESP_DRAM_LOGW(tag, format, ...) do { ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_WARN, W __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define ESP_DRAM_LOGI(tag, format, ...) do { ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_INFO, I __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define ESP_DRAM_LOGD(tag, format, ...) do { ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_DEBUG, D __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define ESP_DRAM_LOGV(tag, format, ...) do { ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_VERBOSE, V __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
/** @endcond */
|
||||
#else // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
/**
|
||||
* @brief Early log macros to output logs in startup code, before heap allocator and syscalls have been initialized.
|
||||
* The log level can be changed per-tag using ``esp_log_level_set(TAG, level)``.
|
||||
*/
|
||||
/// macro to output logs in startup code at ``ESP_LOG_ERROR`` level.
|
||||
#define ESP_EARLY_LOGE(tag, format, ...) do { ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_ERROR, E, ##__VA_ARGS__); } while(0)
|
||||
/// macro to output logs in startup code at ``ESP_LOG_WARN`` level.
|
||||
#define ESP_EARLY_LOGW(tag, format, ...) do { ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_WARN, W, ##__VA_ARGS__); } while(0)
|
||||
/// macro to output logs in startup code at ``ESP_LOG_INFO`` level.
|
||||
#define ESP_EARLY_LOGI(tag, format, ...) do { ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_INFO, I, ##__VA_ARGS__); } while(0)
|
||||
/// macro to output logs in startup code at ``ESP_LOG_DEBUG`` level.
|
||||
#define ESP_EARLY_LOGD(tag, format, ...) do { ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_DEBUG, D, ##__VA_ARGS__); } while(0)
|
||||
/// macro to output logs in startup code at ``ESP_LOG_VERBOSE`` level.
|
||||
#define ESP_EARLY_LOGV(tag, format, ...) do { ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_VERBOSE, V, ##__VA_ARGS__); } while(0)
|
||||
|
||||
/**
|
||||
* Macro to output logs at ESP_LOG_ERROR level.
|
||||
*
|
||||
* @note This macro cannot be used when interrupts are disabled or inside an ISR. @see ``ESP_DRAM_LOGE``.
|
||||
*
|
||||
* @param tag tag of the log, which can be used to change the log level by ``esp_log_level_set`` at runtime.
|
||||
*
|
||||
* @see ``printf``
|
||||
* @brief Normal logging macros to output logs.
|
||||
* The log level can be changed per-tag using ``esp_log_level_set(TAG, level)``.
|
||||
*/
|
||||
#if defined(__cplusplus) && (__cplusplus > 201703L)
|
||||
#define ESP_LOGE( tag, format, ... ) ESP_EARLY_LOGE(tag, format __VA_OPT__(,) __VA_ARGS__)
|
||||
/// macro to output logs at ``ESP_LOG_WARN`` level. @see ``ESP_LOGE``
|
||||
#define ESP_LOGW( tag, format, ... ) ESP_EARLY_LOGW(tag, format __VA_OPT__(,) __VA_ARGS__)
|
||||
/// macro to output logs at ``ESP_LOG_INFO`` level. @see ``ESP_LOGE``
|
||||
#define ESP_LOGI( tag, format, ... ) ESP_EARLY_LOGI(tag, format __VA_OPT__(,) __VA_ARGS__)
|
||||
/// macro to output logs at ``ESP_LOG_DEBUG`` level. @see ``ESP_LOGE``
|
||||
#define ESP_LOGD( tag, format, ... ) ESP_EARLY_LOGD(tag, format __VA_OPT__(,) __VA_ARGS__)
|
||||
/// macro to output logs at ``ESP_LOG_VERBOSE`` level. @see ``ESP_LOGE``
|
||||
#define ESP_LOGV( tag, format, ... ) ESP_EARLY_LOGV(tag, format __VA_OPT__(,) __VA_ARGS__)
|
||||
#else // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
#define ESP_LOGE( tag, format, ... ) ESP_EARLY_LOGE(tag, format, ##__VA_ARGS__)
|
||||
/// macro to output logs at ``ESP_LOG_WARN`` level. @see ``ESP_LOGE``
|
||||
#define ESP_LOGW( tag, format, ... ) ESP_EARLY_LOGW(tag, format, ##__VA_ARGS__)
|
||||
/// macro to output logs at ``ESP_LOG_INFO`` level. @see ``ESP_LOGE``
|
||||
#define ESP_LOGI( tag, format, ... ) ESP_EARLY_LOGI(tag, format, ##__VA_ARGS__)
|
||||
/// macro to output logs at ``ESP_LOG_DEBUG`` level. @see ``ESP_LOGE``
|
||||
#define ESP_LOGD( tag, format, ... ) ESP_EARLY_LOGD(tag, format, ##__VA_ARGS__)
|
||||
/// macro to output logs at ``ESP_LOG_VERBOSE`` level. @see ``ESP_LOGE``
|
||||
#define ESP_LOGV( tag, format, ... ) ESP_EARLY_LOGV(tag, format, ##__VA_ARGS__)
|
||||
#endif // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
#endif // !NON_OS_BUILD
|
||||
#if ESP_LOG_VERSION == 1 && NON_OS_BUILD
|
||||
/// macro to output logs at ``ESP_LOG_ERROR`` level.
|
||||
#define ESP_LOGE(tag, format, ...) do { ESP_EARLY_LOGE(tag, format, ##__VA_ARGS__); } while(0)
|
||||
/// macro to output logs at ``ESP_LOG_WARN`` level.
|
||||
#define ESP_LOGW(tag, format, ...) do { ESP_EARLY_LOGW(tag, format, ##__VA_ARGS__); } while(0)
|
||||
/// macro to output logs at ``ESP_LOG_INFO`` level.
|
||||
#define ESP_LOGI(tag, format, ...) do { ESP_EARLY_LOGI(tag, format, ##__VA_ARGS__); } while(0)
|
||||
/// macro to output logs at ``ESP_LOG_DEBUG`` level.
|
||||
#define ESP_LOGD(tag, format, ...) do { ESP_EARLY_LOGD(tag, format, ##__VA_ARGS__); } while(0)
|
||||
/// macro to output logs at ``ESP_LOG_VERBOSE`` level.
|
||||
#define ESP_LOGV(tag, format, ...) do { ESP_EARLY_LOGV(tag, format, ##__VA_ARGS__); } while(0)
|
||||
#else
|
||||
/// macro to output logs at ``ESP_LOG_ERROR`` level.
|
||||
#define ESP_LOGE(tag, format, ...) do { ESP_LOG_LEVEL_LOCAL(ESP_LOG_ERROR, tag, format, ##__VA_ARGS__); } while(0)
|
||||
/// macro to output logs at ``ESP_LOG_WARN`` level.
|
||||
#define ESP_LOGW(tag, format, ...) do { ESP_LOG_LEVEL_LOCAL(ESP_LOG_WARN, tag, format, ##__VA_ARGS__); } while(0)
|
||||
/// macro to output logs at ``ESP_LOG_INFO`` level.
|
||||
#define ESP_LOGI(tag, format, ...) do { ESP_LOG_LEVEL_LOCAL(ESP_LOG_INFO, tag, format, ##__VA_ARGS__); } while(0)
|
||||
/// macro to output logs at ``ESP_LOG_DEBUG`` level.
|
||||
#define ESP_LOGD(tag, format, ...) do { ESP_LOG_LEVEL_LOCAL(ESP_LOG_DEBUG, tag, format, ##__VA_ARGS__); } while(0)
|
||||
/// macro to output logs at ``ESP_LOG_VERBOSE`` level.
|
||||
#define ESP_LOGV(tag, format, ...) do { ESP_LOG_LEVEL_LOCAL(ESP_LOG_VERBOSE, tag, format, ##__VA_ARGS__); } while(0)
|
||||
#endif
|
||||
|
||||
/** runtime macro to output logs at a specified level.
|
||||
/**
|
||||
* @brief Macros to output logs when the cache is disabled.
|
||||
* Unlike normal logging macros, it's possible to use this macro when interrupts are disabled or inside an ISR.
|
||||
* Placing log strings in DRAM reduces available DRAM, so only use when absolutely essential.
|
||||
*
|
||||
* Usage: `ESP_DRAM_LOGE(DRAM_STR("my_tag"), "format", ...), or `ESP_DRAM_LOGE(TAG, "format", ...)`,
|
||||
* where TAG is a char* that points to a str in the DRAM.
|
||||
*/
|
||||
/// macro to output logs when the cache is disabled at ``ESP_LOG_ERROR`` level.
|
||||
#define ESP_DRAM_LOGE(tag, format, ...) do { ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_ERROR, E, ##__VA_ARGS__); } while(0)
|
||||
/// macro to output logs when the cache is disabled at ``ESP_LOG_WARN`` level.
|
||||
#define ESP_DRAM_LOGW(tag, format, ...) do { ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_WARN, W, ##__VA_ARGS__); } while(0)
|
||||
/// macro to output logs when the cache is disabled at ``ESP_LOG_INFO`` level.
|
||||
#define ESP_DRAM_LOGI(tag, format, ...) do { ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_INFO, I, ##__VA_ARGS__); } while(0)
|
||||
/// macro to output logs when the cache is disabled at ``ESP_LOG_DEBUG`` level.
|
||||
#define ESP_DRAM_LOGD(tag, format, ...) do { ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_DEBUG, D, ##__VA_ARGS__); } while(0)
|
||||
/// macro to output logs when the cache is disabled at ``ESP_LOG_VERBOSE`` level.
|
||||
#define ESP_DRAM_LOGV(tag, format, ...) do { ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_VERBOSE, V, ##__VA_ARGS__); } while(0)
|
||||
#endif // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
|
||||
/// runtime macro to output logs at a specified configs. Also check the level with ``LOG_LOCAL_LEVEL``.
|
||||
#if ESP_LOG_VERSION == 2
|
||||
#if defined(__cplusplus) && (__cplusplus > 201703L)
|
||||
#define ESP_LOG_LEVEL_LOCAL(configs, tag, format, ...) do { if (ESP_LOG_ENABLED(configs)) { ESP_LOG_LEVEL(configs, tag, format __VA_OPT__(,) __VA_ARGS__); } } while(0)
|
||||
#else // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
#define ESP_LOG_LEVEL_LOCAL(configs, tag, format, ...) do { if (ESP_LOG_ENABLED(configs)) { ESP_LOG_LEVEL(configs, tag, format, ##__VA_ARGS__); } } while(0)
|
||||
#endif // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
#else // ESP_LOG_VERSION == 1
|
||||
#if defined(__cplusplus) && (__cplusplus > 201703L)
|
||||
#define ESP_LOG_LEVEL_LOCAL(configs, tag, format, ...) do { if (_ESP_LOG_ENABLED(configs)) { ESP_LOG_LEVEL(configs, tag, format __VA_OPT__(,) __VA_ARGS__); } } while(0)
|
||||
#else // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
#define ESP_LOG_LEVEL_LOCAL(configs, tag, format, ...) do { if (_ESP_LOG_ENABLED(configs)) { ESP_LOG_LEVEL(configs, tag, format, ##__VA_ARGS__); } } while(0)
|
||||
#endif // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
#endif // ESP_LOG_VERSION == 1
|
||||
|
||||
/** runtime macro to output logs at a specified level and with ESP_LOG_CONFIGS_DEFAULT.
|
||||
*
|
||||
* @param configs it includes level and other log configurations.
|
||||
* @param tag tag of the log, which can be used to change the log level by ``esp_log_level_set`` at runtime.
|
||||
* @param level level of the output log.
|
||||
* @param format format of the output log. See ``printf``
|
||||
* @param ... variables to be replaced into the log. See ``printf``
|
||||
*
|
||||
* @see ``printf``
|
||||
*/
|
||||
#if ESP_LOG_VERSION == 2
|
||||
#if defined(__cplusplus) && (__cplusplus > 201703L)
|
||||
#define ESP_LOG_LEVEL(configs, tag, format, ...) do { \
|
||||
esp_log(ESP_LOG_CONFIG_INIT(configs | ESP_LOG_CONFIGS_DEFAULT), tag, format __VA_OPT__(,) __VA_ARGS__); \
|
||||
} while(0)
|
||||
#else // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
#define ESP_LOG_LEVEL(configs, tag, format, ...) do { \
|
||||
esp_log(ESP_LOG_CONFIG_INIT(configs | ESP_LOG_CONFIGS_DEFAULT), tag, format, ##__VA_ARGS__); \
|
||||
} while(0)
|
||||
#endif // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
|
||||
#else // ESP_LOG_VERSION == 1
|
||||
|
||||
#if defined(__cplusplus) && (__cplusplus > 201703L)
|
||||
#if CONFIG_LOG_TIMESTAMP_SOURCE_RTOS
|
||||
#define ESP_LOG_LEVEL(level, tag, format, ...) do { \
|
||||
if (level==ESP_LOG_ERROR ) { esp_log_write(ESP_LOG_ERROR, tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else if (level==ESP_LOG_WARN ) { esp_log_write(ESP_LOG_WARN, tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else if (level==ESP_LOG_DEBUG ) { esp_log_write(ESP_LOG_DEBUG, tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else if (level==ESP_LOG_VERBOSE ) { esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else { esp_log_write(ESP_LOG_INFO, tag, LOG_FORMAT(I, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
#define ESP_LOG_LEVEL(configs, tag, format, ...) do { \
|
||||
if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_ERROR) { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_ERROR), tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_WARN) { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_WARN), tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_DEBUG) { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_DEBUG), tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_VERBOSE) { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_VERBOSE), tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_INFO), tag, LOG_FORMAT(I, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
} while(0)
|
||||
#elif CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM
|
||||
#define ESP_LOG_LEVEL(level, tag, format, ...) do { \
|
||||
if (level==ESP_LOG_ERROR ) { esp_log_write(ESP_LOG_ERROR, tag, LOG_SYSTEM_TIME_FORMAT(E, format), esp_log_system_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else if (level==ESP_LOG_WARN ) { esp_log_write(ESP_LOG_WARN, tag, LOG_SYSTEM_TIME_FORMAT(W, format), esp_log_system_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else if (level==ESP_LOG_DEBUG ) { esp_log_write(ESP_LOG_DEBUG, tag, LOG_SYSTEM_TIME_FORMAT(D, format), esp_log_system_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else if (level==ESP_LOG_VERBOSE ) { esp_log_write(ESP_LOG_VERBOSE, tag, LOG_SYSTEM_TIME_FORMAT(V, format), esp_log_system_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else { esp_log_write(ESP_LOG_INFO, tag, LOG_SYSTEM_TIME_FORMAT(I, format), esp_log_system_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
#define ESP_LOG_LEVEL(configs, tag, format, ...) do { \
|
||||
if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_ERROR) { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_ERROR), tag, LOG_SYSTEM_TIME_FORMAT(E, format), esp_log_system_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_WARN) { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_WARN), tag, LOG_SYSTEM_TIME_FORMAT(W, format), esp_log_system_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_DEBUG) { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_DEBUG), tag, LOG_SYSTEM_TIME_FORMAT(D, format), esp_log_system_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_VERBOSE) { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_VERBOSE), tag, LOG_SYSTEM_TIME_FORMAT(V, format), esp_log_system_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_INFO), tag, LOG_SYSTEM_TIME_FORMAT(I, format), esp_log_system_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
} while(0)
|
||||
#elif NON_OS_BUILD
|
||||
#define ESP_LOG_LEVEL(configs, tag, format, ...) do { \
|
||||
if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_ERROR) { ESP_EARLY_LOGE(tag, format __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_WARN) { ESP_EARLY_LOGW(tag, format __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_DEBUG) { ESP_EARLY_LOGD(tag, format __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_VERBOSE) { ESP_EARLY_LOGV(tag, format __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else { ESP_EARLY_LOGI(tag, format __VA_OPT__(,) __VA_ARGS__); } \
|
||||
} while(0)
|
||||
#endif //CONFIG_LOG_TIMESTAMP_SOURCE_xxx
|
||||
#else // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
#if CONFIG_LOG_TIMESTAMP_SOURCE_RTOS
|
||||
#define ESP_LOG_LEVEL(level, tag, format, ...) do { \
|
||||
if (level==ESP_LOG_ERROR ) { esp_log_write(ESP_LOG_ERROR, tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
else if (level==ESP_LOG_WARN ) { esp_log_write(ESP_LOG_WARN, tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
else if (level==ESP_LOG_DEBUG ) { esp_log_write(ESP_LOG_DEBUG, tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
else if (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__); } \
|
||||
#define ESP_LOG_LEVEL(configs, tag, format, ...) do { \
|
||||
if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_ERROR) { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_ERROR), tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
else if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_WARN) { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_WARN), tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
else if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_DEBUG) { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_DEBUG), tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
else if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_VERBOSE) { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_VERBOSE), tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
else { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_INFO), tag, LOG_FORMAT(I, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
} while(0)
|
||||
#elif CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM
|
||||
#define ESP_LOG_LEVEL(level, tag, format, ...) do { \
|
||||
if (level==ESP_LOG_ERROR ) { esp_log_write(ESP_LOG_ERROR, tag, LOG_SYSTEM_TIME_FORMAT(E, format), esp_log_system_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
else if (level==ESP_LOG_WARN ) { esp_log_write(ESP_LOG_WARN, tag, LOG_SYSTEM_TIME_FORMAT(W, format), esp_log_system_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
else if (level==ESP_LOG_DEBUG ) { esp_log_write(ESP_LOG_DEBUG, tag, LOG_SYSTEM_TIME_FORMAT(D, format), esp_log_system_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
else if (level==ESP_LOG_VERBOSE ) { esp_log_write(ESP_LOG_VERBOSE, tag, LOG_SYSTEM_TIME_FORMAT(V, format), esp_log_system_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
else { esp_log_write(ESP_LOG_INFO, tag, LOG_SYSTEM_TIME_FORMAT(I, format), esp_log_system_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
#define ESP_LOG_LEVEL(configs, tag, format, ...) do { \
|
||||
if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_ERROR) { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_ERROR), tag, LOG_SYSTEM_TIME_FORMAT(E, format), esp_log_system_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
else if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_WARN) { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_WARN), tag, LOG_SYSTEM_TIME_FORMAT(W, format), esp_log_system_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
else if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_DEBUG) { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_DEBUG), tag, LOG_SYSTEM_TIME_FORMAT(D, format), esp_log_system_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
else if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_VERBOSE) { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_VERBOSE), tag, LOG_SYSTEM_TIME_FORMAT(V, format), esp_log_system_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
else { esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_INFO), tag, LOG_SYSTEM_TIME_FORMAT(I, format), esp_log_system_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
} while(0)
|
||||
#elif NON_OS_BUILD
|
||||
#define ESP_LOG_LEVEL(configs, tag, format, ...) do { \
|
||||
if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_ERROR) { ESP_EARLY_LOGE(tag, format, ##__VA_ARGS__); } \
|
||||
else if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_WARN) { ESP_EARLY_LOGW(tag, format, ##__VA_ARGS__); } \
|
||||
else if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_DEBUG) { ESP_EARLY_LOGD(tag, format, ##__VA_ARGS__); } \
|
||||
else if (ESP_LOG_GET_LEVEL(configs)==ESP_LOG_VERBOSE) { ESP_EARLY_LOGV(tag, format, ##__VA_ARGS__); } \
|
||||
else { ESP_EARLY_LOGI(tag, format, ##__VA_ARGS__); } \
|
||||
} while(0)
|
||||
#endif //CONFIG_LOG_TIMESTAMP_SOURCE_xxx
|
||||
#endif // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
|
||||
/** runtime macro to output logs at a specified level. Also check the level with ``LOG_LOCAL_LEVEL``.
|
||||
* If ``CONFIG_LOG_MASTER_LEVEL`` set, also check first against ``esp_log_get_level_master()``.
|
||||
*
|
||||
* @see ``printf``, ``ESP_LOG_LEVEL``
|
||||
*/
|
||||
#define ESP_LOG_LEVEL_LOCAL(level, tag, format, ...) do { \
|
||||
if (_ESP_LOG_ENABLED(level)) ESP_LOG_LEVEL(level, tag, format, ##__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Macro to output logs when the cache is disabled. Log at ``ESP_LOG_ERROR`` level.
|
||||
*
|
||||
* @note Unlike normal logging macros, it's possible to use this macro when interrupts are
|
||||
* disabled or inside an ISR.
|
||||
*
|
||||
* Similar to @see ``ESP_EARLY_LOGE``, the log level cannot be changed per-tag, however
|
||||
* esp_log_level_set("*", level) will set the default level which controls these log lines also.
|
||||
*
|
||||
* Usage: `ESP_DRAM_LOGE(DRAM_STR("my_tag"), "format", or `ESP_DRAM_LOGE(TAG, "format", ...)`,
|
||||
* where TAG is a char* that points to a str in the DRAM.
|
||||
*
|
||||
* @note Placing log strings in DRAM reduces available DRAM, so only use when absolutely essential.
|
||||
*
|
||||
* @see ``esp_rom_printf``,``ESP_LOGE``
|
||||
*/
|
||||
#if defined(__cplusplus) && (__cplusplus > 201703L)
|
||||
#define ESP_DRAM_LOGE( tag, format, ... ) ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_ERROR, E __VA_OPT__(,) __VA_ARGS__)
|
||||
/// macro to output logs when the cache is disabled at ``ESP_LOG_WARN`` level. @see ``ESP_DRAM_LOGW``,``ESP_LOGW``, ``esp_rom_printf``
|
||||
#define ESP_DRAM_LOGW( tag, format, ... ) ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_WARN, W __VA_OPT__(,) __VA_ARGS__)
|
||||
/// macro to output logs when the cache is disabled at ``ESP_LOG_INFO`` level. @see ``ESP_DRAM_LOGI``,``ESP_LOGI``, ``esp_rom_printf``
|
||||
#define ESP_DRAM_LOGI( tag, format, ... ) ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_INFO, I __VA_OPT__(,) __VA_ARGS__)
|
||||
/// macro to output logs when the cache is disabled at ``ESP_LOG_DEBUG`` level. @see ``ESP_DRAM_LOGD``,``ESP_LOGD``, ``esp_rom_printf``
|
||||
#define ESP_DRAM_LOGD( tag, format, ... ) ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_DEBUG, D __VA_OPT__(,) __VA_ARGS__)
|
||||
/// macro to output logs when the cache is disabled at ``ESP_LOG_VERBOSE`` level. @see ``ESP_DRAM_LOGV``,``ESP_LOGV``, ``esp_rom_printf``
|
||||
#define ESP_DRAM_LOGV( tag, format, ... ) ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_VERBOSE, V __VA_OPT__(,) __VA_ARGS__)
|
||||
#else // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
#define ESP_DRAM_LOGE( tag, format, ... ) ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_ERROR, E, ##__VA_ARGS__)
|
||||
/// macro to output logs when the cache is disabled at ``ESP_LOG_WARN`` level. @see ``ESP_DRAM_LOGW``,``ESP_LOGW``, ``esp_rom_printf``
|
||||
#define ESP_DRAM_LOGW( tag, format, ... ) ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_WARN, W, ##__VA_ARGS__)
|
||||
/// macro to output logs when the cache is disabled at ``ESP_LOG_INFO`` level. @see ``ESP_DRAM_LOGI``,``ESP_LOGI``, ``esp_rom_printf``
|
||||
#define ESP_DRAM_LOGI( tag, format, ... ) ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_INFO, I, ##__VA_ARGS__)
|
||||
/// macro to output logs when the cache is disabled at ``ESP_LOG_DEBUG`` level. @see ``ESP_DRAM_LOGD``,``ESP_LOGD``, ``esp_rom_printf``
|
||||
#define ESP_DRAM_LOGD( tag, format, ... ) ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_DEBUG, D, ##__VA_ARGS__)
|
||||
/// macro to output logs when the cache is disabled at ``ESP_LOG_VERBOSE`` level. @see ``ESP_DRAM_LOGV``,``ESP_LOGV``, ``esp_rom_printf``
|
||||
#define ESP_DRAM_LOGV( tag, format, ... ) ESP_DRAM_LOG_IMPL(tag, format, ESP_LOG_VERBOSE, V, ##__VA_ARGS__)
|
||||
#endif // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
#endif // ESP_LOG_VERSION == 1
|
||||
|
||||
/** @cond */
|
||||
|
||||
#if defined(__cplusplus) && (__cplusplus > 201703L)
|
||||
#define ESP_DRAM_LOG_IMPL(tag, format, log_level, log_tag_letter, ...) do { \
|
||||
if (_ESP_LOG_EARLY_ENABLED(log_level)) { \
|
||||
esp_rom_printf(_ESP_LOG_DRAM_LOG_FORMAT(log_tag_letter, format), tag __VA_OPT__(,) __VA_ARGS__); \
|
||||
}} while(0)
|
||||
#define ESP_LOG_EARLY_IMPL(tag, format, configs, log_tag_letter, ...) do { \
|
||||
if (ESP_LOG_VERSION == 1) { \
|
||||
if (_ESP_LOG_EARLY_ENABLED(configs)) { esp_rom_printf(LOG_FORMAT(log_tag_letter, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
} else { \
|
||||
if (ESP_LOG_ENABLED(configs)) { esp_log(ESP_LOG_CONFIG_INIT(configs | ESP_LOG_CONFIGS_DEFAULT | ESP_LOG_CONFIG_CONSTRAINED_ENV), tag, format __VA_OPT__(,) __VA_ARGS__); } \
|
||||
} } while(0)
|
||||
#else // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
#define ESP_DRAM_LOG_IMPL(tag, format, log_level, log_tag_letter, ...) do { \
|
||||
if (_ESP_LOG_EARLY_ENABLED(log_level)) { \
|
||||
esp_rom_printf(_ESP_LOG_DRAM_LOG_FORMAT(log_tag_letter, format), tag, ##__VA_ARGS__); \
|
||||
}} while(0)
|
||||
#define ESP_LOG_EARLY_IMPL(tag, format, configs, log_tag_letter, ...) do { \
|
||||
if (ESP_LOG_VERSION == 1) { \
|
||||
if (_ESP_LOG_EARLY_ENABLED(configs)) { esp_rom_printf(LOG_FORMAT(log_tag_letter, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } \
|
||||
} else { \
|
||||
if (ESP_LOG_ENABLED(configs)) { esp_log(ESP_LOG_CONFIG_INIT(configs | ESP_LOG_CONFIGS_DEFAULT | ESP_LOG_CONFIG_CONSTRAINED_ENV), tag, format, ##__VA_ARGS__); } \
|
||||
} } while(0)
|
||||
#endif // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
|
||||
#if defined(__cplusplus) && (__cplusplus > 201703L)
|
||||
#define ESP_DRAM_LOG_IMPL(tag, format, configs, log_tag_letter, ...) do { \
|
||||
if (ESP_LOG_VERSION == 1) { \
|
||||
if (_ESP_LOG_EARLY_ENABLED(configs)) { esp_rom_printf(_ESP_LOG_DRAM_LOG_FORMAT(log_tag_letter, format), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
} else { \
|
||||
if (ESP_LOG_ENABLED(configs)) { esp_log(ESP_LOG_CONFIG_INIT(configs | ESP_LOG_CONFIGS_DEFAULT | ESP_LOG_CONFIG_CONSTRAINED_ENV | ESP_LOG_CONFIG_DIS_COLOR | ESP_LOG_CONFIG_DIS_TIMESTAMP), tag, DRAM_STR(format) __VA_OPT__(,) __VA_ARGS__); } \
|
||||
} } while(0)
|
||||
#else // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
#define ESP_DRAM_LOG_IMPL(tag, format, configs, log_tag_letter, ...) do { \
|
||||
if (ESP_LOG_VERSION == 1) { \
|
||||
if (_ESP_LOG_EARLY_ENABLED(configs)) { esp_rom_printf(_ESP_LOG_DRAM_LOG_FORMAT(log_tag_letter, format), tag, ##__VA_ARGS__); } \
|
||||
} else { \
|
||||
if (ESP_LOG_ENABLED(configs)) { esp_log(ESP_LOG_CONFIG_INIT(configs | ESP_LOG_CONFIGS_DEFAULT | ESP_LOG_CONFIG_CONSTRAINED_ENV | ESP_LOG_CONFIG_DIS_COLOR | ESP_LOG_CONFIG_DIS_TIMESTAMP), tag, DRAM_STR(format), ##__VA_ARGS__); } \
|
||||
} } while(0)
|
||||
#endif // !(defined(__cplusplus) && (__cplusplus > 201703L))
|
||||
/** @endcond */
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_log_config.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -13,6 +14,13 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/** @cond */
|
||||
// Determines whether esp_log() includes code to handle color codes.
|
||||
#if (!BOOTLOADER_BUILD && CONFIG_LOG_COLORS_SUPPORT) || (BOOTLOADER_BUILD && CONFIG_BOOTLOADER_LOG_COLORS_SUPPORT)
|
||||
#define ESP_LOG_SUPPORT_COLOR (1)
|
||||
#else
|
||||
#define ESP_LOG_SUPPORT_COLOR (0)
|
||||
#endif
|
||||
|
||||
// ANSI Color Codes:
|
||||
// Macros for defining foreground colors (text).
|
||||
#define LOG_ANSI_COLOR_BLACK "30"
|
||||
@@ -77,7 +85,7 @@ extern "C" {
|
||||
* printf(LOG_ANSI_COLOR_FORMAT(LOG_ANSI_COLOR_STYLE_BOLD, LOG_ANSI_COLOR_WHITE, LOG_ANSI_COLOR_BG_BLUE) "%s" LOG_ANSI_COLOR_RESET "\n", text_str);
|
||||
*/
|
||||
|
||||
#if (!BOOTLOADER_BUILD && CONFIG_LOG_COLORS) || (BOOTLOADER_BUILD && CONFIG_BOOTLOADER_LOG_COLORS)
|
||||
#if !ESP_LOG_COLOR_DISABLED
|
||||
#define LOG_COLOR_BLACK LOG_ANSI_COLOR_BLACK
|
||||
#define LOG_COLOR_RED LOG_ANSI_COLOR_RED
|
||||
#define LOG_COLOR_GREEN LOG_ANSI_COLOR_GREEN
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
#include "esp_log_level.h"
|
||||
#include "esp_assert.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @cond */
|
||||
/// Log version macros.
|
||||
#define ESP_LOG_V2 (1)
|
||||
#if BOOTLOADER_BUILD
|
||||
#define ESP_LOG_VERSION (CONFIG_BOOTLOADER_LOG_VERSION)
|
||||
#else
|
||||
#define ESP_LOG_VERSION (CONFIG_LOG_VERSION)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This define controls the log configuration options, particularly when the built project operates in constrained environments.
|
||||
*
|
||||
* For the bootloader build:
|
||||
* It is always set to "1" because certain log features are unnecessary, reducing the binary size.
|
||||
*
|
||||
* For the application build:
|
||||
* If this define is set in the user namespace, all logs in the specific file will use a simplified path for logging.
|
||||
*
|
||||
* This define determines whether the "constrained_env" flag will be enabled in ESP_LOG_CONFIGS_DEFAULT, indicating that logging is capable of functioning
|
||||
* in constrained environments such as the bootloader, ISR, startup code, early log, or when the cache is disabled. In these cases,
|
||||
* `esp_log()` utilizes a simplified implementation to output logs.
|
||||
*/
|
||||
#if BOOTLOADER_BUILD
|
||||
#define ESP_LOG_CONSTRAINED_ENV (1)
|
||||
#else // !BOOTLOADER_BUILD
|
||||
#ifndef ESP_LOG_CONSTRAINED_ENV
|
||||
#define ESP_LOG_CONSTRAINED_ENV (0)
|
||||
#endif
|
||||
#endif // !BOOTLOADER_BUILD
|
||||
|
||||
/**
|
||||
* This define helps control log configuration options, specifically whether color output will be appended to log messages.
|
||||
* If this define is not set in the user namespace, its value will be determined by Kconfig options.
|
||||
* If the define is set in the user namespace, it will override the default configurations (ESP_LOG_CONFIGS_DEFAULT) for the user's specific file.
|
||||
* This define controls the "dis_color" flag, which is included in ESP_LOG_CONFIGS_DEFAULT
|
||||
*/
|
||||
#ifndef ESP_LOG_COLOR_DISABLED
|
||||
#if (!BOOTLOADER_BUILD && CONFIG_LOG_COLORS) || (BOOTLOADER_BUILD && CONFIG_BOOTLOADER_LOG_COLORS)
|
||||
#define ESP_LOG_COLOR_DISABLED (0)
|
||||
#else
|
||||
#define ESP_LOG_COLOR_DISABLED (1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This define helps control log configuration options, specifically whether timestamp will be appended to log message.
|
||||
* If this define is not set in the user namespace, its value will be determined by Kconfig options.
|
||||
* If the define is set in the user namespace, it will override the default configurations (ESP_LOG_CONFIGS_DEFAULT) for the user's specific file.
|
||||
* This define controls the "dis_timestamp" flag, which is included in ESP_LOG_CONFIGS_DEFAULT
|
||||
*/
|
||||
#ifndef ESP_LOG_TIMESTAMP_DISABLED
|
||||
#if (!BOOTLOADER_BUILD && CONFIG_LOG_TIMESTAMP_SOURCE_NONE) || (BOOTLOADER_BUILD && CONFIG_BOOTLOADER_LOG_TIMESTAMP_SOURCE_NONE)
|
||||
#define ESP_LOG_TIMESTAMP_DISABLED (1)
|
||||
#else
|
||||
#define ESP_LOG_TIMESTAMP_DISABLED (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This define helps control log configuration options, specifically whether formatting (ex.: color, timestamp) will be appended to log message.
|
||||
* If the define is set in the user namespace, it will override the default configurations (ESP_LOG_CONFIGS_DEFAULT) for the user's specific file.
|
||||
* This define controls the "require_formatting" flag, which is included in ESP_LOG_CONFIGS_DEFAULT
|
||||
*/
|
||||
#ifndef ESP_LOG_FORMATTING_DISABLED
|
||||
#define ESP_LOG_FORMATTING_DISABLED (0)
|
||||
#endif
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* @brief Logging configuration structure for ESP log.
|
||||
*/
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
esp_log_level_t log_level: ESP_LOG_LEVEL_LEN; /*!< Log level */
|
||||
uint32_t constrained_env: 1; /*!< Flag indicating if logging is from a constrained environment (e.g., bootloader, ISR, startup code, early log, or when the cache is disabled). In such cases, esp_rom_vprintf is used instead of the vprintf. */
|
||||
uint32_t require_formatting: 1; /*!< Flag specifying whether the log message needs additional formatting. If set, esp_log() will add formatting elements like color, timestamp, and tag to the log message. */
|
||||
uint32_t dis_color: 1; /*!< Flag to disable color in log output. If set, log messages will not include color codes. */
|
||||
uint32_t dis_timestamp: 1; /*!< Flag to disable timestamps in log output. If set, log messages will not include timestamps. */
|
||||
uint32_t reserved: 25; /*!< Reserved for future use. Should be initialized to 0. */
|
||||
} opts;
|
||||
uint32_t data; /*!< Raw data representing all options in a 32-bit word. */
|
||||
};
|
||||
} esp_log_config_t;
|
||||
|
||||
/** @cond */
|
||||
#define ESP_LOG_OFFSET_CONSTRAINED_ENV (ESP_LOG_LEVEL_LEN) /*!< Offset for constrained_env field from esp_log_config_t */
|
||||
#define ESP_LOG_OFFSET_REQUIRE_FORMATTING (4) /*!< Offset for require_formatting field from esp_log_config_t */
|
||||
#define ESP_LOG_OFFSET_DIS_COLOR_OFFSET (5) /*!< Offset for dis_color field from esp_log_config_t */
|
||||
#define ESP_LOG_OFFSET_DIS_TIMESTAMP (6) /*!< Offset for dis_timestamp field from esp_log_config_t */
|
||||
|
||||
ESP_STATIC_ASSERT(ESP_LOG_OFFSET_CONSTRAINED_ENV == ESP_LOG_LEVEL_LEN, "The log level should not overlap the following fields in esp_log_config_t");
|
||||
/** @endcond */
|
||||
|
||||
#define ESP_LOG_CONFIG_LEVEL_MASK ((1 << ESP_LOG_LEVEL_LEN) - 1) /*!< Mask for level field in esp_log_config_t */
|
||||
#define ESP_LOG_CONFIG_CONSTRAINED_ENV (1 << ESP_LOG_OFFSET_CONSTRAINED_ENV) /*!< Value for constrained_env field in esp_log_config_t */
|
||||
#define ESP_LOG_CONFIG_REQUIRE_FORMATTING (1 << ESP_LOG_OFFSET_REQUIRE_FORMATTING) /*!< Value for require_formatting field in esp_log_config_t */
|
||||
#define ESP_LOG_CONFIG_DIS_COLOR (1 << ESP_LOG_OFFSET_DIS_COLOR_OFFSET) /*!< Value for dis_color field in esp_log_config_t */
|
||||
#define ESP_LOG_CONFIG_DIS_TIMESTAMP (1 << ESP_LOG_OFFSET_DIS_TIMESTAMP) /*!< Value for dis_timestamp field in esp_log_config_t */
|
||||
|
||||
/**
|
||||
* @brief Macro for setting log configurations according to selected Kconfig options.
|
||||
*
|
||||
* @note The `require_formatting` flag is always set for logv2.
|
||||
*/
|
||||
#ifndef ESP_LOG_CONFIGS_DEFAULT
|
||||
#define ESP_LOG_CONFIGS_DEFAULT ( \
|
||||
((ESP_LOG_CONSTRAINED_ENV) ? (ESP_LOG_CONFIG_CONSTRAINED_ENV) : 0) \
|
||||
| ((ESP_LOG_FORMATTING_DISABLED) ? (0) : (ESP_LOG_CONFIG_REQUIRE_FORMATTING)) \
|
||||
| ((ESP_LOG_COLOR_DISABLED) ? (ESP_LOG_CONFIG_DIS_COLOR) : 0) \
|
||||
| ((ESP_LOG_TIMESTAMP_DISABLED) ? (ESP_LOG_CONFIG_DIS_TIMESTAMP) : 0))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Macro to initialize an `esp_log_config_t` structure.
|
||||
*
|
||||
* This macro directly initializes an `esp_log_config_t` structure by setting the raw `data` field
|
||||
* with the provided `configs` parameter. It is useful when you have already defined the configuration
|
||||
* settings and wish to apply them directly.
|
||||
*
|
||||
* @param configs The raw configuration data to initialize the `esp_log_config_t` structure.
|
||||
*
|
||||
* @return An initialized `esp_log_config_t` structure containing the specified configuration data.
|
||||
*/
|
||||
#if defined(__cplusplus)
|
||||
#define ESP_LOG_CONFIG_INIT(configs) (__extension__({ \
|
||||
esp_log_config_t __esp_log_config; \
|
||||
__esp_log_config.data = (configs); \
|
||||
__esp_log_config;}))
|
||||
#else
|
||||
#define ESP_LOG_CONFIG_INIT(configs) ((esp_log_config_t){.data = (configs)})
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -29,11 +29,25 @@ typedef enum {
|
||||
|
||||
#define ESP_LOG_LEVEL_LEN (3) /*!< Number of bits used to represent the log level */
|
||||
#define ESP_LOG_LEVEL_MASK ((1 << ESP_LOG_LEVEL_LEN) - 1) /*!< Mask for log level */
|
||||
/// Returns level from config
|
||||
#define ESP_LOG_GET_LEVEL(config) ((config) & ESP_LOG_LEVEL_MASK)
|
||||
|
||||
/** @cond */
|
||||
ESP_STATIC_ASSERT(ESP_LOG_MAX <= ESP_LOG_LEVEL_MASK, "Log level items of esp_log_level_t must fit ESP_LOG_LEVEL_MASK");
|
||||
|
||||
// LOG_LOCAL_LEVEL controls what log levels are included in the binary.
|
||||
/**
|
||||
* @brief Controls the log levels included in the binary.
|
||||
*
|
||||
* This define determines the maximum log level that will be compiled into the binary for the current build configuration.
|
||||
* It adjusts the verbosity of logging by specifying which log levels are included or excluded.
|
||||
*
|
||||
* If this define is not explicitly set in the user namespace, its value is derived from Kconfig options:
|
||||
* - `CONFIG_BOOTLOADER_LOG_LEVEL` for bootloader builds.
|
||||
* - `CONFIG_SECURE_TEE_LOG_LEVEL` for Secure TEE builds.
|
||||
* - `CONFIG_LOG_MAXIMUM_LEVEL` for all other builds.
|
||||
*
|
||||
* If explicitly defined in the user's code, it overrides these default values, allowing fine-grained control over log verbosity.
|
||||
*/
|
||||
#ifndef LOG_LOCAL_LEVEL
|
||||
#if BOOTLOADER_BUILD
|
||||
#define LOG_LOCAL_LEVEL CONFIG_BOOTLOADER_LOG_LEVEL
|
||||
@@ -43,6 +57,7 @@ ESP_STATIC_ASSERT(ESP_LOG_MAX <= ESP_LOG_LEVEL_MASK, "Log level items of esp_log
|
||||
#define LOG_LOCAL_LEVEL CONFIG_LOG_MAXIMUM_LEVEL
|
||||
#endif
|
||||
#endif // LOG_LOCAL_LEVEL
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* @brief Check if a specific log level is enabled at compile-time.
|
||||
@@ -52,27 +67,28 @@ ESP_STATIC_ASSERT(ESP_LOG_MAX <= ESP_LOG_LEVEL_MASK, "Log level items of esp_log
|
||||
* determine if logging for the specified level should be included in the binary,
|
||||
* helping to exclude logs that are not configured.
|
||||
*
|
||||
* @param level log level.
|
||||
* @param configs it includes log configs and level.
|
||||
* @return true if the specified log level is enabled, false otherwise.
|
||||
*/
|
||||
#define ESP_LOG_ENABLED(level) (LOG_LOCAL_LEVEL >= (level))
|
||||
#define ESP_LOG_ENABLED(configs) (LOG_LOCAL_LEVEL >= ESP_LOG_GET_LEVEL(configs))
|
||||
|
||||
/** @cond */
|
||||
#if NON_OS_BUILD
|
||||
|
||||
#define _ESP_LOG_ENABLED(log_level) (LOG_LOCAL_LEVEL >= (log_level))
|
||||
#define _ESP_LOG_EARLY_ENABLED(log_level) _ESP_LOG_ENABLED(log_level)
|
||||
#define _ESP_LOG_ENABLED(log_level) ESP_LOG_ENABLED(log_level)
|
||||
#define _ESP_LOG_EARLY_ENABLED(log_level) ESP_LOG_ENABLED(log_level)
|
||||
|
||||
#else // !NON_OS_BUILD
|
||||
|
||||
#if CONFIG_LOG_MASTER_LEVEL
|
||||
#define _ESP_LOG_ENABLED(log_level) (esp_log_get_level_master() >= (log_level) && LOG_LOCAL_LEVEL >= (log_level))
|
||||
#define _ESP_LOG_ENABLED(log_level) (esp_log_get_level_master() >= ESP_LOG_GET_LEVEL(log_level) && ESP_LOG_ENABLED(log_level))
|
||||
#else // !CONFIG_LOG_MASTER_LEVEL
|
||||
#define _ESP_LOG_ENABLED(log_level) (LOG_LOCAL_LEVEL >= (log_level))
|
||||
#define _ESP_LOG_ENABLED(log_level) ESP_LOG_ENABLED(log_level)
|
||||
#endif // !CONFIG_LOG_MASTER_LEVEL
|
||||
|
||||
/* For early log, there is no log tag filtering. So we want to log only if both the LOG_LOCAL_LEVEL and the
|
||||
currently configured min log level are higher than the log level */
|
||||
#define _ESP_LOG_EARLY_ENABLED(log_level) (LOG_LOCAL_LEVEL >= (log_level) && esp_log_get_default_level() >= (log_level))
|
||||
#define _ESP_LOG_EARLY_ENABLED(log_level) (ESP_LOG_ENABLED(log_level) && esp_log_get_default_level() >= ESP_LOG_GET_LEVEL(log_level))
|
||||
|
||||
#endif // !NON_OS_BUILD
|
||||
|
||||
@@ -91,7 +107,11 @@ currently configured min log level are higher than the log level */
|
||||
__attribute__((always_inline))
|
||||
static inline esp_log_level_t esp_log_get_default_level(void)
|
||||
{
|
||||
#if CONFIG_LOG_DYNAMIC_LEVEL_CONTROL
|
||||
#if BOOTLOADER_BUILD
|
||||
return (esp_log_level_t) CONFIG_BOOTLOADER_LOG_LEVEL;
|
||||
#elif ESP_TEE_BUILD
|
||||
return (esp_log_level_t) CONFIG_SECURE_TEE_LOG_LEVEL;
|
||||
#elif CONFIG_LOG_DYNAMIC_LEVEL_CONTROL
|
||||
extern esp_log_level_t esp_log_default_level;
|
||||
return esp_log_default_level;
|
||||
#else
|
||||
@@ -104,14 +124,13 @@ static inline esp_log_level_t esp_log_get_default_level(void)
|
||||
/**
|
||||
* @brief Master log level.
|
||||
*
|
||||
* Optional master log level to check against for ESP_LOGx macros before calling
|
||||
* esp_log_write. Allows one to set a higher CONFIG_LOG_MAXIMUM_LEVEL but not
|
||||
* Allows one to set a higher CONFIG_LOG_MAXIMUM_LEVEL but not
|
||||
* impose a performance hit during normal operation (only when instructed). An
|
||||
* application may set esp_log_set_level_master(level) to globally enforce a
|
||||
* maximum log level. ESP_LOGx macros above this level will be skipped immediately,
|
||||
* rather than calling esp_log or esp_log_write and doing a cache hit.
|
||||
* maximum log level. ESP_LOG macros above this level will be skipped,
|
||||
* rather than doing a tag lookup.
|
||||
*
|
||||
* @note The tradeoff is increased application size.
|
||||
* The Master log level is not applicable for the bootloader.
|
||||
*
|
||||
* @param level Master log level
|
||||
*/
|
||||
@@ -119,6 +138,7 @@ void esp_log_set_level_master(esp_log_level_t level);
|
||||
|
||||
/**
|
||||
* @brief Returns master log level.
|
||||
* The Master log level is not applicable for the bootloader.
|
||||
* @return Master log level
|
||||
*/
|
||||
esp_log_level_t esp_log_get_level_master(void);
|
||||
|
||||
@@ -12,6 +12,16 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Checks if a log message with the given log level and tag should be logged.
|
||||
*
|
||||
* @param level The log level of the message.
|
||||
* @param tag The tag associated with the message.
|
||||
* @return true if the log message can be logged,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool esp_log_is_tag_loggable(esp_log_level_t level, const char *tag);
|
||||
|
||||
/**
|
||||
* @brief Set the default log level.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include "esp_log_config.h"
|
||||
#include "esp_log_write.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Outputs a formatted log message.
|
||||
*
|
||||
* @note It internally calls a vprintf function that was set by esp_log_set_vprintf().
|
||||
* @see esp_log_set_vprintf
|
||||
*
|
||||
* @param config The config log
|
||||
* @param format The format string for the log message.
|
||||
* @param args The variable argument list containing the values to be formatted.
|
||||
*/
|
||||
__attribute__((always_inline)) static inline void esp_log_vprintf(esp_log_config_t config, const char *format, va_list args)
|
||||
{
|
||||
#if BOOTLOADER_BUILD
|
||||
esp_rom_vprintf(format, args);
|
||||
#else // APP
|
||||
extern vprintf_like_t esp_log_vprint_func;
|
||||
#if ESP_LOG_VERSION == 2
|
||||
vprintf_like_t vprint_func[2] = {
|
||||
esp_log_vprint_func,
|
||||
esp_rom_vprintf,
|
||||
};
|
||||
vprint_func[config.opts.constrained_env](format, args);
|
||||
#else // ESP_LOG_VERSION == 1
|
||||
esp_log_vprint_func(format, args);
|
||||
#endif // ESP_LOG_VERSION == 1
|
||||
#endif // APP
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Outputs a formatted log message.
|
||||
*
|
||||
* @note It internally calls esp_log_vprintf().
|
||||
* @see esp_log_vprintf
|
||||
*
|
||||
* @param config The config log
|
||||
* @param format The format string for the log message.
|
||||
* @param ... Optional arguments to be formatted according to the format string.
|
||||
*/
|
||||
void esp_log_printf(esp_log_config_t config, const char *format, ...) __attribute__((format(printf, 2, 3)));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -64,6 +66,45 @@ int esp_log_util_cvt_hex(unsigned long long val, int pad, char *buf);
|
||||
*/
|
||||
int esp_log_util_cvt_dec(unsigned long long val, int pad, char *buf);
|
||||
|
||||
/**
|
||||
* @typedef esp_log_cache_enabled_t
|
||||
* @brief Callback function type for checking the state of the SPI flash cache.
|
||||
*
|
||||
* This function pointer is used to determine whether the SPI flash cache is enabled
|
||||
* during logging operations.
|
||||
*
|
||||
* @return
|
||||
* - true if the SPI flash cache is enabled.
|
||||
* - false if the SPI flash cache is disabled.
|
||||
*/
|
||||
typedef bool (*esp_log_cache_enabled_t)(void);
|
||||
|
||||
/**
|
||||
* @brief Sets the callback function to check the SPI flash cache state.
|
||||
*
|
||||
* This function allows setting a custom callback to check whether the SPI flash
|
||||
* cache is enabled. If a callback is provided, it will be used during logging
|
||||
* operations to ensure that logging does not interfere with cache-disabled scenarios.
|
||||
*
|
||||
* @note This function must be called during system startup to initialize it.
|
||||
*
|
||||
* @param[in] func Pointer to the callback function of type `esp_log_cache_enabled_t`.
|
||||
* Pass `NULL` to disable the cache check.
|
||||
*/
|
||||
void esp_log_util_set_cache_enabled_cb(esp_log_cache_enabled_t func);
|
||||
|
||||
/**
|
||||
* @brief Check if the current context is constrained.
|
||||
*
|
||||
* This function checks if logging in the current context is doing from:
|
||||
* - ISR context.
|
||||
* - Disabled SPI flash cache.
|
||||
* - Task scheduler not running.
|
||||
*
|
||||
* @return true if the context is constrained, false otherwise.
|
||||
*/
|
||||
bool esp_log_util_is_constrained(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -7,3 +7,9 @@ entries:
|
||||
log_timestamp:esp_log_timestamp (noflash)
|
||||
log_timestamp:esp_log_early_timestamp (noflash)
|
||||
log_lock (noflash)
|
||||
util (noflash)
|
||||
log_timestamp_common (noflash)
|
||||
log_print (noflash)
|
||||
log (noflash)
|
||||
if LOG_MASTER_LEVEL = y:
|
||||
log_level: esp_log_get_level_master (noflash)
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool esp_log_util_is_constrained(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include "esp_log_config.h"
|
||||
#include "esp_log_level.h"
|
||||
#include "esp_log_color.h"
|
||||
#include "esp_log_timestamp.h"
|
||||
#include "esp_private/log_level.h"
|
||||
#include "esp_private/log_timestamp.h"
|
||||
#include "esp_private/log_lock.h"
|
||||
#include "esp_private/log_util.h"
|
||||
#include "esp_private/log_print.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
static __attribute__((unused)) const char s_lvl_name[ESP_LOG_MAX] = {
|
||||
'\0', // NONE
|
||||
'E', // ERROR
|
||||
'W', // WARNING
|
||||
'I', // INFO
|
||||
'D', // DEBUG
|
||||
'V', // VERBOSE
|
||||
};
|
||||
|
||||
static __attribute__((unused)) const char s_lvl_color[ESP_LOG_MAX][8] = {
|
||||
"\0", // NONE
|
||||
LOG_ANSI_COLOR_REGULAR(LOG_ANSI_COLOR_RED)"\0", // ERROR
|
||||
LOG_ANSI_COLOR_REGULAR(LOG_ANSI_COLOR_YELLOW)"\0", // WARNING
|
||||
LOG_ANSI_COLOR_REGULAR(LOG_ANSI_COLOR_GREEN)"\0", // INFO
|
||||
"\0", // DEBUG
|
||||
"\0", // VERBOSE
|
||||
};
|
||||
|
||||
static __attribute__((unused)) bool is_level_loggable(esp_log_config_t config)
|
||||
{
|
||||
#if BOOTLOADER_BUILD
|
||||
return (config.opts.log_level != ESP_LOG_NONE) && (esp_log_get_default_level() >= config.opts.log_level);
|
||||
#else
|
||||
return (config.opts.log_level != ESP_LOG_NONE)
|
||||
#if CONFIG_LOG_MASTER_LEVEL
|
||||
&& (esp_log_get_level_master() >= config.opts.log_level)
|
||||
#endif // CONFIG_LOG_MASTER_LEVEL
|
||||
&& ((config.opts.constrained_env) ? (esp_log_get_default_level() >= config.opts.log_level) : true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void __attribute__((optimize("-O3"))) esp_log_va(esp_log_config_t config, const char *tag, const char *format, va_list args)
|
||||
{
|
||||
#if ESP_LOG_VERSION == 1
|
||||
if (config.opts.log_level != ESP_LOG_NONE && esp_log_is_tag_loggable(config.opts.log_level, tag)) {
|
||||
extern vprintf_like_t esp_log_vprint_func;
|
||||
esp_log_vprint_func(format, args);
|
||||
}
|
||||
#else // ESP_LOG_VERSION == 2
|
||||
if (is_level_loggable(config)) {
|
||||
__attribute__((unused)) uint64_t timestamp = 0;
|
||||
config.opts.dis_timestamp |= !ESP_LOG_SUPPORT_TIMESTAMP;
|
||||
config.opts.constrained_env = ESP_LOG_CONSTRAINED_ENV || config.opts.constrained_env || esp_log_util_is_constrained();
|
||||
if (!config.opts.dis_timestamp && ((!ESP_LOG_CONSTRAINED_ENV && config.opts.require_formatting) || ESP_LOG_CONSTRAINED_ENV)) {
|
||||
timestamp = esp_log_timestamp64(config.opts.constrained_env);
|
||||
}
|
||||
#if !ESP_LOG_CONSTRAINED_ENV
|
||||
if (!config.opts.constrained_env && tag != NULL && !esp_log_is_tag_loggable(config.opts.log_level, tag)) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// formatting log
|
||||
if (config.opts.require_formatting) { // 1. print "<color_start><level_name> <(time)> <tag>: "
|
||||
#if !ESP_LOG_CONSTRAINED_ENV
|
||||
if (!config.opts.constrained_env) {
|
||||
// flockfile&funlockfile are used here to prevent other threads
|
||||
// from writing to the same stream simultaneously using printf-like functions.
|
||||
// Below is formatting log, there are multiple calls to vprintf to log a single message.
|
||||
flockfile(stdout);
|
||||
}
|
||||
#endif
|
||||
config.opts.dis_color = !ESP_LOG_SUPPORT_COLOR || config.opts.dis_color || (s_lvl_color[config.opts.log_level][0] == '\0');
|
||||
char timestamp_buffer[32] = { 0 };
|
||||
if (!config.opts.dis_timestamp) {
|
||||
esp_log_timestamp_str(config.opts.constrained_env, timestamp, timestamp_buffer);
|
||||
}
|
||||
esp_log_printf(config, "%s%c %s%s%s%s%s",
|
||||
(!config.opts.dis_color) ? s_lvl_color[config.opts.log_level] : "",
|
||||
s_lvl_name[config.opts.log_level],
|
||||
(!config.opts.dis_timestamp) ? "(" : "",
|
||||
timestamp_buffer,
|
||||
(!config.opts.dis_timestamp) ? ") " : "",
|
||||
(tag) ? tag : "",
|
||||
(tag) ? ": " : "");
|
||||
}
|
||||
|
||||
esp_log_vprintf(config, format, args); // 2. print user message
|
||||
|
||||
if (config.opts.require_formatting) { // 3. print "<color_end><\n>"
|
||||
esp_log_printf(config, "%s", (config.opts.dis_color) ? "\n" : LOG_RESET_COLOR"\n");
|
||||
#if !ESP_LOG_CONSTRAINED_ENV
|
||||
if (!config.opts.constrained_env) {
|
||||
funlockfile(stdout);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif // ESP_LOG_VERSION == 2
|
||||
}
|
||||
|
||||
void __attribute__((optimize("-O3"))) esp_log(esp_log_config_t config, const char* tag, const char* format, ...)
|
||||
{
|
||||
#if ESP_LOG_VERSION == 1
|
||||
if (1) {
|
||||
#else // ESP_LOG_VERSION == 2
|
||||
if (is_level_loggable(config)) {
|
||||
#endif
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
esp_log_va(config, tag, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include "esp_log_level.h"
|
||||
#include "esp_private/log_level.h"
|
||||
#include "esp_attr.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
@@ -38,3 +38,18 @@ void esp_log_set_level_master(esp_log_level_t level)
|
||||
s_master_log_level = level;
|
||||
}
|
||||
#endif // CONFIG_LOG_MASTER_LEVEL
|
||||
|
||||
bool esp_log_is_tag_loggable(esp_log_level_t level, const char *tag)
|
||||
{
|
||||
#if CONFIG_LOG_TAG_LEVEL_IMPL_NONE
|
||||
(void)tag;
|
||||
#if CONFIG_LOG_DYNAMIC_LEVEL_CONTROL
|
||||
return (esp_log_default_level >= level);
|
||||
#else
|
||||
(void)level;
|
||||
return true;
|
||||
#endif
|
||||
#else // !CONFIG_LOG_TAG_LEVEL_IMPL_NONE
|
||||
return esp_log_level_get_timeout(tag) >= level && level > ESP_LOG_NONE;
|
||||
#endif // !CONFIG_LOG_TAG_LEVEL_IMPL_NONE
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include "esp_private/log_print.h"
|
||||
#include "esp_log_config.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
void esp_log_printf(esp_log_config_t config, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
esp_log_vprintf(config, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool esp_log_util_is_constrained(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -10,18 +10,19 @@
|
||||
#include <stdio.h>
|
||||
#include "esp_log_write.h"
|
||||
#include "esp_private/log_lock.h"
|
||||
#include "esp_private/log_level.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log_level.h"
|
||||
#include "esp_log_config.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static vprintf_like_t s_log_print_func = &vprintf;
|
||||
vprintf_like_t esp_log_vprint_func = &vprintf;
|
||||
|
||||
vprintf_like_t esp_log_set_vprintf(vprintf_like_t func)
|
||||
{
|
||||
esp_log_impl_lock();
|
||||
vprintf_like_t orig_func = s_log_print_func;
|
||||
s_log_print_func = func;
|
||||
esp_log_impl_unlock();
|
||||
return orig_func;
|
||||
/* This builtin, as described by Intel, is not a traditional
|
||||
* test-and-set operation, but rather an atomic exchange operation. It
|
||||
* writes value into *ptr, and returns the previous contents of *ptr.
|
||||
*/
|
||||
return __atomic_exchange_n(&esp_log_vprint_func, func, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
void esp_log_writev(esp_log_level_t level,
|
||||
@@ -29,10 +30,7 @@ void esp_log_writev(esp_log_level_t level,
|
||||
const char *format,
|
||||
va_list args)
|
||||
{
|
||||
esp_log_level_t level_for_tag = esp_log_level_get_timeout(tag);
|
||||
if (ESP_LOG_NONE != level_for_tag && level <= level_for_tag) {
|
||||
(*s_log_print_func)(format, args);
|
||||
}
|
||||
esp_log_va(ESP_LOG_CONFIG_INIT(level), tag, format, args);
|
||||
}
|
||||
|
||||
void esp_log_write(esp_log_level_t level,
|
||||
@@ -41,6 +39,6 @@ void esp_log_write(esp_log_level_t level,
|
||||
{
|
||||
va_list list;
|
||||
va_start(list, format);
|
||||
esp_log_writev(level, tag, format, list);
|
||||
esp_log_va(ESP_LOG_CONFIG_INIT(level), tag, format, list);
|
||||
va_end(list);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_private/log_util.h"
|
||||
#include "esp_compiler.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
static esp_log_cache_enabled_t esp_log_cache_enabled = NULL;
|
||||
|
||||
void esp_log_util_set_cache_enabled_cb(esp_log_cache_enabled_t func)
|
||||
{
|
||||
esp_log_cache_enabled = func;
|
||||
}
|
||||
|
||||
bool esp_log_util_is_constrained(void)
|
||||
{
|
||||
return (xPortInIsrContext()
|
||||
#if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
|
||||
|| ((esp_log_cache_enabled) ? !esp_log_cache_enabled() : false)
|
||||
#endif
|
||||
|| unlikely(xTaskGetSchedulerState() != taskSCHEDULER_RUNNING));
|
||||
}
|
||||
@@ -48,7 +48,12 @@ TEST_CASE("test master logging level performance", "[log]")
|
||||
|
||||
#ifdef CONFIG_LOG_MASTER_LEVEL
|
||||
esp_log_set_level_master(ESP_LOG_NONE);
|
||||
TEST_ASSERT_INT_WITHIN(100, 150, calc_time_of_logging(ITERATIONS));
|
||||
#if ESP_LOG_VERSION == 1
|
||||
const int typical_value = 150;
|
||||
#else // ESP_LOG_VERSION == 2
|
||||
const int typical_value = 250;
|
||||
#endif // ESP_LOG_VERSION == 2
|
||||
TEST_ASSERT_INT_WITHIN(100, typical_value, calc_time_of_logging(ITERATIONS));
|
||||
#else
|
||||
esp_log_level_set("*", ESP_LOG_NONE);
|
||||
TEST_ASSERT_INT_WITHIN(DELTA_US, EXPECTED_US, calc_time_of_logging(ITERATIONS) / ITERATIONS);
|
||||
|
||||
@@ -55,8 +55,7 @@ void putc_to_buffer(char c)
|
||||
|
||||
static int print_to_buffer(const char *format, va_list args)
|
||||
{
|
||||
int ret = vsnprintf(s_print_buffer, BUFFER_SIZE, format, args);
|
||||
printf(s_print_buffer);
|
||||
int ret = vsnprintf(&s_print_buffer[s_counter], BUFFER_SIZE, format, args);
|
||||
s_counter += ret;
|
||||
assert(s_counter < BUFFER_SIZE);
|
||||
return ret;
|
||||
|
||||
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <inttypes.h>
|
||||
#include "sys/param.h"
|
||||
#include "unity.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_rom_uart.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
typedef struct {
|
||||
SemaphoreHandle_t done;
|
||||
int stack_usage;
|
||||
int (*func)(void);
|
||||
} perf_log_test_t;
|
||||
|
||||
static const char * TAG = "test";
|
||||
|
||||
const int max_loops = 5;
|
||||
|
||||
static void print_via_vprintf(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vprintf(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void print_via_esp_rom_vprintf(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
esp_rom_vprintf(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static int test_stack_usage_esp_rom_printf(void)
|
||||
{
|
||||
UBaseType_t start, end;
|
||||
start = uxTaskGetStackHighWaterMark(NULL);
|
||||
esp_rom_printf("test msg with value %d\n", 1);
|
||||
end = uxTaskGetStackHighWaterMark(NULL);
|
||||
return start - end;
|
||||
}
|
||||
|
||||
static int test_stack_usage_esp_rom_vprintf(void)
|
||||
{
|
||||
UBaseType_t start, end;
|
||||
start = uxTaskGetStackHighWaterMark(NULL);
|
||||
print_via_esp_rom_vprintf("test msg with value %d\n", 2);
|
||||
end = uxTaskGetStackHighWaterMark(NULL);
|
||||
return start - end;
|
||||
}
|
||||
|
||||
static int test_stack_usage_early_log(void)
|
||||
{
|
||||
UBaseType_t start, end;
|
||||
start = uxTaskGetStackHighWaterMark(NULL);
|
||||
ESP_EARLY_LOGI(TAG, "test msg with value %d", 3);
|
||||
end = uxTaskGetStackHighWaterMark(NULL);
|
||||
return start - end;
|
||||
}
|
||||
|
||||
static int test_stack_usage_dram_log(void)
|
||||
{
|
||||
UBaseType_t start, end;
|
||||
start = uxTaskGetStackHighWaterMark(NULL);
|
||||
ESP_DRAM_LOGI(TAG, "test msg with value %d", 4);
|
||||
end = uxTaskGetStackHighWaterMark(NULL);
|
||||
return start - end;
|
||||
}
|
||||
|
||||
static int test_stack_usage_printf(void)
|
||||
{
|
||||
UBaseType_t start, end;
|
||||
start = uxTaskGetStackHighWaterMark(NULL);
|
||||
printf("test msg with value %d\n", 5);
|
||||
end = uxTaskGetStackHighWaterMark(NULL);
|
||||
return start - end;
|
||||
}
|
||||
|
||||
static int test_stack_usage_vprintf(void)
|
||||
{
|
||||
UBaseType_t start, end;
|
||||
start = uxTaskGetStackHighWaterMark(NULL);
|
||||
print_via_vprintf("test msg with value %d\n", 6);
|
||||
end = uxTaskGetStackHighWaterMark(NULL);
|
||||
return start - end;
|
||||
}
|
||||
|
||||
static int test_stack_usage_esp_log(void)
|
||||
{
|
||||
UBaseType_t start, end;
|
||||
start = uxTaskGetStackHighWaterMark(NULL);
|
||||
ESP_LOGI(TAG, "test msg with value %d", 7);
|
||||
end = uxTaskGetStackHighWaterMark(NULL);
|
||||
return start - end;
|
||||
}
|
||||
|
||||
static void log_stack_usage_task(void* arg)
|
||||
{
|
||||
perf_log_test_t *a = (perf_log_test_t *) arg;
|
||||
|
||||
const uint32_t mask = esp_cpu_intr_get_enabled_mask();
|
||||
esp_cpu_intr_disable(0xFFFFFFFF);
|
||||
a->stack_usage = a->func();
|
||||
esp_cpu_intr_enable(mask);
|
||||
|
||||
TEST_ASSERT(xSemaphoreGive(a->done));
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("Stack usage for log APIs", "[log]")
|
||||
{
|
||||
int priority = uxTaskPriorityGet(NULL) + 1;
|
||||
perf_log_test_t args = {
|
||||
.done = xSemaphoreCreateBinary(),
|
||||
.stack_usage = 0,
|
||||
.func = NULL,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
int (*func)(void);
|
||||
int stack_usages;
|
||||
} log_test_case_t;
|
||||
|
||||
log_test_case_t test_cases[] = {
|
||||
{"esp_rom_printf", test_stack_usage_esp_rom_printf, 0},
|
||||
{"esp_rom_vprintf", test_stack_usage_esp_rom_vprintf, 0},
|
||||
{"early_log", test_stack_usage_early_log, 0},
|
||||
{"dram_log", test_stack_usage_dram_log, 0},
|
||||
{"printf", test_stack_usage_printf, 0},
|
||||
{"vprintf", test_stack_usage_vprintf, 0},
|
||||
{"esp_log", test_stack_usage_esp_log, 0},
|
||||
};
|
||||
|
||||
for (int i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) {
|
||||
args.func = test_cases[i].func;
|
||||
TEST_ASSERT(xTaskCreatePinnedToCore(log_stack_usage_task, test_cases[i].name, 4095, &args, priority, NULL, 0));
|
||||
TEST_ASSERT(xSemaphoreTake(args.done, 100 / portTICK_PERIOD_MS));
|
||||
test_cases[i].stack_usages = args.stack_usage;
|
||||
}
|
||||
|
||||
printf("\nStack usage for %s chip:\n", CONFIG_IDF_TARGET);
|
||||
for (int i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) {
|
||||
printf("%-20s %d bytes\n", test_cases[i].name, test_cases[i].stack_usages);
|
||||
}
|
||||
|
||||
vSemaphoreDelete(args.done);
|
||||
}
|
||||
|
||||
static void mock_putc(char c)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static int mock_vprintf(const char *format, va_list args)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int measuring_execution_time_esp_rom_printf(bool without_output)
|
||||
{
|
||||
int diff;
|
||||
int64_t start, end;
|
||||
diff = INT32_MAX;
|
||||
for (int i = 0; i < max_loops; i++) {
|
||||
start = esp_timer_get_time();
|
||||
if (without_output) {
|
||||
esp_rom_printf("\r");
|
||||
} else {
|
||||
esp_rom_printf("test msg %d\n", i);
|
||||
}
|
||||
end = esp_timer_get_time();
|
||||
diff = MIN(diff, end - start);
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
static int measuring_execution_time_esp_rom_vprintf(bool without_output)
|
||||
{
|
||||
int diff;
|
||||
int64_t start, end;
|
||||
diff = INT32_MAX;
|
||||
for (int i = 0; i < max_loops; i++) {
|
||||
start = esp_timer_get_time();
|
||||
if (without_output) {
|
||||
print_via_esp_rom_vprintf("\r");
|
||||
} else {
|
||||
print_via_esp_rom_vprintf("test msg %d\n", i);
|
||||
}
|
||||
end = esp_timer_get_time();
|
||||
diff = MIN(diff, end - start);
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
static int measuring_execution_time_early_log(bool without_output)
|
||||
{
|
||||
int diff;
|
||||
int64_t start, end;
|
||||
diff = INT32_MAX;
|
||||
if (without_output) {
|
||||
esp_rom_install_channel_putc(1, mock_putc);
|
||||
}
|
||||
for (int i = 0; i < max_loops; i++) {
|
||||
start = esp_timer_get_time();
|
||||
if (without_output) {
|
||||
ESP_EARLY_LOGI(TAG, "");
|
||||
} else {
|
||||
ESP_EARLY_LOGI(TAG, "test msg %d", i);
|
||||
}
|
||||
end = esp_timer_get_time();
|
||||
diff = MIN(diff, end - start);
|
||||
}
|
||||
if (without_output) {
|
||||
esp_rom_install_channel_putc(1, esp_rom_output_putc);
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
static int measuring_execution_time_dram_log(bool without_output)
|
||||
{
|
||||
int diff;
|
||||
int64_t start, end;
|
||||
diff = INT32_MAX;
|
||||
if (without_output) {
|
||||
esp_rom_install_channel_putc(1, mock_putc);
|
||||
}
|
||||
for (int i = 0; i < max_loops; i++) {
|
||||
start = esp_timer_get_time();
|
||||
if (without_output) {
|
||||
ESP_DRAM_LOGI(TAG, "");
|
||||
} else {
|
||||
ESP_DRAM_LOGI(TAG, "test msg %d", i);
|
||||
}
|
||||
end = esp_timer_get_time();
|
||||
diff = MIN(diff, end - start);
|
||||
}
|
||||
if (without_output) {
|
||||
esp_rom_install_channel_putc(1, esp_rom_output_putc);
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
static int measuring_execution_time_printf(bool without_output)
|
||||
{
|
||||
int diff;
|
||||
int64_t start, end;
|
||||
diff = INT32_MAX;
|
||||
for (int i = 0; i < max_loops; i++) {
|
||||
start = esp_timer_get_time();
|
||||
if (without_output) {
|
||||
printf("\r");
|
||||
} else {
|
||||
printf("test msg %d\n", i);
|
||||
}
|
||||
end = esp_timer_get_time();
|
||||
diff = MIN(diff, end - start);
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
static int measuring_execution_time_vprintf(bool without_output)
|
||||
{
|
||||
int diff;
|
||||
int64_t start, end;
|
||||
diff = INT32_MAX;
|
||||
for (int i = 0; i < max_loops; i++) {
|
||||
start = esp_timer_get_time();
|
||||
if (without_output) {
|
||||
print_via_vprintf("\r");
|
||||
} else {
|
||||
print_via_vprintf("test msg %d\n", i);
|
||||
}
|
||||
end = esp_timer_get_time();
|
||||
diff = MIN(diff, end - start);
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
static int measuring_execution_time_esp_log_macro(bool without_output)
|
||||
{
|
||||
int diff;
|
||||
int64_t start, end;
|
||||
diff = INT32_MAX;
|
||||
vprintf_like_t original_vprintf;
|
||||
if (without_output) {
|
||||
original_vprintf = esp_log_set_vprintf(mock_vprintf);
|
||||
}
|
||||
for (int i = 0; i < max_loops; i++) {
|
||||
start = esp_timer_get_time();
|
||||
if (without_output) {
|
||||
ESP_LOGI(TAG, "\r");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "test msg %d", i);
|
||||
}
|
||||
end = esp_timer_get_time();
|
||||
diff = MIN(diff, end - start);
|
||||
}
|
||||
if (without_output) {
|
||||
esp_log_set_vprintf(original_vprintf);
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
TEST_CASE("Performance measurement for log APIs", "[log]")
|
||||
{
|
||||
#if ESP_LOG_VERSION == 2
|
||||
const int count_prints = 3;
|
||||
#else
|
||||
const int count_prints = 1;
|
||||
#endif
|
||||
|
||||
const uint32_t mask = esp_cpu_intr_get_enabled_mask();
|
||||
esp_cpu_intr_disable(0xFFFFFFFF);
|
||||
|
||||
int m_esp_rom_printf = measuring_execution_time_esp_rom_printf(true);
|
||||
int m_esp_rom_printf_output = measuring_execution_time_esp_rom_printf(false);
|
||||
|
||||
int m_esp_rom_vprintf = measuring_execution_time_esp_rom_vprintf(true);
|
||||
int m_esp_rom_vprintf_output = measuring_execution_time_esp_rom_vprintf(false);
|
||||
|
||||
int m_early_log = measuring_execution_time_early_log(true);
|
||||
int m_early_log_output = measuring_execution_time_early_log(false);
|
||||
|
||||
int m_dram_log_printf = measuring_execution_time_dram_log(true);
|
||||
int m_dram_log_printf_output = measuring_execution_time_dram_log(false);
|
||||
|
||||
int m_printf = measuring_execution_time_printf(true);
|
||||
int m_printf_output = measuring_execution_time_printf(false);
|
||||
|
||||
int m_vprintf = measuring_execution_time_vprintf(true);
|
||||
int m_vprintf_output = measuring_execution_time_vprintf(false);
|
||||
|
||||
int m_esp_log_macro = measuring_execution_time_esp_log_macro(true);
|
||||
int m_esp_log_macro_output = measuring_execution_time_esp_log_macro(false);
|
||||
|
||||
esp_cpu_intr_enable(mask);
|
||||
|
||||
esp_rom_printf("\nPerformance measurements for %s chip:\n", CONFIG_IDF_TARGET);
|
||||
esp_rom_printf("Function w/o output (us) | w/ output (us)\n");
|
||||
esp_rom_printf("esp_rom_printf %d %d\n", m_esp_rom_printf, m_esp_rom_printf_output);
|
||||
esp_rom_printf("esp_rom_vprintf %d %d\n", m_esp_rom_vprintf, m_esp_rom_vprintf_output);
|
||||
esp_rom_printf("ESP_EARLY_LOGI %d + %d %d\n", m_early_log, count_prints * m_esp_rom_printf, m_early_log_output);
|
||||
esp_rom_printf("ESP_DRAM_LOGI %d + %d %d\n", m_dram_log_printf, count_prints * m_esp_rom_vprintf, m_dram_log_printf_output);
|
||||
esp_rom_printf("printf %d %d\n", m_printf, m_printf_output);
|
||||
esp_rom_printf("vprintf %d %d\n", m_vprintf, m_vprintf_output);
|
||||
esp_rom_printf("ESP_LOGI %d + %d %d\n", m_esp_log_macro, count_prints * m_vprintf, m_esp_log_macro_output);
|
||||
}
|
||||
Reference in New Issue
Block a user