mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-27 11:57:48 +08:00
feat(freertos): allow overriding idle percentage calculation (#9647)
This commit is contained in:
@@ -162,6 +162,15 @@ menu "LVGL configuration"
|
|||||||
Unblocking an RTOS task with a direct notification is 45% faster and uses less RAM
|
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.
|
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.
|
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
|
endmenu
|
||||||
|
|
||||||
menu "Rendering Configuration"
|
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_IN() lv_freertos_task_switch_in(pxCurrentTCB->pcTaskName);
|
||||||
#define traceTASK_SWITCHED_OUT() lv_freertos_task_switch_out();
|
#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.
|
* 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
|
#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
|
#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.
|
* 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
|
#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
|
#endif
|
||||||
|
|
||||||
/*========================
|
/*========================
|
||||||
|
|||||||
@@ -312,6 +312,15 @@
|
|||||||
#define LV_USE_FREERTOS_TASK_NOTIFY 1
|
#define LV_USE_FREERTOS_TASK_NOTIFY 1
|
||||||
#endif
|
#endif
|
||||||
#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
|
#endif
|
||||||
|
|
||||||
/*========================
|
/*========================
|
||||||
|
|||||||
@@ -403,6 +403,7 @@ void lv_freertos_task_switch_out(void)
|
|||||||
else globals->freertos_non_idle_time_sum += elaps;
|
else globals->freertos_non_idle_time_sum += elaps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LV_OS_IDLE_PERCENT_CUSTOM == 0
|
||||||
uint32_t lv_os_get_idle_percent(void)
|
uint32_t lv_os_get_idle_percent(void)
|
||||||
{
|
{
|
||||||
if(globals->freertos_non_idle_time_sum + globals->freertos_idle_time_sum == 0) {
|
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;
|
return pct;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void lv_sleep_ms(uint32_t ms)
|
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.
|
* 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
|
#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
|
* RENDERING CONFIGURATION
|
||||||
*========================*/
|
*========================*/
|
||||||
|
|||||||
Reference in New Issue
Block a user