diff --git a/Kconfig b/Kconfig index 23a36d67c4..0bf17500ad 100644 --- a/Kconfig +++ b/Kconfig @@ -1619,6 +1619,10 @@ menu "LVGL configuration" bool "Enable built-in profiler by default" depends on LV_USE_PROFILER_BUILTIN default y + config LV_USE_PROFILER_BUILTIN_POSIX + bool "Enable POSIX profiler port" + depends on LV_USE_PROFILER_BUILTIN + default n config LV_PROFILER_INCLUDE string "Header to include for the profiler" default "lvgl/src/misc/lv_profiler_builtin.h" diff --git a/docs/src/details/debugging/profiler.rst b/docs/src/details/debugging/profiler.rst index cb69b330a6..363525311c 100644 --- a/docs/src/details/debugging/profiler.rst +++ b/docs/src/details/debugging/profiler.rst @@ -32,51 +32,12 @@ Configure profiler To enable the profiler, set :c:macro:`LV_USE_PROFILER` in ``lv_conf.h`` and configure the following options: -1. Enable the built-in profiler functionality by setting :c:macro:`LV_USE_PROFILER_BUILTIN`. +1. Enable the built-in profiler functionality by setting :c:macro:`LV_USE_PROFILER_BUILTIN`. If you have POSIX environment support, you can enable :c:macro:`LV_USE_PROFILER_BUILTIN_POSIX`. 2. Buffer configuration: Set the value of :c:macro:`LV_PROFILER_BUILTIN_BUF_SIZE` to configure the buffer size. A larger buffer can store more trace event information, reducing interference with rendering. However, it also results in higher memory consumption. 3. Timestamp configuration: LVGL uses the :cpp:func:`lv_tick_get` function with a precision of 1ms by default to obtain timestamps when events occur. Therefore, it cannot accurately measure intervals below 1ms. If your system environment can provide higher precision (e.g., 1us), you can configure the profiler as follows: -- Recommended configuration in **UNIX** environments: - - .. code-block:: c - - #include - #include - #include - #include - - static uint64_t my_get_tick_cb(void) - { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return ts.tv_sec * 1000000000 + ts.tv_nsec; - } - - static int my_get_tid_cb(void) - { - return (int)syscall(SYS_gettid); - } - - static int my_get_cpu_cb(void) - { - int cpu_id = 0; - syscall(SYS_getcpu, &cpu_id, NULL); - return cpu_id; - } - - void my_profiler_init(void) - { - lv_profiler_builtin_config_t config; - lv_profiler_builtin_config_init(&config); - config.tick_per_sec = 1000000000; /* One second is equal to 1000000000 nanoseconds */ - config.tick_get_cb = my_get_tick_cb; - config.tid_get_cb = my_get_tid_cb; - config.cpu_get_cb = my_get_cpu_cb; - lv_profiler_builtin_init(&config); - } - - Recommended configuration in **Arduino** environments: .. code-block:: c diff --git a/lv_conf_template.h b/lv_conf_template.h index 0e8b27fda9..0b1d0ef57e 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -1094,6 +1094,7 @@ /** Default profiler trace buffer size */ #define LV_PROFILER_BUILTIN_BUF_SIZE (16 * 1024) /**< [bytes] */ #define LV_PROFILER_BUILTIN_DEFAULT_ENABLE 1 + #define LV_USE_PROFILER_BUILTIN_POSIX 0 /**< Enable POSIX profiler port */ #endif /** Header to include for profiler */ diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index 8b31cd19c3..f2cfd85c15 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -3445,6 +3445,13 @@ #define LV_PROFILER_BUILTIN_DEFAULT_ENABLE 1 #endif #endif + #ifndef LV_USE_PROFILER_BUILTIN_POSIX + #ifdef CONFIG_LV_USE_PROFILER_BUILTIN_POSIX + #define LV_USE_PROFILER_BUILTIN_POSIX CONFIG_LV_USE_PROFILER_BUILTIN_POSIX + #else + #define LV_USE_PROFILER_BUILTIN_POSIX 0 /**< Enable POSIX profiler port */ + #endif + #endif #endif /** Header to include for profiler */ diff --git a/src/lv_init.c b/src/lv_init.c index ed580d71ae..2afbacb098 100644 --- a/src/lv_init.c +++ b/src/lv_init.c @@ -203,9 +203,13 @@ void lv_init(void) #endif #if LV_USE_PROFILER && LV_USE_PROFILER_BUILTIN +#if LV_USE_PROFILER_BUILTIN_POSIX + lv_profiler_builtin_posix_init(); +#else lv_profiler_builtin_config_t profiler_config; lv_profiler_builtin_config_init(&profiler_config); lv_profiler_builtin_init(&profiler_config); +#endif #endif lv_os_init(); diff --git a/src/misc/lv_profiler_builtin_posix.c b/src/misc/lv_profiler_builtin_posix.c new file mode 100644 index 0000000000..ca695d384a --- /dev/null +++ b/src/misc/lv_profiler_builtin_posix.c @@ -0,0 +1,134 @@ +/** + * @file lv_profiler_builtin_posix.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_profiler_builtin_private.h" + +#if LV_USE_PROFILER && LV_USE_PROFILER_BUILTIN && LV_USE_PROFILER_BUILTIN_POSIX + +#if defined(_WIN32) + #include +#else + #include +#endif + +#include +#include + +#if defined(__linux__) + #include + #include + #include +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +static uint64_t tick_get_cb(void); +static void flush_cb(const char * buf); +static int tid_get_cb(void); +static int cpu_get_cb(void); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_profiler_builtin_posix_init(void) +{ + lv_profiler_builtin_config_t config; + lv_profiler_builtin_config_init(&config); + + /* One second is equal to 1000000000 nanoseconds */ + config.tick_per_sec = 1000000000; + config.tick_get_cb = tick_get_cb; + config.flush_cb = flush_cb; + config.tid_get_cb = tid_get_cb; + config.cpu_get_cb = cpu_get_cb; + lv_profiler_builtin_init(&config); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static uint64_t tick_get_cb(void) +{ +#if defined(_WIN32) + static LARGE_INTEGER frequency = {0}; + LARGE_INTEGER counter; + + if(frequency.QuadPart == 0) { + if(!QueryPerformanceFrequency(&frequency)) { + fprintf(stderr, "QueryPerformanceFrequency failed\n"); + return 0; + } + } + + if(!QueryPerformanceCounter(&counter)) { + fprintf(stderr, "QueryPerformanceCounter failed\n"); + return 0; + } + + /* Convert counter to nanoseconds */ + return counter.QuadPart * 1000000000ULL / frequency.QuadPart; +#else + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (uint64_t)ts.tv_sec * 1000000000ULL + (uint64_t)ts.tv_nsec; +#endif +} + +static void flush_cb(const char * buf) +{ + printf("%s", buf); +} + +static int tid_get_cb(void) +{ +#if defined(__linux__) + return (int)syscall(SYS_gettid); +#elif defined(_WIN32) + return (int)GetCurrentThreadId(); +#else + return (int)pthread_self(); +#endif +} + +static int cpu_get_cb(void) +{ +#if defined(__linux__) + unsigned cpu; + int result = syscall(SYS_getcpu, &cpu, NULL, NULL); + if(result < 0) { + fprintf(stderr, "getcpu failed\n"); + return -1; + } + return (int)cpu; +#else + return 0; +#endif +} + +#endif diff --git a/src/misc/lv_profiler_builtin_private.h b/src/misc/lv_profiler_builtin_private.h index 48bfc39dae..92c424cebd 100644 --- a/src/misc/lv_profiler_builtin_private.h +++ b/src/misc/lv_profiler_builtin_private.h @@ -43,6 +43,15 @@ struct _lv_profiler_builtin_config_t { * GLOBAL PROTOTYPES **********************/ +#if LV_USE_PROFILER_BUILTIN_POSIX + +/** + * Initialize the built-in profiler with POSIX functions. + */ +void lv_profiler_builtin_posix_init(void); + +#endif /* LV_USE_PROFILER_BUILTIN_POSIX */ + /********************** * MACROS **********************/ diff --git a/tests/src/lv_test_conf_full.h b/tests/src/lv_test_conf_full.h index dceca783f9..f72c27be9e 100644 --- a/tests/src/lv_test_conf_full.h +++ b/tests/src/lv_test_conf_full.h @@ -108,6 +108,7 @@ #define LV_USE_SVG_DEBUG 1 #define LV_USE_PROFILER 1 #define LV_PROFILER_INCLUDE "lv_profiler_builtin.h" +#define LV_USE_PROFILER_BUILTIN_POSIX 1 #define LV_USE_GRIDNAV 1 #define LV_USE_XML 1 #define LV_USE_TRANSLATION 1