diff --git a/CHANGELOG.md b/CHANGELOG.md index efa6ad8..1544752 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # ChangeLog +## v0.2.2 - 2025-06-27 + +### Enhancements: + +* feat(log): add CXX log trace guard and ESP-IDF log implementation +* feat(check): add value check macros +* feat(repo): add thread module, support configure thread +* feat(repo): add more module, support some guard classes +* feat(cmake): remove CXX compile options + ## v0.2.1 - 2025-05-30 ### Enhancements: diff --git a/CMakeLists.txt b/CMakeLists.txt index 86ee7c4..3fd3ab1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ if(ESP_PLATFORM) idf_component_register( SRCS ${SRCS_C} ${SRCS_CPP} INCLUDE_DIRS ${SRC_DIR} + PRIV_REQUIRES pthread ) else() set(COMPONENT_LIB esp-lib-utils) @@ -16,8 +17,6 @@ endif() target_compile_options(${COMPONENT_LIB} PUBLIC -Wno-missing-field-initializers - PRIVATE - $<$:-std=gnu++20> ) if(NOT ESP_PLATFORM) diff --git a/Kconfig b/Kconfig index f7b9569..340fda2 100644 --- a/Kconfig +++ b/Kconfig @@ -7,7 +7,7 @@ menu "ESP Library Utils Configurations" if ESP_UTILS_CONF_FILE_SKIP menu "Check functions" - choice ESP_UTILS_CONF_CHECK_HANDLE_METHOD + choice ESP_UTILS_CONF_CHECK_HANDLE_METHOD_CHOICE prompt "Select handle method when check failed" default ESP_UTILS_CHECK_HANDLE_WITH_ERROR_LOG @@ -29,7 +29,23 @@ menu "ESP Library Utils Configurations" endmenu menu "Log functions" - choice ESP_UTILS_CONF_LOG_LEVEL + choice ESP_UTILS_CONF_LOG_IMPL_TYPE_CHOICE + prompt "Select log implementation" + default ESP_UTILS_CONF_LOG_IMPL_ESP + + config ESP_UTILS_CONF_LOG_IMPL_STDLIB + bool "Standard (printf)" + + config ESP_UTILS_CONF_LOG_IMPL_ESP + bool "ESP (ESP_LOG)" + endchoice + + config ESP_UTILS_CONF_LOG_IMPL_TYPE + int + default 0 if ESP_UTILS_CONF_LOG_IMPL_STDLIB + default 1 if ESP_UTILS_CONF_LOG_IMPL_ESP + + choice ESP_UTILS_CONF_LOG_LEVEL_CHOICE prompt "Select global log level" default ESP_UTILS_CONF_LOG_LEVEL_INFO @@ -110,7 +126,7 @@ menu "ESP Library Utils Configurations" default 2 if ESP_UTILS_CONF_MEM_GEN_ALLOC_TYPE_MICROPYTHON default 3 if ESP_UTILS_CONF_MEM_GEN_ALLOC_TYPE_CUSTOM - choice ESP_UTILS_CONF_MEM_GEN_ALLOC_ESP_CAPS + choice ESP_UTILS_CONF_MEM_GEN_ALLOC_ESP_CAPS_CHOICE prompt "ESP memory caps" depends on ESP_UTILS_CONF_MEM_GEN_ALLOC_TYPE_ESP default ESP_UTILS_CONF_MEM_GEN_ALLOC_ESP_CAPS_DEFAULT @@ -177,7 +193,7 @@ menu "ESP Library Utils Configurations" default 2 if ESP_UTILS_CONF_MEM_CXX_GLOB_ALLOC_TYPE_MICROPYTHON default 3 if ESP_UTILS_CONF_MEM_CXX_GLOB_ALLOC_TYPE_CUSTOM - choice ESP_UTILS_CONF_MEM_CXX_GLOB_ALLOC_ESP_CAPS + choice ESP_UTILS_CONF_MEM_CXX_GLOB_ALLOC_ESP_CAPS_CHOICE prompt "ESP memory caps" depends on ESP_UTILS_CONF_MEM_CXX_GLOB_ALLOC_TYPE_ESP default ESP_UTILS_CONF_MEM_CXX_GLOB_ALLOC_ESP_CAPS_DEFAULT diff --git a/esp_utils_conf.h b/esp_utils_conf.h index f865cfe..40a6ac2 100644 --- a/esp_utils_conf.h +++ b/esp_utils_conf.h @@ -22,6 +22,13 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////// Log Configurations ////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Log implementation, choose one of the following: + * - ESP_UTILS_CONF_LOG_IMPL_STDLIB: Use the standard library log implementation (printf) + * - ESP_UTILS_CONF_LOG_IMPL_ESP: Use the ESP-IDF log implementation (ESP_LOG) + */ +#define ESP_UTILS_CONF_LOG_IMPL_TYPE (ESP_UTILS_CONF_LOG_IMPL_STDLIB) + /** * Global log level, logs with a level lower than this will not be compiled. Choose one of the following: * - ESP_UTILS_LOG_LEVEL_DEBUG: Extra information which is not necessary for normal use (values, pointers, sizes, etc) @@ -135,7 +142,7 @@ * 3. Patch version mismatch: No impact on functionality */ #define ESP_UTILS_CONF_FILE_VERSION_MAJOR 1 -#define ESP_UTILS_CONF_FILE_VERSION_MINOR 3 +#define ESP_UTILS_CONF_FILE_VERSION_MINOR 4 #define ESP_UTILS_CONF_FILE_VERSION_PATCH 0 // *INDENT-ON* diff --git a/idf_component.yml b/idf_component.yml index 012811b..0b2bbe5 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -1,4 +1,4 @@ -version: "0.2.1" +version: "0.2.2" description: esp-lib-utils is a library designed for ESP SoCs to provide utility functions, including logging, checking, and memory. url: https://github.com/esp-arduino-libs/esp-lib-utils repository: https://github.com/esp-arduino-libs/esp-lib-utils.git diff --git a/library.properties b/library.properties index 531513f..7a9b525 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=esp-lib-utils -version=0.2.1 +version=0.2.2 author=espressif maintainer=espressif sentence=esp-lib-utils is a library designed for ESP SoCs to provide utility functions, including logging, checking, and memory. diff --git a/src/check/esp_utils_check.h b/src/check/esp_utils_check.h index 4580b93..4cd737f 100644 --- a/src/check/esp_utils_check.h +++ b/src/check/esp_utils_check.h @@ -189,6 +189,21 @@ } while (0) #endif // __cplusplus && CONFIG_COMPILER_CXX_EXCEPTIONS +/** + * @brief Check if the value is within the range [min, max]; + * + * @param x Value to check + * @param min Minimum acceptable value + * @param max Maximum acceptable value + */ +#define ESP_UTILS_CHECK_VALUE(x, min, max) do { \ + __typeof__(x) _x = (x); \ + __typeof__(min) _min = (min); \ + __typeof__(max) _max = (max); \ + if ((_x < _min) || (_x > _max)) { \ + } \ + } while(0) + #else #ifndef unlikely @@ -392,6 +407,22 @@ } while (0) #endif // __cplusplus && CONFIG_COMPILER_CXX_EXCEPTIONS +/** + * @brief Check if the value is within the range [min, max]; if not, log an error + * + * @param x Value to check + * @param min Minimum acceptable value + * @param max Maximum acceptable value + */ +#define ESP_UTILS_CHECK_VALUE(x, min, max) do { \ + __typeof__(x) _x = (x); \ + __typeof__(min) _min = (min); \ + __typeof__(max) _max = (max); \ + if ((_x < _min) || (_x > _max)) { \ + ESP_UTILS_LOGE("Invalid value: %d, should be in range [%d, %d]", _x, _min, _max); \ + } \ + } while(0) + #elif ESP_UTILS_CONF_CHECK_HANDLE_METHOD == ESP_UTILS_CHECK_HANDLE_WITH_ASSERT #define ESP_UTILS_CHECK_NULL_RETURN(x, ...) assert((x) != NULL) @@ -456,9 +487,69 @@ } while (0) #endif // __cplusplus && CONFIG_COMPILER_CXX_EXCEPTIONS +#define ESP_UTILS_CHECK_VALUE(x, min, max) do { \ + __typeof__(x) _x = (x); \ + __typeof__(min) _min = (min); \ + __typeof__(max) _max = (max); \ + assert((_x >= _min) && (_x <= _max)); \ + } while(0) + #endif // ESP_UTILS_CONF_CHECK_HANDLE_METHOD #endif // ESP_UTILS_CONF_CHECK_HANDLE_METHOD +/** + * @brief Check if the value is within the range [min, max]; if not, log an error and return the specified value. + * + * @param x Value to check + * @param min Minimum acceptable value + * @param max Maximum acceptable value + * @param ret Value to return if the value is out of range + * @param fmt Format string for the error message + * @param ... Additional arguments for the format string + */ +#define ESP_UTILS_CHECK_VALUE_RETURN(x, min, max, ret, fmt, ...) do { \ + __typeof__(x) __x = (x); \ + __typeof__(min) __min = (min); \ + __typeof__(max) __max = (max); \ + ESP_UTILS_CHECK_VALUE(__x, __min, __max); \ + ESP_UTILS_CHECK_FALSE_RETURN((__x >= __min) && (__x <= __max), ret, fmt, ##__VA_ARGS__); \ + } while(0) + +/** + * @brief Check if the value is within the range [min, max]; if not, log an error and goto the specified label. + * + * @param x Value to check + * @param min Minimum acceptable value + * @param max Maximum acceptable value + * @param goto_tag Label to jump to if the value is out of range + * @param fmt Format string for the error message + * @param ... Additional arguments for the format string + */ +#define ESP_UTILS_CHECK_VALUE_GOTO(x, min, max, goto_tag, fmt, ...) do { \ + __typeof__(x) __x = (x); \ + __typeof__(min) __min = (min); \ + __typeof__(max) __max = (max); \ + ESP_UTILS_CHECK_VALUE(__x, __min, __max); \ + ESP_UTILS_CHECK_FALSE_GOTO((__x >= __min) && (__x <= __max), goto_tag, fmt, ##__VA_ARGS__); \ + } while(0) + +/** + * @brief Check if the value is within the range [min, max]; if not, log an error and return without a value. + * + * @param x Value to check + * @param min Minimum acceptable value + * @param max Maximum acceptable value + * @param fmt Format string for the error message + * @param ... Additional arguments for the format string + */ +#define ESP_UTILS_CHECK_VALUE_EXIT(x, min, max, fmt, ...) do { \ + __typeof__(x) __x = (x); \ + __typeof__(min) __min = (min); \ + __typeof__(max) __max = (max); \ + ESP_UTILS_CHECK_VALUE(__x, __min, __max); \ + ESP_UTILS_CHECK_FALSE_EXIT((__x >= __min) && (__x <= __max), fmt, ##__VA_ARGS__); \ + } while(0) + #ifdef __cplusplus #ifndef ESP_UTILS_CHECK_EXCEPTION_RETURN #define ESP_UTILS_CHECK_EXCEPTION_RETURN(x, ret, fmt, ...) ((void)(x)) diff --git a/src/esp_lib_utils.h b/src/esp_lib_utils.h index 994a691..daf72c6 100644 --- a/src/esp_lib_utils.h +++ b/src/esp_lib_utils.h @@ -18,3 +18,12 @@ /* Memory */ #include "memory/esp_utils_mem.h" + +#if defined(__cplusplus) +/* Thread */ +#include "thread/esp_utils_thread.hpp" +/* Log */ +#include "log/esp_utils_log.hpp" +/* More */ +#include "more/esp_utils_more.hpp" +#endif // defined(__cplusplus) diff --git a/src/esp_utils_conf_kconfig.h b/src/esp_utils_conf_kconfig.h index 1149133..125844f 100644 --- a/src/esp_utils_conf_kconfig.h +++ b/src/esp_utils_conf_kconfig.h @@ -20,6 +20,14 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////// LOG Configurations ////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#ifndef ESP_UTILS_CONF_LOG_IMPL_TYPE +# ifdef CONFIG_ESP_UTILS_CONF_LOG_IMPL_TYPE +# define ESP_UTILS_CONF_LOG_IMPL_TYPE CONFIG_ESP_UTILS_CONF_LOG_IMPL_TYPE +# else +# define ESP_UTILS_CONF_LOG_IMPL_TYPE ESP_UTILS_LOG_IMPL_STDLIB +# endif +#endif + #ifndef ESP_UTILS_CONF_LOG_LEVEL # ifdef CONFIG_ESP_UTILS_CONF_LOG_LEVEL # define ESP_UTILS_CONF_LOG_LEVEL CONFIG_ESP_UTILS_CONF_LOG_LEVEL diff --git a/src/esp_utils_types.h b/src/esp_utils_types.h index 1ebbf84..a9f7edf 100644 --- a/src/esp_utils_types.h +++ b/src/esp_utils_types.h @@ -13,6 +13,12 @@ #define ESP_UTILS_CHECK_HANDLE_WITH_ERROR_LOG (1) /*!< Print error message when check failed */ #define ESP_UTILS_CHECK_HANDLE_WITH_ASSERT (2) /*!< Assert when check failed */ +/** + * @brief Macros for log implementation + */ +#define ESP_UTILS_LOG_IMPL_STDLIB (0) /*!< Standard (printf) */ +#define ESP_UTILS_LOG_IMPL_ESP (1) /*!< ESP (esp_log) */ + /** * @brief Macros for log level */ diff --git a/src/esp_utils_versions.h b/src/esp_utils_versions.h index aaf197a..5f5b55f 100644 --- a/src/esp_utils_versions.h +++ b/src/esp_utils_versions.h @@ -8,9 +8,9 @@ /* Library Version */ #define ESP_UTILS_VERSION_MAJOR 0 #define ESP_UTILS_VERSION_MINOR 2 -#define ESP_UTILS_VERSION_PATCH 1 +#define ESP_UTILS_VERSION_PATCH 2 /* File `esp_utils_conf.h` */ #define ESP_UTILS_CONF_VERSION_MAJOR 1 -#define ESP_UTILS_CONF_VERSION_MINOR 3 +#define ESP_UTILS_CONF_VERSION_MINOR 4 #define ESP_UTILS_CONF_VERSION_PATCH 0 diff --git a/src/log/esp_utils_log.h b/src/log/esp_utils_log.h index 6737b95..4d10a3d 100644 --- a/src/log/esp_utils_log.h +++ b/src/log/esp_utils_log.h @@ -8,25 +8,23 @@ #include #include #include "esp_utils_conf_internal.h" +#if ESP_UTILS_CONF_LOG_IMPL_TYPE == ESP_UTILS_LOG_IMPL_STDLIB +# include "impl/esp_utils_log_impl_std.h" +#elif ESP_UTILS_CONF_LOG_IMPL_TYPE == ESP_UTILS_LOG_IMPL_ESP +# include "impl/esp_utils_log_impl_esp.h" +#else +# error "Invalid log implementation" +#endif #ifndef ESP_UTILS_LOG_TAG #define ESP_UTILS_LOG_TAG "Utils" #endif -#define ESP_UTILS_IMPL_LOGD(format, ...) printf("[D][" ESP_UTILS_LOG_TAG "][%s:%04d](%s): " format "\n", \ - esp_utils_log_extract_file_name(__FILE__), __LINE__, __func__, ##__VA_ARGS__) -#define ESP_UTILS_IMPL_LOGI(format, ...) printf("[I][" ESP_UTILS_LOG_TAG "][%s:%04d](%s): " format "\n", \ - esp_utils_log_extract_file_name(__FILE__), __LINE__, __func__, ##__VA_ARGS__) -#define ESP_UTILS_IMPL_LOGW(format, ...) printf("[W][" ESP_UTILS_LOG_TAG "][%s:%04d](%s): " format "\n", \ - esp_utils_log_extract_file_name(__FILE__), __LINE__, __func__, ##__VA_ARGS__) -#define ESP_UTILS_IMPL_LOGE(format, ...) printf("[E][" ESP_UTILS_LOG_TAG "][%s:%04d](%s): " format "\n", \ - esp_utils_log_extract_file_name(__FILE__), __LINE__, __func__, ##__VA_ARGS__) - #define ESP_UTILS_LOG_LEVEL(level, format, ...) do { \ - if (level == ESP_UTILS_LOG_LEVEL_DEBUG) { ESP_UTILS_IMPL_LOGD(format, ##__VA_ARGS__); } \ - else if (level == ESP_UTILS_LOG_LEVEL_INFO) { ESP_UTILS_IMPL_LOGI(format, ##__VA_ARGS__); } \ - else if (level == ESP_UTILS_LOG_LEVEL_WARNING) { ESP_UTILS_IMPL_LOGW(format, ##__VA_ARGS__); } \ - else if (level == ESP_UTILS_LOG_LEVEL_ERROR) { ESP_UTILS_IMPL_LOGE(format, ##__VA_ARGS__); } \ + if (level == ESP_UTILS_LOG_LEVEL_DEBUG) { ESP_UTILS_IMPL_LOGD(ESP_UTILS_LOG_TAG, format, ##__VA_ARGS__); } \ + else if (level == ESP_UTILS_LOG_LEVEL_INFO) { ESP_UTILS_IMPL_LOGI(ESP_UTILS_LOG_TAG, format, ##__VA_ARGS__); } \ + else if (level == ESP_UTILS_LOG_LEVEL_WARNING) { ESP_UTILS_IMPL_LOGW(ESP_UTILS_LOG_TAG, format, ##__VA_ARGS__); } \ + else if (level == ESP_UTILS_LOG_LEVEL_ERROR) { ESP_UTILS_IMPL_LOGE(ESP_UTILS_LOG_TAG, format, ##__VA_ARGS__); } \ else { } \ } while(0) @@ -52,15 +50,6 @@ # define ESP_UTILS_LOG_TRACE_ENTER() # define ESP_UTILS_LOG_TRACE_EXIT() #endif -#ifdef __cplusplus -# if ESP_UTILS_CONF_ENABLE_LOG_TRACE -# define ESP_UTILS_LOG_TRACE_ENTER_WITH_THIS() ESP_UTILS_LOGD("(@%p) Enter", this) -# define ESP_UTILS_LOG_TRACE_EXIT_WITH_THIS() ESP_UTILS_LOGD("(@%p) Exit", this) -# else -# define ESP_UTILS_LOG_TRACE_ENTER_WITH_THIS() -# define ESP_UTILS_LOG_TRACE_EXIT_WITH_THIS() -# endif -#endif #ifdef __cplusplus extern "C" { diff --git a/src/log/esp_utils_log.hpp b/src/log/esp_utils_log.hpp new file mode 100644 index 0000000..572d29c --- /dev/null +++ b/src/log/esp_utils_log.hpp @@ -0,0 +1,116 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include +#include +#include +#include +#include "esp_utils_log.h" + +namespace esp_utils { +namespace detail { + +// Template for string NTTP parameters +template +struct FixedString { + char data[N] {}; + + constexpr FixedString(const char (&str)[N]) + { + std::copy_n(str, N, data); + } + + constexpr bool operator==(const FixedString &) const = default; + constexpr bool operator<(const FixedString &rhs) const + { + for (size_t i = 0; i < N; ++i) { + if (data[i] != rhs.data[i]) { + return data[i] < rhs.data[i]; + } + } + return false; + } + + constexpr const char *c_str() const + { + return data; + } + constexpr size_t size() const + { + return N; + } +}; + +// Log trace RAII class +template +class log_trace_guard { +public: + log_trace_guard() + { + const char *fname = esp_utils_log_extract_file_name(file.c_str()); + printf("[D][" ESP_UTILS_LOG_TAG "][%s:%04d](%s): Enter\n", fname ? fname : "??", line, func.c_str()); + } + + explicit log_trace_guard(const void *this_ptr) + : _this_ptr(this_ptr) + { + const char *fname = esp_utils_log_extract_file_name(file.c_str()); + printf("[D][" ESP_UTILS_LOG_TAG "][%s:%04d](%s): (@%p) Enter\n", fname ? fname : "??", line, func.c_str(), _this_ptr); + } + + ~log_trace_guard() + { + const char *fname = esp_utils_log_extract_file_name(file.c_str()); + if (_this_ptr) { + printf("[D][" ESP_UTILS_LOG_TAG "][%s:%04d](%s): (@%p) Exit\n", fname ? fname : "??", line, func.c_str(), _this_ptr); + } else { + printf("[D][" ESP_UTILS_LOG_TAG "][%s:%04d](%s): Exit\n", fname ? fname : "??", line, func.c_str()); + } + } + +private: + const void *_this_ptr = nullptr; +}; + +} // namespace detail +} // namespace esp_utils + +#if ESP_UTILS_CONF_ENABLE_LOG_TRACE +// The following macros are deprecated, please use `ESP_UTILS_LOG_TRACE_GUARD()` instead +# define ESP_UTILS_LOG_TRACE_ENTER_WITH_THIS() ESP_UTILS_LOGD("(@%p) Enter", this) +# define ESP_UTILS_LOG_TRACE_EXIT_WITH_THIS() ESP_UTILS_LOGD("(@%p) Exit", this) + +# define ESP_UTILS_MAKE_FS(str) []{ constexpr esp_utils::detail::FixedString s(str); return s; }() +# define ESP_UTILS_LOG_TRACE_GUARD() \ + [[maybe_unused]] auto _log_trace_guard_ = [] { \ + using namespace esp_utils::detail; \ + constexpr auto __file = ESP_UTILS_MAKE_FS(__FILE__); \ + constexpr auto __func = ESP_UTILS_MAKE_FS(__func__); \ + std::unique_ptr> _g; \ + if constexpr (ESP_UTILS_CONF_LOG_LEVEL == ESP_UTILS_LOG_LEVEL_DEBUG) { \ + _g = std::make_unique>(); \ + } \ + return _g; \ + }() +# define ESP_UTILS_LOG_TRACE_GUARD_WITH_THIS() \ + [[maybe_unused]] auto _log_trace_guard_ = [this] { \ + using namespace esp_utils::detail; \ + constexpr auto __file = ESP_UTILS_MAKE_FS(__FILE__); \ + constexpr auto __func = ESP_UTILS_MAKE_FS(__func__); \ + std::unique_ptr> _g; \ + if constexpr (ESP_UTILS_CONF_LOG_LEVEL == ESP_UTILS_LOG_LEVEL_DEBUG) { \ + _g = std::make_unique>(this); \ + } \ + return _g; \ + }() +#else +# define ESP_UTILS_LOG_TRACE_ENTER_WITH_THIS() +# define ESP_UTILS_LOG_TRACE_EXIT_WITH_THIS() +# define ESP_UTILS_LOG_TRACE_GUARD() +# define ESP_UTILS_LOG_TRACE_GUARD_WITH_THIS() +#endif diff --git a/src/log/esp_utils_log_helper.h b/src/log/esp_utils_log_helper.h index e0f2364..1a25de4 100644 --- a/src/log/esp_utils_log_helper.h +++ b/src/log/esp_utils_log_helper.h @@ -7,6 +7,7 @@ #include "esp_utils_log.h" +#if ESP_UTILS_CONF_LOG_IMPL_TYPE != ESP_UTILS_LOG_IMPL_ESP /** * Helper macros to replace ESP-IDF logging functions */ @@ -20,3 +21,4 @@ #define ESP_LOGI(TAG, ...) { (void)TAG; ESP_UTILS_LOGI(__VA_ARGS__); } #define ESP_LOGW(TAG, ...) { (void)TAG; ESP_UTILS_LOGW(__VA_ARGS__); } #define ESP_LOGE(TAG, ...) { (void)TAG; ESP_UTILS_LOGE(__VA_ARGS__); } +#endif diff --git a/src/log/esp_utils_log.c b/src/log/impl/esp_utils_log_impl.c similarity index 93% rename from src/log/esp_utils_log.c rename to src/log/impl/esp_utils_log_impl.c index b300665..80e0b27 100644 --- a/src/log/esp_utils_log.c +++ b/src/log/impl/esp_utils_log_impl.c @@ -4,7 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ #include -#include "esp_utils_conf_internal.h" /** * @brief Extract filename from file path diff --git a/src/log/impl/esp_utils_log_impl_esp.h b/src/log/impl/esp_utils_log_impl_esp.h new file mode 100644 index 0000000..06fdc14 --- /dev/null +++ b/src/log/impl/esp_utils_log_impl_esp.h @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include "esp_log.h" + +#define ESP_UTILS_IMPL_LOGD(TAG, format, ...) ESP_LOGD(TAG, "[%s:%04d](%s): " format, \ + esp_utils_log_extract_file_name(__FILE__), __LINE__, __func__, ##__VA_ARGS__) +#define ESP_UTILS_IMPL_LOGI(TAG, format, ...) ESP_LOGI(TAG, "[%s:%04d](%s): " format, \ + esp_utils_log_extract_file_name(__FILE__), __LINE__, __func__, ##__VA_ARGS__) +#define ESP_UTILS_IMPL_LOGW(TAG, format, ...) ESP_LOGW(TAG, "[%s:%04d](%s): " format, \ + esp_utils_log_extract_file_name(__FILE__), __LINE__, __func__, ##__VA_ARGS__) +#define ESP_UTILS_IMPL_LOGE(TAG, format, ...) ESP_LOGE(TAG, "[%s:%04d](%s): " format, \ + esp_utils_log_extract_file_name(__FILE__), __LINE__, __func__, ##__VA_ARGS__) diff --git a/src/log/impl/esp_utils_log_impl_std.h b/src/log/impl/esp_utils_log_impl_std.h new file mode 100644 index 0000000..b4f8018 --- /dev/null +++ b/src/log/impl/esp_utils_log_impl_std.h @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include + +#define ESP_UTILS_IMPL_LOGD(TAG, format, ...) printf("[D][" TAG "][%s:%04d](%s): " format "\n", \ + esp_utils_log_extract_file_name(__FILE__), __LINE__, __func__, ##__VA_ARGS__) +#define ESP_UTILS_IMPL_LOGI(TAG, format, ...) printf("[I][" TAG "][%s:%04d](%s): " format "\n", \ + esp_utils_log_extract_file_name(__FILE__), __LINE__, __func__, ##__VA_ARGS__) +#define ESP_UTILS_IMPL_LOGW(TAG, format, ...) printf("[W][" TAG "][%s:%04d](%s): " format "\n", \ + esp_utils_log_extract_file_name(__FILE__), __LINE__, __func__, ##__VA_ARGS__) +#define ESP_UTILS_IMPL_LOGE(TAG, format, ...) printf("[E][" TAG "][%s:%04d](%s): " format "\n", \ + esp_utils_log_extract_file_name(__FILE__), __LINE__, __func__, ##__VA_ARGS__) diff --git a/src/more/esp_utils_more.hpp b/src/more/esp_utils_more.hpp new file mode 100644 index 0000000..97ac0ad --- /dev/null +++ b/src/more/esp_utils_more.hpp @@ -0,0 +1,72 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include + +namespace esp_utils { + +template +class value_guard { +public: + value_guard(T &value) + : ref_(value) + , origin_(value) + {} + + ~value_guard() + { + if (!is_release_) { + ref_ = origin_; + } + } + + void set(T value) + { + ref_ = value; + } + + void release() + { + is_release_ = true; + } + +private: + T &ref_; + T origin_; + bool is_release_ = false; +}; + +template +class function_guard { +public: + function_guard(T func, Args &&... args) + : func_(func) + , args_(std::forward(args)...) + {} + + ~function_guard() + { + if (!is_release_) { + std::apply([this](auto &&... args) { + func_(std::forward(args)...); + }, args_); + } + } + + void release() + { + is_release_ = true; + } + +private: + T func_; + std::tuple args_; + bool is_release_ = false; +}; + +} // namespace esp_utils diff --git a/src/thread/esp_utils_thread.cpp b/src/thread/esp_utils_thread.cpp new file mode 100644 index 0000000..2dea94a --- /dev/null +++ b/src/thread/esp_utils_thread.cpp @@ -0,0 +1,66 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "esp_pthread.h" +#include "check/esp_utils_check.h" +#include "log/esp_utils_log.hpp" +#include "esp_utils_thread.hpp" + +namespace esp_utils { + +void ThreadConfig::dump() const +{ + ESP_UTILS_LOGI( + "\n{ThreadConfig}:\n" + "\t-name(%s)\n" + "\t-core_id(%d)\n" + "\t-priority(%d)\n" + "\t-stack_size(%d)\n" +#if ESP_THREAD_CONFIG_STACK_CAPS_VALID + "\t-stack_in_ext(%s)\n" +#endif + , (name == nullptr) ? CONFIG_PTHREAD_TASK_NAME_DEFAULT : name + , core_id + , static_cast(priority) + , static_cast(stack_size) +#if ESP_THREAD_CONFIG_STACK_CAPS_VALID + , stack_in_ext ? "true" : "false" +#endif + ); +} + +thread_config_guard::thread_config_guard(const ThreadConfig &config) +{ + ESP_UTILS_LOG_TRACE_GUARD(); + + ESP_UTILS_LOGD("Param: config(%p)", &config); +#if ESP_UTILS_CONF_LOG_LEVEL == ESP_UTILS_LOG_LEVEL_DEBUG + config.dump(); +#endif + + auto new_cfg = esp_pthread_get_default_config(); + new_cfg.thread_name = config.name; + new_cfg.stack_size = config.stack_size; + new_cfg.prio = config.priority; + new_cfg.inherit_cfg = false; + new_cfg.pin_to_core = config.core_id; +#if ESP_THREAD_CONFIG_STACK_CAPS_VALID + new_cfg.stack_alloc_caps = (config.stack_in_ext ? MALLOC_CAP_SPIRAM : MALLOC_CAP_INTERNAL) | MALLOC_CAP_8BIT; +#endif + + auto err = esp_pthread_set_cfg(&new_cfg); + ESP_UTILS_CHECK_FALSE_EXIT(err == ESP_OK, "Set thread config failed(%s)", esp_err_to_name(err)); +} + +thread_config_guard::~thread_config_guard() +{ + ESP_UTILS_LOG_TRACE_GUARD(); + + auto new_cfg = esp_pthread_get_default_config(); + auto err = esp_pthread_set_cfg(&new_cfg); + ESP_UTILS_CHECK_FALSE_EXIT(err == ESP_OK, "Set thread config failed(%s)", esp_err_to_name(err)); +} + +}; // namespace esp_utils diff --git a/src/thread/esp_utils_thread.hpp b/src/thread/esp_utils_thread.hpp new file mode 100644 index 0000000..33d3d61 --- /dev/null +++ b/src/thread/esp_utils_thread.hpp @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#define ESP_THREAD_CONFIG_STACK_CAPS_VALID (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)) + +namespace esp_utils { + +struct ThreadConfig { + void dump() const; + + const char *name = nullptr; + int core_id = (CONFIG_PTHREAD_TASK_CORE_DEFAULT == -1) ? tskNO_AFFINITY : CONFIG_PTHREAD_TASK_CORE_DEFAULT; + size_t priority = CONFIG_PTHREAD_TASK_PRIO_DEFAULT; + size_t stack_size = CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT; +#if ESP_THREAD_CONFIG_STACK_CAPS_VALID + bool stack_in_ext = false; +#endif +}; + +class thread_config_guard { +public: + thread_config_guard(const ThreadConfig &config); + ~thread_config_guard(); +}; + +}; // namespace esp_utils diff --git a/test_apps/main/test_on_cpp.cpp b/test_apps/main/test_on_cpp.cpp index 1222350..0ae0a78 100644 --- a/test_apps/main/test_on_cpp.cpp +++ b/test_apps/main/test_on_cpp.cpp @@ -3,24 +3,23 @@ * * SPDX-License-Identifier: CC0-1.0 */ +#include #include #include "unity.h" #define ESP_UTILS_LOG_TAG "TestCpp" #include "esp_lib_utils.h" #include "esp_utils_helpers.h" -using namespace std; +using namespace esp_utils; TEST_CASE("Test log functions on cpp", "[utils][log][CPP]") { - ESP_UTILS_LOG_TRACE_ENTER(); + ESP_UTILS_LOG_TRACE_GUARD(); ESP_UTILS_LOGD("This is a debug message"); ESP_UTILS_LOGI("This is an info message"); ESP_UTILS_LOGW("This is a warning message"); ESP_UTILS_LOGE("This is an error message"); - - ESP_UTILS_LOG_TRACE_EXIT(); } #define MALLOC_GOOD_SIZE (1 * 1024) @@ -49,7 +48,7 @@ TEST_CASE("Test memory functions on cpp", "[utils][memory][CPP]") std::shared_ptr good_ptr = nullptr; ESP_UTILS_CHECK_EXCEPTION_GOTO( - (good_ptr = make_shared()), err, "Failed to allocate memory size: %d", + (good_ptr = std::make_shared()), err, "Failed to allocate memory size: %d", MALLOC_GOOD_SIZE ); ESP_UTILS_LOGI("Malloced value: %d", good_ptr->buffer[0]); @@ -57,7 +56,7 @@ TEST_CASE("Test memory functions on cpp", "[utils][memory][CPP]") { std::shared_ptr bad_ptr = nullptr; ESP_UTILS_CHECK_EXCEPTION_GOTO( - (bad_ptr = make_shared()), end, "Failed to allocate memory size: %d", MALLOC_BAD_SIZE + (bad_ptr = std::make_shared()), end, "Failed to allocate memory size: %d", MALLOC_BAD_SIZE ); ESP_UTILS_LOGI("Malloced value: %d", bad_ptr->buffer[0]); } @@ -186,3 +185,18 @@ TEST_CASE("Test check functions on cpp", "[utils][check][CPP]") test_check_null_exit(); TEST_ASSERT(test_check_null_exit_result); } + +TEST_CASE("Test thread functions on cpp", "[utils][thread][CPP]") +{ + thread_config_guard guard(ThreadConfig{ + .name = "test_thread", + .core_id = 0, + .priority = 5, + .stack_size = 10 * 1024, + }); + std::thread([]() { + char buffer[5 * 1024] = { 0 }; + sprintf(buffer, "Create thread"); + ESP_UTILS_LOGI("%s", buffer); + }).join(); +}