From 21f7309a52aa1ed0940143b0f03f83fc59ff5be9 Mon Sep 17 00:00:00 2001 From: Konstantin Kondrashov Date: Tue, 27 Aug 2024 13:25:57 +0300 Subject: [PATCH] feat(esp_rom): Adds esp_rom_cvt func for logging and rom_vprintf --- components/esp_rom/include/esp_rom_sys.h | 28 ++++++++++ components/esp_rom/patches/esp_rom_print.c | 60 ++++++++++++++-------- components/log/src/util.c | 43 ++-------------- 3 files changed, 71 insertions(+), 60 deletions(-) diff --git a/components/esp_rom/include/esp_rom_sys.h b/components/esp_rom/include/esp_rom_sys.h index 44bd2570c8..c8611c0ec0 100644 --- a/components/esp_rom/include/esp_rom_sys.h +++ b/components/esp_rom/include/esp_rom_sys.h @@ -53,6 +53,34 @@ int esp_rom_printf(const char *fmt, ...); */ int esp_rom_vprintf(const char *fmt, va_list ap); +/** + * @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_rom_cvt(unsigned long long val, long radix, int pad, const char *digits, char *buf); + /** * @brief Pauses execution for us microseconds * diff --git a/components/esp_rom/patches/esp_rom_print.c b/components/esp_rom/patches/esp_rom_print.c index f92f0e3dd7..2eefab0db7 100644 --- a/components/esp_rom/patches/esp_rom_print.c +++ b/components/esp_rom/patches/esp_rom_print.c @@ -14,34 +14,52 @@ #include "rom/ets_sys.h" #include "sdkconfig.h" -#if !ESP_ROM_HAS_VPRINTF_FUNC -static int _cvt(unsigned long long val, char *buf, long radix, const char *digits) +int esp_rom_cvt(unsigned long long val, long radix, int pad, const char *digits, char *buf) { -#ifdef SUPPORT_LITTLE_RADIX - char temp[64]; -#else - char temp[32]; -#endif - char *cp = temp; + char *orig_buf = buf; int length = 0; - if (val == 0) { - /* Special case */ - *cp++ = '0'; - } else { - while (val) { - *cp++ = digits[val % radix]; - val /= radix; - } + if (radix <= 0 || digits == NULL || buf == NULL) { + return 0; } - while (cp != temp) { - *buf++ = *--cp; + + // The comments below show an example of the conversion process for val = 123 and pad = 6 + 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); } +#if !ESP_ROM_HAS_VPRINTF_FUNC #define is_digit(c) ((c >= '0') && (c <= '9')) static int ets_vprintf(void (*putc)(char c), const char *fmt, va_list ap) { @@ -151,14 +169,14 @@ static int ets_vprintf(void (*putc)(char c), const char *fmt, va_list ap) case 'D': case 'u': case 'U': - length = _cvt(val, buf, 10, "0123456789"); + length = esp_rom_cvt(val, 10, 0, "0123456789", buf); break; case 'p': case 'x': - length = _cvt(val, buf, 16, "0123456789abcdef"); + length = esp_rom_cvt(val, 16, 0, "0123456789abcdef", buf); break; case 'X': - length = _cvt(val, buf, 16, "0123456789ABCDEF"); + length = esp_rom_cvt(val, 16, 0, "0123456789ABCDEF", buf); break; } cp = buf; diff --git a/components/log/src/util.c b/components/log/src/util.c index 675ee09b97..9a724d056b 100644 --- a/components/log/src/util.c +++ b/components/log/src/util.c @@ -5,54 +5,19 @@ */ #include +#include "esp_rom_sys.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); + return esp_rom_cvt(val, radix, pad, digits, buf); } int esp_log_util_cvt_hex(unsigned long long val, int pad, char *buf) { - return esp_log_util_cvt(val, 16, pad, "0123456789abcdef", buf); + return esp_rom_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); + return esp_rom_cvt(val, 10, pad, "0123456789", buf); }