summaryrefslogtreecommitdiff
path: root/lib/lvgl/src/misc/lv_timer.c
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-06-12 17:54:40 +1000
committerjacqueline <me@jacqueline.id.au>2024-06-12 17:54:40 +1000
commit64bd9053a25297f7a442ca831c7da5b44bd33f84 (patch)
treea90c6cad25a12028302ab1a5334510fba0229bae /lib/lvgl/src/misc/lv_timer.c
parent611176ed667c4ed7ee9f609e958f9404f4aee91d (diff)
downloadtangara-fw-64bd9053a25297f7a442ca831c7da5b44bd33f84.tar.gz
Update LVGL to v9.1.0
Diffstat (limited to 'lib/lvgl/src/misc/lv_timer.c')
-rw-r--r--lib/lvgl/src/misc/lv_timer.c280
1 files changed, 149 insertions, 131 deletions
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;
+}