forked from espressif/esp-idf
Merge branch 'feature/log_buffer' into 'master'
feat(log): Refactoring buffer log APIs Closes IDF-8092 See merge request espressif/esp-idf!29559
This commit is contained in:
@@ -1,22 +1,27 @@
|
|||||||
idf_build_get_property(target IDF_TARGET)
|
idf_build_get_property(target IDF_TARGET)
|
||||||
set(srcs "log.c" "log_buffers.c")
|
|
||||||
|
set(srcs "")
|
||||||
set(priv_requires "")
|
set(priv_requires "")
|
||||||
|
|
||||||
|
if(BOOTLOADER_BUILD)
|
||||||
|
list(APPEND srcs "log_noos.c")
|
||||||
|
else()
|
||||||
|
list(APPEND srcs "log.c")
|
||||||
|
|
||||||
if(${target} STREQUAL "linux")
|
if(${target} STREQUAL "linux")
|
||||||
list(APPEND srcs "log_linux.c")
|
list(APPEND srcs "log_linux.c")
|
||||||
else()
|
else()
|
||||||
|
list(APPEND srcs "log_freertos.c")
|
||||||
list(APPEND priv_requires soc hal esp_hw_support)
|
list(APPEND priv_requires soc hal esp_hw_support)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Buffer APIs call ESP_LOG_LEVEL -> esp_log_write, which can not used in bootloader.
|
||||||
|
list(APPEND srcs "src/buffer/log_buffers.c"
|
||||||
|
"src/util.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRCS ${srcs}
|
idf_component_register(SRCS ${srcs}
|
||||||
INCLUDE_DIRS "include"
|
INCLUDE_DIRS "include"
|
||||||
|
PRIV_INCLUDE_DIRS "include/esp_private"
|
||||||
LDFRAGMENTS linker.lf
|
LDFRAGMENTS linker.lf
|
||||||
PRIV_REQUIRES ${priv_requires})
|
PRIV_REQUIRES ${priv_requires})
|
||||||
|
|
||||||
if(NOT ${target} STREQUAL "linux")
|
|
||||||
# Ideally, FreeRTOS shouldn't be included into bootloader build, so the 2nd check should be unnecessary
|
|
||||||
if(freertos IN_LIST BUILD_COMPONENTS AND NOT BOOTLOADER_BUILD)
|
|
||||||
target_sources(${COMPONENT_TARGET} PRIVATE log_freertos.c)
|
|
||||||
else()
|
|
||||||
target_sources(${COMPONENT_TARGET} PRIVATE log_noos.c)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
#include <regex>
|
#include <regex>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
#include "esp_private/log_util.h"
|
||||||
|
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
@@ -24,6 +25,7 @@ public:
|
|||||||
BasicLogFixture(esp_log_level_t log_level = ESP_LOG_VERBOSE)
|
BasicLogFixture(esp_log_level_t log_level = ESP_LOG_VERBOSE)
|
||||||
{
|
{
|
||||||
std::memset(print_buffer, 0, BUFFER_SIZE);
|
std::memset(print_buffer, 0, BUFFER_SIZE);
|
||||||
|
buffer_idx = 0;
|
||||||
esp_log_level_set("*", log_level);
|
esp_log_level_set("*", log_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,11 +42,13 @@ public:
|
|||||||
void reset_buffer()
|
void reset_buffer()
|
||||||
{
|
{
|
||||||
std::memset(print_buffer, 0, BUFFER_SIZE);
|
std::memset(print_buffer, 0, BUFFER_SIZE);
|
||||||
|
buffer_idx = 0;
|
||||||
additional_reset();
|
additional_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
char print_buffer [BUFFER_SIZE];
|
char print_buffer [BUFFER_SIZE];
|
||||||
|
int buffer_idx;
|
||||||
|
|
||||||
virtual void additional_reset() { }
|
virtual void additional_reset() { }
|
||||||
};
|
};
|
||||||
@@ -75,7 +79,9 @@ private:
|
|||||||
|
|
||||||
int print_to_buffer(const char *format, va_list args)
|
int print_to_buffer(const char *format, va_list args)
|
||||||
{
|
{
|
||||||
int ret = vsnprintf(print_buffer, BUFFER_SIZE, format, args);
|
// Added support for multi-line log, for example ESP_LOG_BUFFER...
|
||||||
|
int ret = vsnprintf(&print_buffer[buffer_idx], BUFFER_SIZE, format, args);
|
||||||
|
buffer_idx += ret;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,6 +221,19 @@ TEST_CASE("log bytes > 127")
|
|||||||
CHECK(regex_search(fix.get_print_buffer_string(), buffer_regex));
|
CHECK(regex_search(fix.get_print_buffer_string(), buffer_regex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("log buffer char")
|
||||||
|
{
|
||||||
|
PrintFixture fix(ESP_LOG_INFO);
|
||||||
|
const char g[] = "The way to get started is to quit talking and begin doing. - Walt Disney";
|
||||||
|
const std::regex buffer_regex("I \\([0-9]*\\) test: The way to get s.*\n\
|
||||||
|
.*I \\([0-9]*\\) test: tarted is to qui.*\n\
|
||||||
|
.*I \\([0-9]*\\) test: t talking and be.*\n\
|
||||||
|
.*I \\([0-9]*\\) test: gin doing. - Wal.*\n\
|
||||||
|
.*I \\([0-9]*\\) test: t Disney", std::regex::ECMAScript);
|
||||||
|
ESP_LOG_BUFFER_CHAR(TEST_TAG, g, sizeof(g));
|
||||||
|
CHECK(regex_search(fix.get_print_buffer_string(), buffer_regex) == true);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("log buffer dump")
|
TEST_CASE("log buffer dump")
|
||||||
{
|
{
|
||||||
PrintFixture fix(ESP_LOG_INFO);
|
PrintFixture fix(ESP_LOG_INFO);
|
||||||
@@ -303,3 +322,51 @@ TEST_CASE("changing early log level")
|
|||||||
ESP_EARLY_LOGI(TEST_TAG, "must indeed be printed");
|
ESP_EARLY_LOGI(TEST_TAG, "must indeed be printed");
|
||||||
CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true);
|
CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("esp_log_util_cvt")
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
CHECK(esp_log_util_cvt_dec(123456, 0, buf) == 6);
|
||||||
|
CHECK(strcmp(buf, "123456") == 0);
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
CHECK(esp_log_util_cvt_dec(123456, 2, buf) == 6);
|
||||||
|
CHECK(strcmp(buf, "123456") == 0);
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
CHECK(esp_log_util_cvt_dec(123456, 8, buf) == 8);
|
||||||
|
CHECK(strcmp(buf, "00123456") == 0);
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
CHECK(esp_log_util_cvt_dec(1, 0, buf) == 1);
|
||||||
|
CHECK(strcmp(buf, "1") == 0);
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
CHECK(esp_log_util_cvt_dec(0, 0, buf) == 1);
|
||||||
|
CHECK(strcmp(buf, "0") == 0);
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
CHECK(esp_log_util_cvt_dec(0, 4, buf) == 4);
|
||||||
|
CHECK(strcmp(buf, "0000") == 0);
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
CHECK(esp_log_util_cvt_dec(1, 2, buf) == 2);
|
||||||
|
CHECK(strcmp(buf, "01") == 0);
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
CHECK(esp_log_util_cvt_hex(0x73f, -1, buf) == 3);
|
||||||
|
CHECK(strcmp(buf, "73f") == 0);
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
CHECK(esp_log_util_cvt_hex(0x73f, 2, buf) == 3);
|
||||||
|
CHECK(strcmp(buf, "73f") == 0);
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
CHECK(esp_log_util_cvt_hex(0x73f, 3, buf) == 3);
|
||||||
|
CHECK(strcmp(buf, "73f") == 0);
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
CHECK(esp_log_util_cvt_hex(0x73f, 4, buf) == 4);
|
||||||
|
CHECK(strcmp(buf, "073f") == 0);
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -12,24 +12,13 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "esp_rom_sys.h"
|
#include "esp_rom_sys.h"
|
||||||
|
#include "esp_log_level.h"
|
||||||
|
#include "esp_log_buffer.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Log level
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
ESP_LOG_NONE, /*!< No log output */
|
|
||||||
ESP_LOG_ERROR, /*!< Critical errors, software module can not recover on its own */
|
|
||||||
ESP_LOG_WARN, /*!< Error conditions from which recovery measures have been taken */
|
|
||||||
ESP_LOG_INFO, /*!< Information messages which describe normal flow of events */
|
|
||||||
ESP_LOG_DEBUG, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */
|
|
||||||
ESP_LOG_VERBOSE /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */
|
|
||||||
} esp_log_level_t;
|
|
||||||
|
|
||||||
typedef int (*vprintf_like_t)(const char *, va_list);
|
typedef int (*vprintf_like_t)(const char *, va_list);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -172,113 +161,6 @@ void esp_log_writev(esp_log_level_t level, const char* tag, const char* format,
|
|||||||
|
|
||||||
/** @cond */
|
/** @cond */
|
||||||
|
|
||||||
#include "esp_log_internal.h"
|
|
||||||
|
|
||||||
#ifndef LOG_LOCAL_LEVEL
|
|
||||||
#ifndef BOOTLOADER_BUILD
|
|
||||||
#define LOG_LOCAL_LEVEL CONFIG_LOG_MAXIMUM_LEVEL
|
|
||||||
#else
|
|
||||||
#define LOG_LOCAL_LEVEL CONFIG_BOOTLOADER_LOG_LEVEL
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** @endcond */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Log a buffer of hex bytes at specified level, separated into 16 bytes each line.
|
|
||||||
*
|
|
||||||
* @param tag description tag
|
|
||||||
* @param buffer Pointer to the buffer array
|
|
||||||
* @param buff_len length of buffer in bytes
|
|
||||||
* @param level level of the log
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define ESP_LOG_BUFFER_HEX_LEVEL( tag, buffer, buff_len, level ) \
|
|
||||||
do {\
|
|
||||||
if ( LOG_LOCAL_LEVEL >= (level) ) { \
|
|
||||||
esp_log_buffer_hex_internal( tag, buffer, buff_len, level ); \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Log a buffer of characters at specified level, separated into 16 bytes each line. Buffer should contain only printable characters.
|
|
||||||
*
|
|
||||||
* @param tag description tag
|
|
||||||
* @param buffer Pointer to the buffer array
|
|
||||||
* @param buff_len length of buffer in bytes
|
|
||||||
* @param level level of the log
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define ESP_LOG_BUFFER_CHAR_LEVEL( tag, buffer, buff_len, level ) \
|
|
||||||
do {\
|
|
||||||
if ( LOG_LOCAL_LEVEL >= (level) ) { \
|
|
||||||
esp_log_buffer_char_internal( tag, buffer, buff_len, level ); \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Dump a buffer to the log at specified level.
|
|
||||||
*
|
|
||||||
* The dump log shows just like the one below:
|
|
||||||
*
|
|
||||||
* W (195) log_example: 0x3ffb4280 45 53 50 33 32 20 69 73 20 67 72 65 61 74 2c 20 |ESP32 is great, |
|
|
||||||
* W (195) log_example: 0x3ffb4290 77 6f 72 6b 69 6e 67 20 61 6c 6f 6e 67 20 77 69 |working along wi|
|
|
||||||
* W (205) log_example: 0x3ffb42a0 74 68 20 74 68 65 20 49 44 46 2e 00 |th the IDF..|
|
|
||||||
*
|
|
||||||
* It is highly recommended to use terminals with over 102 text width.
|
|
||||||
*
|
|
||||||
* @param tag description tag
|
|
||||||
* @param buffer Pointer to the buffer array
|
|
||||||
* @param buff_len length of buffer in bytes
|
|
||||||
* @param level level of the log
|
|
||||||
*/
|
|
||||||
#define ESP_LOG_BUFFER_HEXDUMP( tag, buffer, buff_len, level ) \
|
|
||||||
do { \
|
|
||||||
if ( LOG_LOCAL_LEVEL >= (level) ) { \
|
|
||||||
esp_log_buffer_hexdump_internal( tag, buffer, buff_len, level); \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Log a buffer of hex bytes at Info level
|
|
||||||
*
|
|
||||||
* @param tag description tag
|
|
||||||
* @param buffer Pointer to the buffer array
|
|
||||||
* @param buff_len length of buffer in bytes
|
|
||||||
*
|
|
||||||
* @see ``esp_log_buffer_hex_level``
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define ESP_LOG_BUFFER_HEX(tag, buffer, buff_len) \
|
|
||||||
do { \
|
|
||||||
if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) { \
|
|
||||||
ESP_LOG_BUFFER_HEX_LEVEL( tag, buffer, buff_len, ESP_LOG_INFO ); \
|
|
||||||
}\
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Log a buffer of characters at Info level. Buffer should contain only printable characters.
|
|
||||||
*
|
|
||||||
* @param tag description tag
|
|
||||||
* @param buffer Pointer to the buffer array
|
|
||||||
* @param buff_len length of buffer in bytes
|
|
||||||
*
|
|
||||||
* @see ``esp_log_buffer_char_level``
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define ESP_LOG_BUFFER_CHAR(tag, buffer, buff_len) \
|
|
||||||
do { \
|
|
||||||
if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) { \
|
|
||||||
ESP_LOG_BUFFER_CHAR_LEVEL( tag, buffer, buff_len, ESP_LOG_INFO ); \
|
|
||||||
}\
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
/** @cond */
|
|
||||||
|
|
||||||
//to be back compatible
|
|
||||||
#define esp_log_buffer_hex ESP_LOG_BUFFER_HEX
|
|
||||||
#define esp_log_buffer_char ESP_LOG_BUFFER_CHAR
|
|
||||||
|
|
||||||
#if CONFIG_LOG_COLORS
|
#if CONFIG_LOG_COLORS
|
||||||
#define LOG_COLOR_BLACK "30"
|
#define LOG_COLOR_BLACK "30"
|
||||||
#define LOG_COLOR_RED "31"
|
#define LOG_COLOR_RED "31"
|
||||||
|
180
components/log/include/esp_log_buffer.h
Normal file
180
components/log/include/esp_log_buffer.h
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "esp_log_level.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !BOOTLOADER_BUILD || __DOXYGEN__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Logs a buffer of hexadecimal bytes at the specified log level.
|
||||||
|
*
|
||||||
|
* This function logs a buffer of hexadecimal bytes with 16 bytes per line. The
|
||||||
|
* log level determines the severity of the log message.
|
||||||
|
*
|
||||||
|
* @note This function does not check the log level against the ESP_LOCAL_LEVEL.
|
||||||
|
* The log level comparison should be done in esp_log.h.
|
||||||
|
*
|
||||||
|
* @param tag Description tag to identify the log.
|
||||||
|
* @param buffer Pointer to the buffer array containing the data to be logged.
|
||||||
|
* @param buff_len Length of the buffer in bytes.
|
||||||
|
* @param level Log level indicating the severity of the log message.
|
||||||
|
*/
|
||||||
|
void esp_log_buffer_hex_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t level);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function logs a buffer of characters with 16 characters per line.
|
||||||
|
* The buffer should contain only printable characters. The log level determines
|
||||||
|
* the severity of the log message.
|
||||||
|
*
|
||||||
|
* @note This function does not check the log level against the ESP_LOCAL_LEVEL.
|
||||||
|
* The log level comparison should be done in esp_log.h.
|
||||||
|
*
|
||||||
|
* @param tag Description tag to identify the log.
|
||||||
|
* @param buffer Pointer to the buffer array containing the data to be logged.
|
||||||
|
* @param buff_len Length of the buffer in bytes.
|
||||||
|
* @param level Log level indicating the severity of the log message.
|
||||||
|
*/
|
||||||
|
void esp_log_buffer_char_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t level);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function dumps a buffer to the log in a formatted hex dump style,
|
||||||
|
* displaying both the memory address and the corresponding hex and ASCII values
|
||||||
|
* of the bytes. The log level determines the severity of the log message.
|
||||||
|
*
|
||||||
|
* @note This function does not check the log level against the ESP_LOCAL_LEVEL.
|
||||||
|
* The log level comparison should be done in esp_log.h.
|
||||||
|
* @note It is recommended to use terminals with a width of at least 102
|
||||||
|
* characters to display the log dump properly.
|
||||||
|
*
|
||||||
|
* @param tag Description tag to identify the log.
|
||||||
|
* @param buffer Pointer to the buffer array containing the data to be logged.
|
||||||
|
* @param buff_len Length of the buffer in bytes.
|
||||||
|
* @param log_level Log level indicating the severity of the log message.
|
||||||
|
*/
|
||||||
|
void esp_log_buffer_hexdump_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t log_level);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Log a buffer of hex bytes at specified level, separated into 16 bytes each line.
|
||||||
|
*
|
||||||
|
* The hex log shows just like the one below:
|
||||||
|
*
|
||||||
|
* I (954) log_example: 54 68 65 20 77 61 79 20 74 6f 20 67 65 74 20 73
|
||||||
|
* I (962) log_example: 74 61 72 74 65 64 20 69 73 20 74 6f 20 71 75 69
|
||||||
|
* I (969) log_example: 74 20 74 61 6c 6b 69 6e 67 20 61 6e 64 20 62 65
|
||||||
|
* I (977) log_example: 67 69 6e 20 64 6f 69 6e 67 2e 20 2d 20 57 61 6c
|
||||||
|
* I (984) log_example: 74 20 44 69 73 6e 65 79 00
|
||||||
|
*
|
||||||
|
* @param tag Description tag to identify the log.
|
||||||
|
* @param buffer Pointer to the buffer array containing the data to be logged.
|
||||||
|
* @param buff_len Length of the buffer in bytes.
|
||||||
|
* @param level Log level
|
||||||
|
*/
|
||||||
|
#define ESP_LOG_BUFFER_HEX_LEVEL(tag, buffer, buff_len, level) \
|
||||||
|
do { if (LOG_LOCAL_LEVEL >= (level)) {esp_log_buffer_hex_internal(tag, buffer, buff_len, level);} } while(0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Log a buffer of characters at specified level, separated into 16 bytes each line. Buffer should contain only printable characters.
|
||||||
|
*
|
||||||
|
* The char log shows just like the one below:
|
||||||
|
*
|
||||||
|
* I (980) log_example: The way to get s
|
||||||
|
* I (985) log_example: tarted is to qui
|
||||||
|
* I (989) log_example: t talking and be
|
||||||
|
* I (994) log_example: gin doing. - Wal
|
||||||
|
* I (999) log_example: t Disney
|
||||||
|
*
|
||||||
|
* @param tag Description tag to identify the log.
|
||||||
|
* @param buffer Pointer to the buffer array containing the data to be logged.
|
||||||
|
* @param buff_len Length of the buffer in bytes.
|
||||||
|
* @param level Log level.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define ESP_LOG_BUFFER_CHAR_LEVEL(tag, buffer, buff_len, level) \
|
||||||
|
do { if (LOG_LOCAL_LEVEL >= (level)) {esp_log_buffer_char_internal(tag, buffer, buff_len, level);} } while(0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Dump a buffer to the log at specified level.
|
||||||
|
*
|
||||||
|
* The dump log shows just like the one below:
|
||||||
|
*
|
||||||
|
* I (1013) log_example: 0x3ffb5bc0 54 68 65 20 77 61 79 20 74 6f 20 67 65 74 20 73 |The way to get s|
|
||||||
|
* I (1024) log_example: 0x3ffb5bd0 74 61 72 74 65 64 20 69 73 20 74 6f 20 71 75 69 |tarted is to qui|
|
||||||
|
* I (1034) log_example: 0x3ffb5be0 74 20 74 61 6c 6b 69 6e 67 20 61 6e 64 20 62 65 |t talking and be|
|
||||||
|
* I (1044) log_example: 0x3ffb5bf0 67 69 6e 20 64 6f 69 6e 67 2e 20 2d 20 57 61 6c |gin doing. - Wal|
|
||||||
|
* I (1054) log_example: 0x3ffb5c00 74 20 44 69 73 6e 65 79 00 |t Disney.|
|
||||||
|
*
|
||||||
|
* @note It is highly recommended to use terminals with over 102 text width.
|
||||||
|
*
|
||||||
|
* @param tag Description tag to identify the log.
|
||||||
|
* @param buffer Pointer to the buffer array containing the data to be logged.
|
||||||
|
* @param buff_len Length of the buffer in bytes.
|
||||||
|
* @param level Log level.
|
||||||
|
*/
|
||||||
|
#define ESP_LOG_BUFFER_HEXDUMP(tag, buffer, buff_len, level) \
|
||||||
|
do { if (LOG_LOCAL_LEVEL >= (level)) {esp_log_buffer_hexdump_internal(tag, buffer, buff_len, level);} } while(0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Log a buffer of hex bytes at Info level
|
||||||
|
*
|
||||||
|
* @param tag Description tag to identify the log.
|
||||||
|
* @param buffer Pointer to the buffer array containing the data to be logged.
|
||||||
|
* @param buff_len Length of the buffer in bytes.
|
||||||
|
*
|
||||||
|
* @see ``ESP_LOG_BUFFER_HEX_LEVEL``
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define ESP_LOG_BUFFER_HEX(tag, buffer, buff_len) \
|
||||||
|
do { if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) {ESP_LOG_BUFFER_HEX_LEVEL(tag, buffer, buff_len, ESP_LOG_INFO);} } while(0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Log a buffer of characters at Info level. Buffer should contain only printable characters.
|
||||||
|
*
|
||||||
|
* @param tag Description tag to identify the log.
|
||||||
|
* @param buffer Pointer to the buffer array containing the data to be logged.
|
||||||
|
* @param buff_len Length of the buffer in bytes.
|
||||||
|
*
|
||||||
|
* @see ``ESP_LOG_BUFFER_CHAR_LEVEL``
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define ESP_LOG_BUFFER_CHAR(tag, buffer, buff_len) \
|
||||||
|
do { if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) {ESP_LOG_BUFFER_CHAR_LEVEL(tag, buffer, buff_len, ESP_LOG_INFO);} } while(0)
|
||||||
|
|
||||||
|
/** @cond */
|
||||||
|
/**
|
||||||
|
* @note For back compatible
|
||||||
|
* @deprecated This function is deprecated and will be removed in the future.
|
||||||
|
* Please use ESP_LOG_BUFFER_HEX
|
||||||
|
*/
|
||||||
|
// __attribute__((deprecated("Use 'ESP_LOG_BUFFER_HEX' instead")))
|
||||||
|
static inline void esp_log_buffer_hex(const char *tag, const void *buffer, uint16_t buff_len)
|
||||||
|
{
|
||||||
|
ESP_LOG_BUFFER_HEX(tag, buffer, buff_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @note For back compatible
|
||||||
|
* @deprecated This function is deprecated and will be removed in the future.
|
||||||
|
* Please use ESP_LOG_BUFFER_CHAR
|
||||||
|
*/
|
||||||
|
// __attribute__((deprecated("Use 'ESP_LOG_BUFFER_CHAR' instead")))
|
||||||
|
static inline void esp_log_buffer_char(const char *tag, const void *buffer, uint16_t buff_len)
|
||||||
|
{
|
||||||
|
ESP_LOG_BUFFER_CHAR(tag, buffer, buff_len);
|
||||||
|
}
|
||||||
|
/** @endcond */
|
||||||
|
|
||||||
|
#endif // !BOOTLOADER_BUILD || __DOXYGEN__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@@ -1,15 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __ESP_LOG_INTERNAL_H__
|
#pragma once
|
||||||
#define __ESP_LOG_INTERNAL_H__
|
#warning "esp_log_internal.h is deprecated, please migrate to esp_log_buffer.h"
|
||||||
|
#include "esp_log_buffer.h"
|
||||||
//these functions do not check level versus ESP_LOCAL_LEVEL, this should be done in esp_log.h
|
|
||||||
void esp_log_buffer_hex_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t level);
|
|
||||||
void esp_log_buffer_char_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t level);
|
|
||||||
void esp_log_buffer_hexdump_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t log_level);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
42
components/log/include/esp_log_level.h
Normal file
42
components/log/include/esp_log_level.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Log level
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
ESP_LOG_NONE = 0, /*!< No log output */
|
||||||
|
ESP_LOG_ERROR = 1, /*!< Critical errors, software module can not recover on its own */
|
||||||
|
ESP_LOG_WARN = 2, /*!< Error conditions from which recovery measures have been taken */
|
||||||
|
ESP_LOG_INFO = 3, /*!< Information messages which describe normal flow of events */
|
||||||
|
ESP_LOG_DEBUG = 4, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */
|
||||||
|
ESP_LOG_VERBOSE = 5, /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */
|
||||||
|
ESP_LOG_MAX = 6, /*!< Number of levels supported */
|
||||||
|
} esp_log_level_t;
|
||||||
|
|
||||||
|
/** @cond */
|
||||||
|
|
||||||
|
#ifndef LOG_LOCAL_LEVEL
|
||||||
|
#ifndef BOOTLOADER_BUILD
|
||||||
|
#define LOG_LOCAL_LEVEL CONFIG_LOG_MAXIMUM_LEVEL
|
||||||
|
#else
|
||||||
|
#define LOG_LOCAL_LEVEL CONFIG_BOOTLOADER_LOG_LEVEL
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @endcond */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
69
components/log/include/esp_private/log_util.h
Normal file
69
components/log/include/esp_private/log_util.h
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert an unsigned integer value to a string representation in the specified radix.
|
||||||
|
*
|
||||||
|
* This function converts the given unsigned integer value to a string representation in the specified radix.
|
||||||
|
* The resulting string is stored in the provided character buffer `buf`.
|
||||||
|
*
|
||||||
|
* @param[in] val The unsigned integer value to be converted.
|
||||||
|
* @param[in] radix The base of the numeral system to be used for the conversion.
|
||||||
|
* It determines the number of unique digits in the numeral system
|
||||||
|
* (e.g., 2 for binary, 10 for decimal, 16 for hexadecimal).
|
||||||
|
* @param[in] pad The optional padding width (0 - unused) for the resulting string. It adds zero-padding.
|
||||||
|
* (val=123, pad=6 -> result=000123).
|
||||||
|
* @param[in] digits Pointer to a character array representing the digits of the
|
||||||
|
* numeral system. The array must contain characters in the order of increasing
|
||||||
|
* values, corresponding to the digits of the radix. For example, "0123456789ABCDEF"
|
||||||
|
* or hexadecimal.
|
||||||
|
* @param[out] buf Pointer to the character buffer where the resulting string will
|
||||||
|
* be stored. The buffer must have enough space to accommodate the entire converted
|
||||||
|
* string, including the null-terminator.
|
||||||
|
*
|
||||||
|
* @return The length of the resulting string (excluding the null-terminator).
|
||||||
|
*
|
||||||
|
* @note The buffer `buf` must have sufficient space to hold the entire converted string, including the null-terminator.
|
||||||
|
* The caller is responsible for ensuring the buffer's size is large enough to prevent buffer overflow.
|
||||||
|
* @note The provided `digits` array must have enough elements to cover the entire radix used for conversion. Otherwise, undefined behavior may occur.
|
||||||
|
*/
|
||||||
|
int esp_log_util_cvt(unsigned long long val, long radix, int pad, const char *digits, char *buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert an unsigned integer to a hexadecimal string with optional padding.
|
||||||
|
*
|
||||||
|
* This function converts an unsigned integer value to a hexadecimal string representation.
|
||||||
|
* This function calls esp_log_util_cvt(val, 16, pad, "0123456789abcdef", buf) inside.
|
||||||
|
*
|
||||||
|
* @param val The unsigned integer value to be converted.
|
||||||
|
* @param pad The optional padding width for the resulting string.
|
||||||
|
* @param buf The buffer to store the hexadecimal string.
|
||||||
|
* @return The length of the converted string.
|
||||||
|
*/
|
||||||
|
int esp_log_util_cvt_hex(unsigned long long val, int pad, char *buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert an unsigned integer to a decimal string with optional padding.
|
||||||
|
*
|
||||||
|
* This function converts an unsigned integer value to a decimal string representation.
|
||||||
|
* This function calls esp_log_util_cvt(val, 10, pad, "0123456789", buf) inside.
|
||||||
|
*
|
||||||
|
* @param val The unsigned integer value to be converted.
|
||||||
|
* @param pad The optional padding width for the resulting string.
|
||||||
|
* @param buf The buffer to store the decimal string.
|
||||||
|
* @return The length of the converted string.
|
||||||
|
*/
|
||||||
|
int esp_log_util_cvt_dec(unsigned long long val, int pad, char *buf);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@@ -1,148 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include "esp_log.h"
|
|
||||||
|
|
||||||
#ifndef CONFIG_IDF_TARGET_LINUX
|
|
||||||
#include "esp_memory_utils.h" // for esp_ptr_byte_accessible
|
|
||||||
#else
|
|
||||||
static inline bool esp_ptr_byte_accessible(const void* ptr)
|
|
||||||
{
|
|
||||||
(void) ptr;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif // CONFIG_IDF_TARGET_LINUX
|
|
||||||
|
|
||||||
//print number of bytes per line for esp_log_buffer_char and esp_log_buffer_hex
|
|
||||||
#define BYTES_PER_LINE 16
|
|
||||||
|
|
||||||
void esp_log_buffer_hex_internal(const char *tag, const void *buffer, uint16_t buff_len,
|
|
||||||
esp_log_level_t log_level)
|
|
||||||
{
|
|
||||||
if (buff_len == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
char temp_buffer[BYTES_PER_LINE + 3]; //for not-byte-accessible memory
|
|
||||||
char hex_buffer[3 * BYTES_PER_LINE + 1];
|
|
||||||
const char *ptr_line;
|
|
||||||
int bytes_cur_line;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (buff_len > BYTES_PER_LINE) {
|
|
||||||
bytes_cur_line = BYTES_PER_LINE;
|
|
||||||
} else {
|
|
||||||
bytes_cur_line = buff_len;
|
|
||||||
}
|
|
||||||
if (!esp_ptr_byte_accessible(buffer)) {
|
|
||||||
//use memcpy to get around alignment issue
|
|
||||||
memcpy(temp_buffer, buffer, (bytes_cur_line + 3) / 4 * 4);
|
|
||||||
ptr_line = temp_buffer;
|
|
||||||
} else {
|
|
||||||
ptr_line = buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < bytes_cur_line; i ++) {
|
|
||||||
sprintf(hex_buffer + 3 * i, "%02x ", (unsigned char) ptr_line[i]);
|
|
||||||
}
|
|
||||||
ESP_LOG_LEVEL(log_level, tag, "%s", hex_buffer);
|
|
||||||
buffer += bytes_cur_line;
|
|
||||||
buff_len -= bytes_cur_line;
|
|
||||||
} while (buff_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void esp_log_buffer_char_internal(const char *tag, const void *buffer, uint16_t buff_len,
|
|
||||||
esp_log_level_t log_level)
|
|
||||||
{
|
|
||||||
if (buff_len == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
char temp_buffer[BYTES_PER_LINE + 3]; //for not-byte-accessible memory
|
|
||||||
char char_buffer[BYTES_PER_LINE + 1];
|
|
||||||
const char *ptr_line;
|
|
||||||
int bytes_cur_line;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (buff_len > BYTES_PER_LINE) {
|
|
||||||
bytes_cur_line = BYTES_PER_LINE;
|
|
||||||
} else {
|
|
||||||
bytes_cur_line = buff_len;
|
|
||||||
}
|
|
||||||
if (!esp_ptr_byte_accessible(buffer)) {
|
|
||||||
//use memcpy to get around alignment issue
|
|
||||||
memcpy(temp_buffer, buffer, (bytes_cur_line + 3) / 4 * 4);
|
|
||||||
ptr_line = temp_buffer;
|
|
||||||
} else {
|
|
||||||
ptr_line = buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < bytes_cur_line; i ++) {
|
|
||||||
sprintf(char_buffer + i, "%c", ptr_line[i]);
|
|
||||||
}
|
|
||||||
ESP_LOG_LEVEL(log_level, tag, "%s", char_buffer);
|
|
||||||
buffer += bytes_cur_line;
|
|
||||||
buff_len -= bytes_cur_line;
|
|
||||||
} while (buff_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void esp_log_buffer_hexdump_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t log_level)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (buff_len == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
char temp_buffer[BYTES_PER_LINE + 3]; //for not-byte-accessible memory
|
|
||||||
const char *ptr_line;
|
|
||||||
//format: field[length]
|
|
||||||
// ADDR[10]+" "+DATA_HEX[8*3]+" "+DATA_HEX[8*3]+" |"+DATA_CHAR[8]+"|"
|
|
||||||
char hd_buffer[2 + sizeof(void *) * 2 + 3 + BYTES_PER_LINE * 3 + 1 + 3 + BYTES_PER_LINE + 1 + 1];
|
|
||||||
char *ptr_hd;
|
|
||||||
int bytes_cur_line;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (buff_len > BYTES_PER_LINE) {
|
|
||||||
bytes_cur_line = BYTES_PER_LINE;
|
|
||||||
} else {
|
|
||||||
bytes_cur_line = buff_len;
|
|
||||||
}
|
|
||||||
if (!esp_ptr_byte_accessible(buffer)) {
|
|
||||||
//use memcpy to get around alignment issue
|
|
||||||
memcpy(temp_buffer, buffer, (bytes_cur_line + 3) / 4 * 4);
|
|
||||||
ptr_line = temp_buffer;
|
|
||||||
} else {
|
|
||||||
ptr_line = buffer;
|
|
||||||
}
|
|
||||||
ptr_hd = hd_buffer;
|
|
||||||
|
|
||||||
ptr_hd += sprintf(ptr_hd, "%p ", buffer);
|
|
||||||
for (int i = 0; i < BYTES_PER_LINE; i ++) {
|
|
||||||
if ((i & 7) == 0) {
|
|
||||||
ptr_hd += sprintf(ptr_hd, " ");
|
|
||||||
}
|
|
||||||
if (i < bytes_cur_line) {
|
|
||||||
ptr_hd += sprintf(ptr_hd, " %02x", (unsigned char) ptr_line[i]);
|
|
||||||
} else {
|
|
||||||
ptr_hd += sprintf(ptr_hd, " ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ptr_hd += sprintf(ptr_hd, " |");
|
|
||||||
for (int i = 0; i < bytes_cur_line; i ++) {
|
|
||||||
if (isprint((int)ptr_line[i])) {
|
|
||||||
ptr_hd += sprintf(ptr_hd, "%c", ptr_line[i]);
|
|
||||||
} else {
|
|
||||||
ptr_hd += sprintf(ptr_hd, ".");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ptr_hd += sprintf(ptr_hd, "|");
|
|
||||||
|
|
||||||
ESP_LOG_LEVEL(log_level, tag, "%s", hd_buffer);
|
|
||||||
buffer += bytes_cur_line;
|
|
||||||
buff_len -= bytes_cur_line;
|
|
||||||
} while (buff_len);
|
|
||||||
}
|
|
137
components/log/src/buffer/log_buffers.c
Normal file
137
components/log/src/buffer/log_buffers.c
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_private/log_util.h"
|
||||||
|
|
||||||
|
#ifndef CONFIG_IDF_TARGET_LINUX
|
||||||
|
#include "esp_memory_utils.h" // for esp_ptr_byte_accessible
|
||||||
|
#else // !CONFIG_IDF_TARGET_LINUX
|
||||||
|
static inline bool esp_ptr_byte_accessible(const void* ptr)
|
||||||
|
{
|
||||||
|
(void) ptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif // !CONFIG_IDF_TARGET_LINUX
|
||||||
|
|
||||||
|
/* It represents the number of bytes printed per line when displaying the
|
||||||
|
* contents of a buffer in hexadecimal format. It determines how many bytes of
|
||||||
|
* the buffer will be shown on each line, making it easier to read and interpret
|
||||||
|
* the data. */
|
||||||
|
#define BYTES_PER_LINE 16
|
||||||
|
|
||||||
|
/* Checks if a character is a printable ASCII character.
|
||||||
|
* If the provided character falls within the printable ASCII range,
|
||||||
|
* which includes characters with ASCII values from 32 (space) to 126 (tilde). */
|
||||||
|
#define IS_CHAR_PRINTABLE(character) ((character) >= 32 && (character) <= 126)
|
||||||
|
|
||||||
|
typedef void (*print_line_t)(uintptr_t, const void *, char *, int);
|
||||||
|
|
||||||
|
static void log_buffer_hex_line(uintptr_t orig_buff, const void *ptr_line, char *output_str, int buff_len);
|
||||||
|
static void log_buffer_char_line(uintptr_t orig_buff, const void *ptr_line, char *output_str, int buff_len);
|
||||||
|
static void log_buffer_hexdump_line(uintptr_t orig_buff, const void *ptr_line, char *output_str, int buff_len);
|
||||||
|
static void print_buffer(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t log_level, char *output_str, print_line_t print_line_func);
|
||||||
|
|
||||||
|
void esp_log_buffer_hex_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t log_level)
|
||||||
|
{
|
||||||
|
// I (954) log_example: 54 68 65 20 77 61 79 20 74 6f 20 67 65 74 20 73
|
||||||
|
// I (962) log_example: 74 61 72 74 65 64 20 69 73 20 74 6f 20 71 75 69
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
char output_str[3 * BYTES_PER_LINE];
|
||||||
|
print_buffer(tag, buffer, buff_len, log_level, output_str, log_buffer_hex_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_log_buffer_char_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t log_level)
|
||||||
|
{
|
||||||
|
// I (980) log_example: The way to get s
|
||||||
|
// I (985) log_example: tarted is to qui
|
||||||
|
// ^^^^^^^^^^^^^^^^^
|
||||||
|
char output_str[BYTES_PER_LINE + 1];
|
||||||
|
print_buffer(tag, buffer, buff_len, log_level, output_str, log_buffer_char_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_log_buffer_hexdump_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t log_level)
|
||||||
|
{
|
||||||
|
// I (1013) log_example: 0x3ffb5bc0 54 68 65 20 77 61 79 20 74 6f 20 67 65 74 20 73 |The way to get s|
|
||||||
|
// I (1024) log_example: 0x3ffb5bd0 74 61 72 74 65 64 20 69 73 20 74 6f 20 71 75 69 |tarted is to qui|
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
char output_str[(2 + sizeof(void *) * 2) + 3 + (BYTES_PER_LINE * 3) + 2 + (1 + BYTES_PER_LINE + 1) + 1];
|
||||||
|
print_buffer(tag, buffer, buff_len, log_level, output_str, log_buffer_hexdump_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_buffer(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t log_level, char *output_str, print_line_t print_line_func)
|
||||||
|
{
|
||||||
|
if (buff_len == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char temp_buffer[BYTES_PER_LINE + 3]; //for not-byte-accessible memory
|
||||||
|
|
||||||
|
do {
|
||||||
|
const char *ptr_line = buffer;
|
||||||
|
int bytes_cur_line = (buff_len > BYTES_PER_LINE) ? BYTES_PER_LINE : buff_len;
|
||||||
|
if (!esp_ptr_byte_accessible(buffer)) {
|
||||||
|
//use memcpy to get around alignment issue
|
||||||
|
memcpy(temp_buffer, buffer, (bytes_cur_line + 3) / 4 * 4);
|
||||||
|
ptr_line = temp_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_line_func((uintptr_t)buffer, ptr_line, output_str, bytes_cur_line);
|
||||||
|
|
||||||
|
ESP_LOG_LEVEL(log_level, tag, "%s", output_str);
|
||||||
|
buffer += bytes_cur_line;
|
||||||
|
buff_len -= bytes_cur_line;
|
||||||
|
} while (buff_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_buffer_hex_line(uintptr_t orig_buff, const void *ptr_line, char *output_str, int buff_len)
|
||||||
|
{
|
||||||
|
(void) orig_buff;
|
||||||
|
const unsigned char *ptr = (unsigned char *)ptr_line;
|
||||||
|
for (int i = 0; i < buff_len; i++) {
|
||||||
|
output_str += esp_log_util_cvt_hex(ptr[i], 2, output_str);
|
||||||
|
*output_str++ = ' ';
|
||||||
|
}
|
||||||
|
*--output_str = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_buffer_char_line(uintptr_t orig_buff, const void *ptr_line, char *output_str, int buff_len)
|
||||||
|
{
|
||||||
|
(void) orig_buff;
|
||||||
|
const char *ptr = (char *)ptr_line;
|
||||||
|
memcpy(output_str, ptr, buff_len);
|
||||||
|
output_str[buff_len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_buffer_hexdump_line(uintptr_t orig_buff, const void *ptr_line, char *output_str, int buff_len)
|
||||||
|
{
|
||||||
|
const unsigned char *ptr = (unsigned char *)ptr_line;
|
||||||
|
*output_str++ = '0';
|
||||||
|
*output_str++ = 'x';
|
||||||
|
output_str += esp_log_util_cvt_hex(orig_buff, sizeof(uintptr_t), output_str);
|
||||||
|
*output_str++ = ' ';
|
||||||
|
for (int i = 0; i < BYTES_PER_LINE; i++) {
|
||||||
|
if ((i & 7) == 0) {
|
||||||
|
*output_str++ = ' ';
|
||||||
|
}
|
||||||
|
*output_str++ = ' ';
|
||||||
|
if (i < buff_len) {
|
||||||
|
output_str += esp_log_util_cvt_hex(ptr[i], 2, output_str);
|
||||||
|
} else {
|
||||||
|
*output_str++ = ' ';
|
||||||
|
*output_str++ = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*output_str++ = ' ';
|
||||||
|
*output_str++ = ' ';
|
||||||
|
*output_str++ = '|';
|
||||||
|
for (int i = 0; i < buff_len; i++) {
|
||||||
|
*output_str++ = IS_CHAR_PRINTABLE(ptr[i]) ? ptr[i] : '.';
|
||||||
|
}
|
||||||
|
*output_str++ = '|';
|
||||||
|
*output_str = 0;
|
||||||
|
}
|
58
components/log/src/util.c
Normal file
58
components/log/src/util.c
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
int esp_log_util_cvt(unsigned long long val, long radix, int pad, const char *digits, char *buf)
|
||||||
|
{
|
||||||
|
char *orig_buf = buf;
|
||||||
|
int length = 0;
|
||||||
|
|
||||||
|
// val = 123
|
||||||
|
do {
|
||||||
|
*buf++ = digits[val % radix];
|
||||||
|
val /= radix;
|
||||||
|
length++;
|
||||||
|
} while (val);
|
||||||
|
// 3 2 1
|
||||||
|
// buf = [0] [1] [2] [3]
|
||||||
|
|
||||||
|
// length = 3, pad = 6
|
||||||
|
while (pad > 0 && pad > length) {
|
||||||
|
*buf++ = '0';
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
*buf = '\0';
|
||||||
|
// length = 6
|
||||||
|
// 3 2 1 0 0 0 \0
|
||||||
|
// buf = [0] [1] [2] [3] [4] [5] [6]
|
||||||
|
|
||||||
|
--buf;
|
||||||
|
// reverse the order of characters
|
||||||
|
// 3 2 1 0 0 0 \0
|
||||||
|
// [0] [1] [2] [3] [4] [5] [6]
|
||||||
|
// orig_buf -- ^ ^ ----- buf
|
||||||
|
while (orig_buf < buf) {
|
||||||
|
char first_char = *orig_buf;
|
||||||
|
char last_char = *buf;
|
||||||
|
*buf-- = first_char;
|
||||||
|
*orig_buf++ = last_char;
|
||||||
|
}
|
||||||
|
// 0 0 0 1 2 3 \0
|
||||||
|
// buf = [0] [1] [2] [3] [4] [5] [6]
|
||||||
|
|
||||||
|
return (length);
|
||||||
|
}
|
||||||
|
|
||||||
|
int esp_log_util_cvt_hex(unsigned long long val, int pad, char *buf)
|
||||||
|
{
|
||||||
|
return esp_log_util_cvt(val, 16, pad, "0123456789abcdef", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int esp_log_util_cvt_dec(unsigned long long val, int pad, char *buf)
|
||||||
|
{
|
||||||
|
return esp_log_util_cvt(val, 10, pad, "0123456789", buf);
|
||||||
|
}
|
@@ -267,6 +267,8 @@ INPUT = \
|
|||||||
$(PROJECT_PATH)/components/ieee802154/include/esp_ieee802154_types.h \
|
$(PROJECT_PATH)/components/ieee802154/include/esp_ieee802154_types.h \
|
||||||
$(PROJECT_PATH)/components/ieee802154/include/esp_ieee802154.h \
|
$(PROJECT_PATH)/components/ieee802154/include/esp_ieee802154.h \
|
||||||
$(PROJECT_PATH)/components/log/include/esp_log.h \
|
$(PROJECT_PATH)/components/log/include/esp_log.h \
|
||||||
|
$(PROJECT_PATH)/components/log/include/esp_log_level.h \
|
||||||
|
$(PROJECT_PATH)/components/log/include/esp_log_buffer.h \
|
||||||
$(PROJECT_PATH)/components/lwip/include/apps/esp_sntp.h \
|
$(PROJECT_PATH)/components/lwip/include/apps/esp_sntp.h \
|
||||||
$(PROJECT_PATH)/components/lwip/include/apps/ping/ping_sock.h \
|
$(PROJECT_PATH)/components/lwip/include/apps/ping/ping_sock.h \
|
||||||
$(PROJECT_PATH)/components/mbedtls/esp_crt_bundle/include/esp_crt_bundle.h \
|
$(PROJECT_PATH)/components/mbedtls/esp_crt_bundle/include/esp_crt_bundle.h \
|
||||||
|
@@ -135,3 +135,5 @@ API Reference
|
|||||||
-------------
|
-------------
|
||||||
|
|
||||||
.. include-build-file:: inc/esp_log.inc
|
.. include-build-file:: inc/esp_log.inc
|
||||||
|
.. include-build-file:: inc/esp_log_level.inc
|
||||||
|
.. include-build-file:: inc/esp_log_buffer.inc
|
||||||
|
Reference in New Issue
Block a user