Skip to content

Commit 0ea15dc

Browse files
author
Konstantin Kondrashov
committed
Merge branch 'feature/logv2_preliminary' into 'master'
feat(log): Some simple changes in log to prepare it for log v2 See merge request espressif/esp-idf!35289
2 parents 486fd18 + d9265a3 commit 0ea15dc

File tree

14 files changed

+203
-117
lines changed

14 files changed

+203
-117
lines changed

components/esp_rom/include/esp_rom_sys.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,34 @@ int esp_rom_printf(const char *fmt, ...);
5353
*/
5454
int esp_rom_vprintf(const char *fmt, va_list ap);
5555

56+
/**
57+
* @brief Convert an unsigned integer value to a string representation in the specified radix.
58+
*
59+
* This function converts the given unsigned integer value to a string representation in the specified radix.
60+
* The resulting string is stored in the provided character buffer `buf`.
61+
*
62+
* @param[in] val The unsigned integer value to be converted.
63+
* @param[in] radix The base of the numeral system to be used for the conversion.
64+
* It determines the number of unique digits in the numeral system
65+
* (e.g., 2 for binary, 10 for decimal, 16 for hexadecimal).
66+
* @param[in] pad The optional padding width (0 - unused) for the resulting string. It adds zero-padding.
67+
* (val=123, pad=6 -> result=000123).
68+
* @param[in] digits Pointer to a character array representing the digits of the
69+
* numeral system. The array must contain characters in the order of increasing
70+
* values, corresponding to the digits of the radix. For example, "0123456789ABCDEF"
71+
* or hexadecimal.
72+
* @param[out] buf Pointer to the character buffer where the resulting string will
73+
* be stored. The buffer must have enough space to accommodate the entire converted
74+
* string, including the null-terminator.
75+
*
76+
* @return The length of the resulting string (excluding the null-terminator).
77+
*
78+
* @note The buffer `buf` must have sufficient space to hold the entire converted string, including the null-terminator.
79+
* The caller is responsible for ensuring the buffer's size is large enough to prevent buffer overflow.
80+
* @note The provided `digits` array must have enough elements to cover the entire radix used for conversion. Otherwise, undefined behavior may occur.
81+
*/
82+
int esp_rom_cvt(unsigned long long val, long radix, int pad, const char *digits, char *buf);
83+
5684
/**
5785
* @brief Pauses execution for us microseconds
5886
*

components/esp_rom/patches/esp_rom_print.c

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,34 +14,52 @@
1414
#include "rom/ets_sys.h"
1515
#include "sdkconfig.h"
1616

17-
#if !ESP_ROM_HAS_VPRINTF_FUNC
18-
static int _cvt(unsigned long long val, char *buf, long radix, const char *digits)
17+
int esp_rom_cvt(unsigned long long val, long radix, int pad, const char *digits, char *buf)
1918
{
20-
#ifdef SUPPORT_LITTLE_RADIX
21-
char temp[64];
22-
#else
23-
char temp[32];
24-
#endif
25-
char *cp = temp;
19+
char *orig_buf = buf;
2620
int length = 0;
2721

28-
if (val == 0) {
29-
/* Special case */
30-
*cp++ = '0';
31-
} else {
32-
while (val) {
33-
*cp++ = digits[val % radix];
34-
val /= radix;
35-
}
22+
if (radix <= 0 || digits == NULL || buf == NULL) {
23+
return 0;
3624
}
37-
while (cp != temp) {
38-
*buf++ = *--cp;
25+
26+
// The comments below show an example of the conversion process for val = 123 and pad = 6
27+
do {
28+
*buf++ = digits[val % radix];
29+
val /= radix;
30+
length++;
31+
} while (val);
32+
// 3 2 1
33+
// buf = [0] [1] [2] [3]
34+
35+
// length = 3, pad = 6
36+
while (pad > 0 && pad > length) {
37+
*buf++ = '0';
3938
length++;
4039
}
4140
*buf = '\0';
41+
// length = 6
42+
// 3 2 1 0 0 0 \0
43+
// buf = [0] [1] [2] [3] [4] [5] [6]
44+
45+
--buf;
46+
// reverse the order of characters
47+
// 3 2 1 0 0 0 \0
48+
// [0] [1] [2] [3] [4] [5] [6]
49+
// orig_buf -- ^ ^ ----- buf
50+
while (orig_buf < buf) {
51+
char first_char = *orig_buf;
52+
char last_char = *buf;
53+
*buf-- = first_char;
54+
*orig_buf++ = last_char;
55+
}
56+
// 0 0 0 1 2 3 \0
57+
// buf = [0] [1] [2] [3] [4] [5] [6]
58+
4259
return (length);
4360
}
4461

62+
#if !ESP_ROM_HAS_VPRINTF_FUNC
4563
#define is_digit(c) ((c >= '0') && (c <= '9'))
4664
static int ets_vprintf(void (*putc)(char c), const char *fmt, va_list ap)
4765
{
@@ -151,14 +169,14 @@ static int ets_vprintf(void (*putc)(char c), const char *fmt, va_list ap)
151169
case 'D':
152170
case 'u':
153171
case 'U':
154-
length = _cvt(val, buf, 10, "0123456789");
172+
length = esp_rom_cvt(val, 10, 0, "0123456789", buf);
155173
break;
156174
case 'p':
157175
case 'x':
158-
length = _cvt(val, buf, 16, "0123456789abcdef");
176+
length = esp_rom_cvt(val, 16, 0, "0123456789abcdef", buf);
159177
break;
160178
case 'X':
161-
length = _cvt(val, buf, 16, "0123456789ABCDEF");
179+
length = esp_rom_cvt(val, 16, 0, "0123456789ABCDEF", buf);
162180
break;
163181
}
164182
cp = buf;

components/log/include/esp_log.h

Lines changed: 2 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -15,55 +15,13 @@
1515
#include "esp_log_color.h"
1616
#include "esp_log_buffer.h"
1717
#include "esp_log_timestamp.h"
18+
#include "esp_log_write.h"
19+
#include "esp_log_format.h"
1820

1921
#ifdef __cplusplus
2022
extern "C" {
2123
#endif
2224

23-
typedef int (*vprintf_like_t)(const char *, va_list);
24-
25-
/**
26-
* @brief Set function used to output log entries
27-
*
28-
* By default, log output goes to UART0. This function can be used to redirect log
29-
* output to some other destination, such as file or network. Returns the original
30-
* log handler, which may be necessary to return output to the previous destination.
31-
*
32-
* @note Please note that function callback here must be re-entrant as it can be
33-
* invoked in parallel from multiple thread context.
34-
*
35-
* @param func new Function used for output. Must have same signature as vprintf.
36-
*
37-
* @return func old Function used for output.
38-
*/
39-
vprintf_like_t esp_log_set_vprintf(vprintf_like_t func);
40-
41-
/**
42-
* @brief Write message into the log
43-
*
44-
* This function is not intended to be used directly. Instead, use one of
45-
* ESP_LOGE, ESP_LOGW, ESP_LOGI, ESP_LOGD, ESP_LOGV macros.
46-
*
47-
* This function or these macros should not be used from an interrupt.
48-
*/
49-
void esp_log_write(esp_log_level_t level, const char* tag, const char* format, ...) __attribute__((format(printf, 3, 4)));
50-
51-
/**
52-
* @brief Write message into the log, va_list variant
53-
* @see esp_log_write()
54-
*
55-
* This function is provided to ease integration toward other logging framework,
56-
* so that esp_log can be used as a log sink.
57-
*/
58-
void esp_log_writev(esp_log_level_t level, const char* tag, const char* format, va_list args);
59-
60-
/** @cond */
61-
62-
#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%" PRIu32 ") %s: " format LOG_RESET_COLOR "\n"
63-
#define LOG_SYSTEM_TIME_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%s) %s: " format LOG_RESET_COLOR "\n"
64-
65-
/** @endcond */
66-
6725
/// macro to output logs in startup code, before heap allocator and syscalls have been initialized.
6826
/// Log at ``ESP_LOG_ERROR`` level. @see ``printf``,``ESP_LOGE``,``ESP_DRAM_LOGE``
6927

@@ -244,7 +202,6 @@ void esp_log_writev(esp_log_level_t level, const char* tag, const char* format,
244202
#endif // !(defined(__cplusplus) && (__cplusplus > 201703L))
245203

246204
/** @cond */
247-
#define _ESP_LOG_DRAM_LOG_FORMAT(letter, format) DRAM_STR(#letter " %s: " format "\n")
248205

249206
#if defined(__cplusplus) && (__cplusplus > 201703L)
250207
#define ESP_DRAM_LOG_IMPL(tag, format, log_level, log_tag_letter, ...) do { \

components/log/include/esp_log_buffer.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ void esp_log_buffer_hexdump_internal(const char *tag, const void *buffer, uint16
8080
* @param level Log level
8181
*/
8282
#define ESP_LOG_BUFFER_HEX_LEVEL(tag, buffer, buff_len, level) \
83-
do { if (LOG_LOCAL_LEVEL >= (level)) {esp_log_buffer_hex_internal(tag, buffer, buff_len, level);} } while(0)
83+
do { if (ESP_LOG_ENABLED(level)) {esp_log_buffer_hex_internal(tag, buffer, buff_len, level);} } while(0)
8484

8585
/**
8686
* @brief Log a buffer of characters at specified level, separated into 16 bytes each line. Buffer should contain only printable characters.
@@ -100,7 +100,7 @@ void esp_log_buffer_hexdump_internal(const char *tag, const void *buffer, uint16
100100
*
101101
*/
102102
#define ESP_LOG_BUFFER_CHAR_LEVEL(tag, buffer, buff_len, level) \
103-
do { if (LOG_LOCAL_LEVEL >= (level)) {esp_log_buffer_char_internal(tag, buffer, buff_len, level);} } while(0)
103+
do { if (ESP_LOG_ENABLED(level)) {esp_log_buffer_char_internal(tag, buffer, buff_len, level);} } while(0)
104104

105105
/**
106106
* @brief Dump a buffer to the log at specified level.
@@ -121,7 +121,7 @@ void esp_log_buffer_hexdump_internal(const char *tag, const void *buffer, uint16
121121
* @param level Log level.
122122
*/
123123
#define ESP_LOG_BUFFER_HEXDUMP(tag, buffer, buff_len, level) \
124-
do { if (LOG_LOCAL_LEVEL >= (level)) {esp_log_buffer_hexdump_internal(tag, buffer, buff_len, level);} } while(0)
124+
do { if (ESP_LOG_ENABLED(level)) {esp_log_buffer_hexdump_internal(tag, buffer, buff_len, level);} } while(0)
125125

126126
/**
127127
* @brief Log a buffer of hex bytes at Info level
@@ -134,7 +134,7 @@ void esp_log_buffer_hexdump_internal(const char *tag, const void *buffer, uint16
134134
*
135135
*/
136136
#define ESP_LOG_BUFFER_HEX(tag, buffer, buff_len) \
137-
do { if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) {ESP_LOG_BUFFER_HEX_LEVEL(tag, buffer, buff_len, ESP_LOG_INFO);} } while(0)
137+
do { if (ESP_LOG_ENABLED(ESP_LOG_INFO)) {ESP_LOG_BUFFER_HEX_LEVEL(tag, buffer, buff_len, ESP_LOG_INFO);} } while(0)
138138

139139
/**
140140
* @brief Log a buffer of characters at Info level. Buffer should contain only printable characters.
@@ -147,7 +147,7 @@ void esp_log_buffer_hexdump_internal(const char *tag, const void *buffer, uint16
147147
*
148148
*/
149149
#define ESP_LOG_BUFFER_CHAR(tag, buffer, buff_len) \
150-
do { if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) {ESP_LOG_BUFFER_CHAR_LEVEL(tag, buffer, buff_len, ESP_LOG_INFO);} } while(0)
150+
do { if (ESP_LOG_ENABLED(ESP_LOG_INFO)) {ESP_LOG_BUFFER_CHAR_LEVEL(tag, buffer, buff_len, ESP_LOG_INFO);} } while(0)
151151

152152
/** @cond */
153153
/**
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#ifdef __cplusplus
10+
extern "C" {
11+
#endif
12+
13+
/** @cond */
14+
// For backward compatibility (these macros are not used in the log v2).
15+
#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%" PRIu32 ") %s: " format LOG_RESET_COLOR "\n"
16+
#define _ESP_LOG_DRAM_LOG_FORMAT(letter, format) DRAM_STR(#letter " %s: " format "\n")
17+
#define LOG_SYSTEM_TIME_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%s) %s: " format LOG_RESET_COLOR "\n"
18+
/** @endcond */
19+
20+
#ifdef __cplusplus
21+
}
22+
#endif

components/log/include/esp_log_level.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#pragma once
88

99
#include <stdint.h>
10+
#include "esp_assert.h"
1011
#include "sdkconfig.h"
1112

1213
#ifdef __cplusplus
@@ -26,7 +27,11 @@ typedef enum {
2627
ESP_LOG_MAX = 6, /*!< Number of levels supported */
2728
} esp_log_level_t;
2829

30+
#define ESP_LOG_LEVEL_LEN (3) /*!< Number of bits used to represent the log level */
31+
#define ESP_LOG_LEVEL_MASK ((1 << ESP_LOG_LEVEL_LEN) - 1) /*!< Mask for log level */
32+
2933
/** @cond */
34+
ESP_STATIC_ASSERT(ESP_LOG_MAX <= ESP_LOG_LEVEL_MASK, "Log level items of esp_log_level_t must fit ESP_LOG_LEVEL_MASK");
3035

3136
// LOG_LOCAL_LEVEL controls what log levels are included in the binary.
3237
#ifndef LOG_LOCAL_LEVEL
@@ -39,6 +44,19 @@ typedef enum {
3944
#endif
4045
#endif // LOG_LOCAL_LEVEL
4146

47+
/**
48+
* @brief Check if a specific log level is enabled at compile-time.
49+
*
50+
* This macro checks whether logging for the specified log level is enabled based on the
51+
* current local log level setting (`LOG_LOCAL_LEVEL`). It uses a compile-time check to
52+
* determine if logging for the specified level should be included in the binary,
53+
* helping to exclude logs that are not configured.
54+
*
55+
* @param level log level.
56+
* @return true if the specified log level is enabled, false otherwise.
57+
*/
58+
#define ESP_LOG_ENABLED(level) (LOG_LOCAL_LEVEL >= (level))
59+
4260
#if NON_OS_BUILD
4361

4462
#define _ESP_LOG_ENABLED(log_level) (LOG_LOCAL_LEVEL >= (log_level))
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#include <stdint.h>
10+
#include <stdarg.h>
11+
#include "esp_log_level.h"
12+
13+
#ifdef __cplusplus
14+
extern "C" {
15+
#endif
16+
17+
typedef int (*vprintf_like_t)(const char *, va_list);
18+
19+
/**
20+
* @brief Set function used to output log entries
21+
*
22+
* By default, log output goes to UART0. This function can be used to redirect log
23+
* output to some other destination, such as file or network. Returns the original
24+
* log handler, which may be necessary to return output to the previous destination.
25+
*
26+
* @note Please note that function callback here must be re-entrant as it can be
27+
* invoked in parallel from multiple tasks context.
28+
*
29+
* @param func new Function used for output. Must have same signature as vprintf.
30+
*
31+
* @return func old Function used for output.
32+
*/
33+
vprintf_like_t esp_log_set_vprintf(vprintf_like_t func);
34+
35+
/**
36+
* @brief Write message into the log
37+
*
38+
* This function is not intended to be used directly. Instead, use one of
39+
* ESP_LOGE, ESP_LOGW, ESP_LOGI, ESP_LOGD, ESP_LOGV macros.
40+
*
41+
* This function or these macros should not be used from an interrupt.
42+
*
43+
* This function does not add any formatting elements such as color, timestamp, or tag.
44+
* It checks the level and tag level. If logging is allowed then it outputs it as is.
45+
*
46+
* @param level Log level of the message.
47+
* @param tag It is used to check whether logging is enabled for that tag (depends on CONFIG_LOG_TAG_LEVEL_IMPL).
48+
* @param format The format string for the log message. It has to be fully formatted, no additional formatting items will be added.
49+
* @param ... Optional arguments to be formatted according to the format string.
50+
*/
51+
void esp_log_write(esp_log_level_t level, const char* tag, const char* format, ...) __attribute__((format(printf, 3, 4)));
52+
53+
/**
54+
* @brief Write message into the log, va_list variant
55+
* @see esp_log_write()
56+
*
57+
* This function is provided to ease integration toward other logging framework,
58+
* so that esp_log can be used as a log sink.
59+
*
60+
* This function does not add any formatting elements such as color, timestamp, or tag.
61+
* It checks the level and tag level. If logging is allowed then it outputs it as is.
62+
*
63+
* @param level Log level of the message.
64+
* @param tag It is used to check whether logging is enabled for that tag (depends on CONFIG_LOG_TAG_LEVEL_IMPL).
65+
* @param format The format string for the log message. It has to be fully formatted, no additional formatting items will be added.
66+
* @param args List of arguments.
67+
*/
68+
void esp_log_writev(esp_log_level_t level, const char* tag, const char* format, va_list args);
69+
70+
#ifdef __cplusplus
71+
}
72+
#endif

0 commit comments

Comments
 (0)