From 64bd9053a25297f7a442ca831c7da5b44bd33f84 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Wed, 12 Jun 2024 17:54:40 +1000 Subject: Update LVGL to v9.1.0 --- lib/lvgl/src/misc/lv_timer.c | 280 +++++++++++++++++++++++-------------------- 1 file changed, 149 insertions(+), 131 deletions(-) (limited to 'lib/lvgl/src/misc/lv_timer.c') diff --git a/lib/lvgl/src/misc/lv_timer.c b/lib/lvgl/src/misc/lv_timer.c index d8dd55b7..5537e591 100644 --- a/lib/lvgl/src/misc/lv_timer.c +++ b/lib/lvgl/src/misc/lv_timer.c @@ -6,18 +6,24 @@ * INCLUDES *********************/ #include "lv_timer.h" -#include "../hal/lv_hal_tick.h" +#include "../core/lv_global.h" +#include "../tick/lv_tick.h" +#include "../stdlib/lv_mem.h" +#include "../stdlib/lv_sprintf.h" #include "lv_assert.h" -#include "lv_mem.h" #include "lv_ll.h" -#include "lv_gc.h" +#include "lv_profiler.h" /********************* * DEFINES *********************/ + #define IDLE_MEAS_PERIOD 500 /*[ms]*/ #define DEF_PERIOD 500 +#define state LV_GLOBAL_DEFAULT()->timer_state +#define timer_ll_p &(state.timer_ll) + /********************** * TYPEDEFS **********************/ @@ -27,148 +33,136 @@ **********************/ static bool lv_timer_exec(lv_timer_t * timer); static uint32_t lv_timer_time_remaining(lv_timer_t * timer); +static void lv_timer_handler_resume(void); /********************** * STATIC VARIABLES **********************/ -static bool lv_timer_run = false; -static uint8_t idle_last = 0; -static bool timer_deleted; -static bool timer_created; /********************** * MACROS **********************/ -#if LV_LOG_TRACE_TIMER - #define TIMER_TRACE(...) LV_LOG_TRACE(__VA_ARGS__) +#if LV_USE_LOG && LV_LOG_TRACE_TIMER + #define LV_TRACE_TIMER(...) LV_LOG_TRACE(__VA_ARGS__) #else - #define TIMER_TRACE(...) + #define LV_TRACE_TIMER(...) #endif /********************** * GLOBAL FUNCTIONS **********************/ -/** - * Init the lv_timer module - */ void _lv_timer_core_init(void) { - _lv_ll_init(&LV_GC_ROOT(_lv_timer_ll), sizeof(lv_timer_t)); + _lv_ll_init(timer_ll_p, sizeof(lv_timer_t)); /*Initially enable the lv_timer handling*/ lv_timer_enable(true); } -/** - * Call it periodically to handle lv_timers. - * @return the time after which it must be called again - */ LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler(void) { - TIMER_TRACE("begin"); + LV_TRACE_TIMER("begin"); + lv_timer_state_t * state_p = &state; /*Avoid concurrent running of the timer handler*/ - static bool already_running = false; - if(already_running) { - TIMER_TRACE("already running, concurrent calls are not allow, returning"); + if(state_p->already_running) { + LV_TRACE_TIMER("already running, concurrent calls are not allow, returning"); return 1; } - already_running = true; + state_p->already_running = true; - if(lv_timer_run == false) { - already_running = false; /*Release mutex*/ + if(state_p->lv_timer_run == false) { + state_p->already_running = false; /*Release mutex*/ return 1; } - static uint32_t idle_period_start = 0; - static uint32_t busy_time = 0; - + LV_PROFILER_BEGIN; uint32_t handler_start = lv_tick_get(); if(handler_start == 0) { - static uint32_t run_cnt = 0; - run_cnt++; - if(run_cnt > 100) { - run_cnt = 0; + state.run_cnt++; + if(state.run_cnt > 100) { + state.run_cnt = 0; LV_LOG_WARN("It seems lv_tick_inc() is not called."); } } /*Run all timer from the list*/ lv_timer_t * next; + lv_timer_t * timer_active; + lv_ll_t * timer_head = timer_ll_p; do { - timer_deleted = false; - timer_created = false; - LV_GC_ROOT(_lv_timer_act) = _lv_ll_get_head(&LV_GC_ROOT(_lv_timer_ll)); - while(LV_GC_ROOT(_lv_timer_act)) { + state_p->timer_deleted = false; + state_p->timer_created = false; + + timer_active = _lv_ll_get_head(timer_head); + while(timer_active) { /*The timer might be deleted if it runs only once ('repeat_count = 1') *So get next element until the current is surely valid*/ - next = _lv_ll_get_next(&LV_GC_ROOT(_lv_timer_ll), LV_GC_ROOT(_lv_timer_act)); + next = _lv_ll_get_next(timer_head, timer_active); - if(lv_timer_exec(LV_GC_ROOT(_lv_timer_act))) { + if(lv_timer_exec(timer_active)) { /*If a timer was created or deleted then this or the next item might be corrupted*/ - if(timer_created || timer_deleted) { - TIMER_TRACE("Start from the first timer again because a timer was created or deleted"); + if(state_p->timer_created || state_p->timer_deleted) { + LV_TRACE_TIMER("Start from the first timer again because a timer was created or deleted"); break; } } - LV_GC_ROOT(_lv_timer_act) = next; /*Load the next timer*/ + timer_active = next; /*Load the next timer*/ } - } while(LV_GC_ROOT(_lv_timer_act)); + } while(timer_active); - uint32_t time_till_next = LV_NO_TIMER_READY; - next = _lv_ll_get_head(&LV_GC_ROOT(_lv_timer_ll)); + uint32_t time_until_next = LV_NO_TIMER_READY; + next = _lv_ll_get_head(timer_head); while(next) { if(!next->paused) { uint32_t delay = lv_timer_time_remaining(next); - if(delay < time_till_next) - time_till_next = delay; + if(delay < time_until_next) + time_until_next = delay; } - next = _lv_ll_get_next(&LV_GC_ROOT(_lv_timer_ll), next); /*Find the next timer*/ + next = _lv_ll_get_next(timer_head, next); /*Find the next timer*/ } - busy_time += lv_tick_elaps(handler_start); - uint32_t idle_period_time = lv_tick_elaps(idle_period_start); + state_p->busy_time += lv_tick_elaps(handler_start); + uint32_t idle_period_time = lv_tick_elaps(state_p->idle_period_start); if(idle_period_time >= IDLE_MEAS_PERIOD) { - idle_last = (busy_time * 100) / idle_period_time; /*Calculate the busy percentage*/ - idle_last = idle_last > 100 ? 0 : 100 - idle_last; /*But we need idle time*/ - busy_time = 0; - idle_period_start = lv_tick_get(); + state_p->idle_last = (state_p->busy_time * 100) / idle_period_time; /*Calculate the busy percentage*/ + state_p->idle_last = state_p->idle_last > 100 ? 0 : 100 - state_p->idle_last; /*But we need idle time*/ + state_p->busy_time = 0; + state_p->idle_period_start = lv_tick_get(); } - already_running = false; /*Release the mutex*/ + state_p->timer_time_until_next = time_until_next; + state_p->already_running = false; /*Release the mutex*/ - TIMER_TRACE("finished (%d ms until the next timer call)", time_till_next); - return time_till_next; + LV_TRACE_TIMER("finished (%" LV_PRIu32 " ms until the next timer call)", time_until_next); + LV_PROFILER_END; + return time_until_next; +} + +LV_ATTRIBUTE_TIMER_HANDLER void lv_timer_periodic_handler(void) +{ + lv_timer_state_t * state_p = &state; + if(lv_tick_elaps(state_p->periodic_last_tick) >= state_p->timer_time_until_next) { + LV_TRACE_TIMER("calling lv_timer_handler()"); + lv_timer_handler(); + state_p->periodic_last_tick = lv_tick_get(); + } } -/** - * Create an "empty" timer. It needs to initialized with at least - * `lv_timer_set_cb` and `lv_timer_set_period` - * @return pointer to the created timer - */ lv_timer_t * lv_timer_create_basic(void) { return lv_timer_create(NULL, DEF_PERIOD, NULL); } -/** - * Create a new lv_timer - * @param timer_xcb a callback which is the timer itself. It will be called periodically. - * (the 'x' in the argument name indicates that it's not a fully generic function because it not follows - * the `func_name(object, callback, ...)` convention) - * @param period call period in ms unit - * @param user_data custom parameter - * @return pointer to the new timer - */ lv_timer_t * lv_timer_create(lv_timer_cb_t timer_xcb, uint32_t period, void * user_data) { lv_timer_t * new_timer = NULL; - new_timer = _lv_ll_ins_head(&LV_GC_ROOT(_lv_timer_ll)); + new_timer = _lv_ll_ins_head(timer_ll_p); LV_ASSERT_MALLOC(new_timer); if(new_timer == NULL) return NULL; @@ -178,114 +172,106 @@ lv_timer_t * lv_timer_create(lv_timer_cb_t timer_xcb, uint32_t period, void * us new_timer->paused = 0; new_timer->last_run = lv_tick_get(); new_timer->user_data = user_data; + new_timer->auto_delete = true; + + state.timer_created = true; - timer_created = true; + lv_timer_handler_resume(); return new_timer; } -/** - * Set the callback the timer (the function to call periodically) - * @param timer pointer to a timer - * @param timer_cb the function to call periodically - */ void lv_timer_set_cb(lv_timer_t * timer, lv_timer_cb_t timer_cb) { + LV_ASSERT_NULL(timer); timer->timer_cb = timer_cb; } -/** - * Delete a lv_timer - * @param timer pointer to timer created by timer - */ -void lv_timer_del(lv_timer_t * timer) +void lv_timer_delete(lv_timer_t * timer) { - _lv_ll_remove(&LV_GC_ROOT(_lv_timer_ll), timer); - timer_deleted = true; + _lv_ll_remove(timer_ll_p, timer); + state.timer_deleted = true; - lv_mem_free(timer); + lv_free(timer); } -/** - * Pause/resume a timer. - * @param timer pointer to an lv_timer - */ void lv_timer_pause(lv_timer_t * timer) { + LV_ASSERT_NULL(timer); timer->paused = true; } void lv_timer_resume(lv_timer_t * timer) { + LV_ASSERT_NULL(timer); timer->paused = false; + lv_timer_handler_resume(); } -/** - * Set new period for a lv_timer - * @param timer pointer to a lv_timer - * @param period the new period - */ void lv_timer_set_period(lv_timer_t * timer, uint32_t period) { + LV_ASSERT_NULL(timer); timer->period = period; } -/** - * Make a lv_timer ready. It will not wait its period. - * @param timer pointer to a lv_timer. - */ void lv_timer_ready(lv_timer_t * timer) { + LV_ASSERT_NULL(timer); timer->last_run = lv_tick_get() - timer->period - 1; } -/** - * Set the number of times a timer will repeat. - * @param timer pointer to a lv_timer. - * @param repeat_count -1 : infinity; 0 : stop ; n >0: residual times - */ void lv_timer_set_repeat_count(lv_timer_t * timer, int32_t repeat_count) { + LV_ASSERT_NULL(timer); timer->repeat_count = repeat_count; } -/** - * Reset a lv_timer. - * It will be called the previously set period milliseconds later. - * @param timer pointer to a lv_timer. - */ +void lv_timer_set_auto_delete(lv_timer_t * timer, bool auto_delete) +{ + LV_ASSERT_NULL(timer); + timer->auto_delete = auto_delete; +} + +void lv_timer_set_user_data(lv_timer_t * timer, void * user_data) +{ + LV_ASSERT_NULL(timer); + timer->user_data = user_data; +} + void lv_timer_reset(lv_timer_t * timer) { + LV_ASSERT_NULL(timer); timer->last_run = lv_tick_get(); + lv_timer_handler_resume(); } -/** - * Enable or disable the whole lv_timer handling - * @param en true: lv_timer handling is running, false: lv_timer handling is suspended - */ void lv_timer_enable(bool en) { - lv_timer_run = en; + state.lv_timer_run = en; + if(en) lv_timer_handler_resume(); } -/** - * Get idle percentage - * @return the lv_timer idle in percentage - */ -uint8_t lv_timer_get_idle(void) +void _lv_timer_core_deinit(void) { - return idle_last; + lv_timer_enable(false); + + _lv_ll_clear(timer_ll_p); +} + +uint32_t lv_timer_get_idle(void) +{ + return state.idle_last; +} + +uint32_t lv_timer_get_time_until_next(void) +{ + return state.timer_time_until_next; } -/** - * Iterate through the timers - * @param timer NULL to start iteration or the previous return value to get the next timer - * @return the next timer or NULL if there is no more timer - */ lv_timer_t * lv_timer_get_next(lv_timer_t * timer) { - if(timer == NULL) return _lv_ll_get_head(&LV_GC_ROOT(_lv_timer_ll)); - else return _lv_ll_get_next(&LV_GC_ROOT(_lv_timer_ll), timer); + if(timer == NULL) return _lv_ll_get_head(timer_ll_p); + else return _lv_ll_get_next(timer_ll_p, timer); } /********************** @@ -309,17 +295,31 @@ static bool lv_timer_exec(lv_timer_t * timer) int32_t original_repeat_count = timer->repeat_count; if(timer->repeat_count > 0) timer->repeat_count--; timer->last_run = lv_tick_get(); - TIMER_TRACE("calling timer callback: %p", *((void **)&timer->timer_cb)); + LV_TRACE_TIMER("calling timer callback: %p", *((void **)&timer->timer_cb)); + if(timer->timer_cb && original_repeat_count != 0) timer->timer_cb(timer); - TIMER_TRACE("timer callback %p finished", *((void **)&timer->timer_cb)); + + if(!state.timer_deleted) { + LV_TRACE_TIMER("timer callback %p finished", *((void **)&timer->timer_cb)); + } + else { + LV_TRACE_TIMER("timer callback finished"); + } + LV_ASSERT_MEM_INTEGRITY(); exec = true; } - if(timer_deleted == false) { /*The timer might be deleted by itself as well*/ + if(state.timer_deleted == false) { /*The timer might be deleted by itself as well*/ if(timer->repeat_count == 0) { /*The repeat count is over, delete the timer*/ - TIMER_TRACE("deleting timer with %p callback because the repeat count is over", *((void **)&timer->timer_cb)); - lv_timer_del(timer); + if(timer->auto_delete) { + LV_TRACE_TIMER("deleting timer with %p callback because the repeat count is over", *((void **)&timer->timer_cb)); + lv_timer_delete(timer); + } + else { + LV_TRACE_TIMER("pausing timer with %p callback because the repeat count is over", *((void **)&timer->timer_cb)); + lv_timer_pause(timer); + } } } @@ -339,3 +339,21 @@ static uint32_t lv_timer_time_remaining(lv_timer_t * timer) return 0; return timer->period - elp; } + +/** + * Call the ready lv_timer + */ +static void lv_timer_handler_resume(void) +{ + /*If there is a timer which is ready to run then resume the timer loop*/ + state.timer_time_until_next = 0; + if(state.resume_cb) { + state.resume_cb(state.resume_data); + } +} + +void lv_timer_handler_set_resume_cb(lv_timer_handler_resume_cb_t cb, void * data) +{ + state.resume_cb = cb; + state.resume_data = data; +} -- cgit v1.2.3