mirror of
https://github.com/lvgl/lvgl.git
synced 2026-03-23 14:03:13 +08:00
feat(freertos): allow overriding idle percentage calculation (#9647)
This commit is contained in:
9
Kconfig
9
Kconfig
@@ -162,6 +162,15 @@ menu "LVGL configuration"
|
||||
Unblocking an RTOS task with a direct notification is 45% faster and uses less RAM
|
||||
than unblocking a task using an intermediary object such as a binary semaphore.
|
||||
RTOS task notifications can only be used when there is only one task that can be the recipient of the event.
|
||||
config LV_OS_IDLE_PERCENT_CUSTOM
|
||||
bool "Custom idle percentage calculation"
|
||||
default n
|
||||
depends on LV_OS_FREERTOS
|
||||
help
|
||||
Enable this to provide a custom implementation of lv_os_get_idle_percent.
|
||||
This is useful for multi-core systems where the default
|
||||
FreeRTOS implementation might not sufficiently track idle time across all cores.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Rendering Configuration"
|
||||
|
||||
@@ -31,3 +31,67 @@ the idle function. To enable this, the following needs to be added in
|
||||
|
||||
#define traceTASK_SWITCHED_IN() lv_freertos_task_switch_in(pxCurrentTCB->pcTaskName);
|
||||
#define traceTASK_SWITCHED_OUT() lv_freertos_task_switch_out();
|
||||
|
||||
Alternatively, on multi-core environments (like the ESP32 SMP), this default
|
||||
implementation can be insufficient or inaccurate. In this case, you can set
|
||||
``LV_OS_IDLE_PERCENT_CUSTOM`` to ``1`` in ``lv_conf.h`` to disable the default
|
||||
implementation. Then, you can provide a custom implementation of
|
||||
:cpp:expr:`lv_os_get_idle_percent` tailored to your environment
|
||||
(e.g., using ``uxTaskGetSystemState()``) without modifying LVGL source files.
|
||||
|
||||
Example: Custom implementation for ESP32 SMP
|
||||
********************************************
|
||||
|
||||
For multi-core environments like the ESP32 (which uses dual-core SMP), the default
|
||||
implementation might not track all idle tasks. Below is an example of a custom
|
||||
implementation using ``uxTaskGetSystemState()``. This requires
|
||||
``configGENERATE_RUN_TIME_STATS`` and ``configUSE_TRACE_FACILITY`` to be enabled
|
||||
in your ``FreeRTOSConfig.h`` (or via menuconfig for ESP-IDF).
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include <string.h>
|
||||
|
||||
uint32_t lv_os_get_idle_percent(void) {
|
||||
static uint32_t last_idle_time = 0;
|
||||
static uint32_t last_total_time = 0;
|
||||
|
||||
uint32_t ulTotalRunTime;
|
||||
uint32_t ulIdleTime = 0;
|
||||
|
||||
TaskStatus_t *pxTaskStatusArray;
|
||||
UBaseType_t uxArraySize, x;
|
||||
|
||||
uxArraySize = uxTaskGetNumberOfTasks();
|
||||
pxTaskStatusArray = pvPortMalloc(uxArraySize * sizeof(TaskStatus_t));
|
||||
|
||||
if (pxTaskStatusArray == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uxArraySize = uxTaskGetSystemState(pxTaskStatusArray, uxArraySize, &ulTotalRunTime);
|
||||
for (x = 0; x < uxArraySize; x++) {
|
||||
/* ESP32 has IDLE0 and IDLE1 tasks */
|
||||
if (strcmp(pxTaskStatusArray[x].pcTaskName, "IDLE0") == 0 ||
|
||||
strcmp(pxTaskStatusArray[x].pcTaskName, "IDLE1") == 0) {
|
||||
ulIdleTime += pxTaskStatusArray[x].ulRunTimeCounter;
|
||||
}
|
||||
}
|
||||
vPortFree(pxTaskStatusArray);
|
||||
|
||||
uint32_t idle_diff = ulIdleTime - last_idle_time;
|
||||
uint32_t total_diff = ulTotalRunTime - last_total_time;
|
||||
|
||||
last_idle_time = ulIdleTime;
|
||||
last_total_time = ulTotalRunTime;
|
||||
|
||||
if (total_diff == 0) return 0;
|
||||
|
||||
/* Combined idle percentage across both cores (0-200 on dual-core) */
|
||||
uint32_t idle_pct = (idle_diff * 100) / total_diff;
|
||||
|
||||
/* For Sysmon, we usually want average load across all cores (0-100) */
|
||||
return idle_pct / 2; /* Adjust divisor based on your CPU core count */
|
||||
}
|
||||
|
||||
@@ -127,6 +127,9 @@
|
||||
* RTOS task notifications can only be used when there is only one task that can be the recipient of the event.
|
||||
*/
|
||||
#define LV_USE_FREERTOS_TASK_NOTIFY 1
|
||||
|
||||
/* Enable this to provide a custom implementation of lv_os_get_idle_percent. */
|
||||
#define LV_OS_IDLE_PERCENT_CUSTOM 0
|
||||
#endif
|
||||
|
||||
/*========================
|
||||
|
||||
@@ -119,6 +119,9 @@
|
||||
* RTOS task notifications can only be used when there is only one task that can be the recipient of the event.
|
||||
*/
|
||||
#define LV_USE_FREERTOS_TASK_NOTIFY 1
|
||||
|
||||
/* Enable this to provide a custom implementation of lv_os_get_idle_percent. */
|
||||
#define LV_OS_IDLE_PERCENT_CUSTOM 0
|
||||
#endif
|
||||
|
||||
/*========================
|
||||
|
||||
@@ -312,6 +312,15 @@
|
||||
#define LV_USE_FREERTOS_TASK_NOTIFY 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Enable this to provide a custom implementation of lv_os_get_idle_percent. */
|
||||
#ifndef LV_OS_IDLE_PERCENT_CUSTOM
|
||||
#ifdef CONFIG_LV_OS_IDLE_PERCENT_CUSTOM
|
||||
#define LV_OS_IDLE_PERCENT_CUSTOM CONFIG_LV_OS_IDLE_PERCENT_CUSTOM
|
||||
#else
|
||||
#define LV_OS_IDLE_PERCENT_CUSTOM 0
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*========================
|
||||
|
||||
@@ -403,6 +403,7 @@ void lv_freertos_task_switch_out(void)
|
||||
else globals->freertos_non_idle_time_sum += elaps;
|
||||
}
|
||||
|
||||
#if LV_OS_IDLE_PERCENT_CUSTOM == 0
|
||||
uint32_t lv_os_get_idle_percent(void)
|
||||
{
|
||||
if(globals->freertos_non_idle_time_sum + globals->freertos_idle_time_sum == 0) {
|
||||
@@ -418,6 +419,7 @@ uint32_t lv_os_get_idle_percent(void)
|
||||
|
||||
return pct;
|
||||
}
|
||||
#endif
|
||||
|
||||
void lv_sleep_ms(uint32_t ms)
|
||||
{
|
||||
|
||||
@@ -121,8 +121,10 @@
|
||||
* RTOS task notifications can only be used when there is only one task that can be the recipient of the event.
|
||||
*/
|
||||
#define LV_USE_FREERTOS_TASK_NOTIFY 1
|
||||
#endif
|
||||
|
||||
/* Enable this to provide a custom implementation of lv_os_get_idle_percent. */
|
||||
#define LV_OS_IDLE_PERCENT_CUSTOM 0
|
||||
#endif
|
||||
/*========================
|
||||
* RENDERING CONFIGURATION
|
||||
*========================*/
|
||||
|
||||
Reference in New Issue
Block a user