1 /**
2  * @file lv_timer.c
3  */
4 
5 /*********************
6  *      INCLUDES
7  *********************/
8 #include "lv_timer_private.h"
9 #include "../core/lv_global.h"
10 #include "../tick/lv_tick.h"
11 #include "../stdlib/lv_mem.h"
12 #include "../stdlib/lv_sprintf.h"
13 #include "lv_assert.h"
14 #include "lv_ll.h"
15 #include "lv_profiler.h"
16 
17 /*********************
18  *      DEFINES
19  *********************/
20 
21 #define IDLE_MEAS_PERIOD 500 /*[ms]*/
22 #define DEF_PERIOD 500
23 
24 #define state LV_GLOBAL_DEFAULT()->timer_state
25 #define timer_ll_p &(state.timer_ll)
26 
27 /**********************
28  *      TYPEDEFS
29  **********************/
30 
31 /**********************
32  *  STATIC PROTOTYPES
33  **********************/
34 static bool lv_timer_exec(lv_timer_t * timer);
35 static uint32_t lv_timer_time_remaining(lv_timer_t * timer);
36 static void lv_timer_handler_resume(void);
37 
38 /**********************
39  *  STATIC VARIABLES
40  **********************/
41 
42 /**********************
43  *      MACROS
44  **********************/
45 #if LV_USE_LOG && LV_LOG_TRACE_TIMER
46     #define LV_TRACE_TIMER(...) LV_LOG_TRACE(__VA_ARGS__)
47 #else
48     #define LV_TRACE_TIMER(...)
49 #endif
50 
51 /**********************
52  *   GLOBAL FUNCTIONS
53  **********************/
54 
lv_timer_core_init(void)55 void lv_timer_core_init(void)
56 {
57     lv_ll_init(timer_ll_p, sizeof(lv_timer_t));
58 
59     /*Initially enable the lv_timer handling*/
60     lv_timer_enable(true);
61 }
62 
lv_timer_handler(void)63 LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler(void)
64 {
65     LV_TRACE_TIMER("begin");
66 
67     lv_timer_state_t * state_p = &state;
68     /*Avoid concurrent running of the timer handler*/
69     if(state_p->already_running) {
70         LV_TRACE_TIMER("already running, concurrent calls are not allow, returning");
71         return 1;
72     }
73     state_p->already_running = true;
74 
75     if(state_p->lv_timer_run == false) {
76         state_p->already_running = false; /*Release mutex*/
77         return 1;
78     }
79 
80     LV_PROFILER_TIMER_BEGIN;
81     lv_lock();
82 
83     uint32_t handler_start = lv_tick_get();
84 
85     if(handler_start == 0) {
86         state.run_cnt++;
87         if(state.run_cnt > 100) {
88             state.run_cnt = 0;
89             LV_LOG_WARN("It seems lv_tick_inc() is not called.");
90         }
91     }
92 
93     /*Run all timer from the list*/
94     lv_timer_t * next;
95     lv_timer_t * timer_active;
96     lv_ll_t * timer_head = timer_ll_p;
97     do {
98         state_p->timer_deleted             = false;
99         state_p->timer_created             = false;
100 
101         timer_active = lv_ll_get_head(timer_head);
102         while(timer_active) {
103             /*The timer might be deleted if it runs only once ('repeat_count = 1')
104              *So get next element until the current is surely valid*/
105             next = lv_ll_get_next(timer_head, timer_active);
106 
107             if(lv_timer_exec(timer_active)) {
108                 /*If a timer was created or deleted then this or the next item might be corrupted*/
109                 if(state_p->timer_created || state_p->timer_deleted) {
110                     LV_TRACE_TIMER("Start from the first timer again because a timer was created or deleted");
111                     break;
112                 }
113             }
114 
115             timer_active = next; /*Load the next timer*/
116         }
117     } while(timer_active);
118 
119     uint32_t time_until_next = LV_NO_TIMER_READY;
120     next = lv_ll_get_head(timer_head);
121     while(next) {
122         if(!next->paused) {
123             uint32_t delay = lv_timer_time_remaining(next);
124             if(delay < time_until_next)
125                 time_until_next = delay;
126         }
127 
128         next = lv_ll_get_next(timer_head, next); /*Find the next timer*/
129     }
130 
131     state_p->busy_time += lv_tick_elaps(handler_start);
132     uint32_t idle_period_time = lv_tick_elaps(state_p->idle_period_start);
133     if(idle_period_time >= IDLE_MEAS_PERIOD) {
134         state_p->idle_last         = (state_p->busy_time * 100) / idle_period_time;  /*Calculate the busy percentage*/
135         state_p->idle_last         = state_p->idle_last > 100 ? 0 : 100 - state_p->idle_last; /*But we need idle time*/
136         state_p->busy_time         = 0;
137         state_p->idle_period_start = lv_tick_get();
138     }
139 
140     state_p->timer_time_until_next = time_until_next;
141     state_p->already_running = false; /*Release the mutex*/
142 
143     LV_TRACE_TIMER("finished (%" LV_PRIu32 " ms until the next timer call)", time_until_next);
144     lv_unlock();
145 
146     LV_PROFILER_TIMER_END;
147     return time_until_next;
148 }
149 
lv_timer_periodic_handler(void)150 LV_ATTRIBUTE_TIMER_HANDLER void lv_timer_periodic_handler(void)
151 {
152     lv_timer_state_t * state_p = &state;
153     if(lv_tick_elaps(state_p->periodic_last_tick) >= state_p->timer_time_until_next) {
154         LV_TRACE_TIMER("calling lv_timer_handler()");
155         lv_timer_handler();
156         state_p->periodic_last_tick = lv_tick_get();
157     }
158 }
159 
lv_timer_create_basic(void)160 lv_timer_t * lv_timer_create_basic(void)
161 {
162     return lv_timer_create(NULL, DEF_PERIOD, NULL);
163 }
164 
lv_timer_create(lv_timer_cb_t timer_xcb,uint32_t period,void * user_data)165 lv_timer_t * lv_timer_create(lv_timer_cb_t timer_xcb, uint32_t period, void * user_data)
166 {
167     lv_timer_t * new_timer = NULL;
168 
169     new_timer = lv_ll_ins_head(timer_ll_p);
170     LV_ASSERT_MALLOC(new_timer);
171     if(new_timer == NULL) return NULL;
172 
173     new_timer->period = period;
174     new_timer->timer_cb = timer_xcb;
175     new_timer->repeat_count = -1;
176     new_timer->paused = 0;
177     new_timer->last_run = lv_tick_get();
178     new_timer->user_data = user_data;
179     new_timer->auto_delete = true;
180 
181     state.timer_created = true;
182 
183     lv_timer_handler_resume();
184 
185     return new_timer;
186 }
187 
lv_timer_set_cb(lv_timer_t * timer,lv_timer_cb_t timer_cb)188 void lv_timer_set_cb(lv_timer_t * timer, lv_timer_cb_t timer_cb)
189 {
190     LV_ASSERT_NULL(timer);
191     timer->timer_cb = timer_cb;
192 }
193 
lv_timer_delete(lv_timer_t * timer)194 void lv_timer_delete(lv_timer_t * timer)
195 {
196     lv_ll_remove(timer_ll_p, timer);
197     state.timer_deleted = true;
198 
199     lv_free(timer);
200 }
201 
lv_timer_pause(lv_timer_t * timer)202 void lv_timer_pause(lv_timer_t * timer)
203 {
204     LV_ASSERT_NULL(timer);
205     timer->paused = true;
206 }
207 
lv_timer_resume(lv_timer_t * timer)208 void lv_timer_resume(lv_timer_t * timer)
209 {
210     LV_ASSERT_NULL(timer);
211     timer->paused = false;
212     lv_timer_handler_resume();
213 }
214 
lv_timer_set_period(lv_timer_t * timer,uint32_t period)215 void lv_timer_set_period(lv_timer_t * timer, uint32_t period)
216 {
217     LV_ASSERT_NULL(timer);
218     timer->period = period;
219 }
220 
lv_timer_ready(lv_timer_t * timer)221 void lv_timer_ready(lv_timer_t * timer)
222 {
223     LV_ASSERT_NULL(timer);
224     timer->last_run = lv_tick_get() - timer->period - 1;
225 }
226 
lv_timer_set_repeat_count(lv_timer_t * timer,int32_t repeat_count)227 void lv_timer_set_repeat_count(lv_timer_t * timer, int32_t repeat_count)
228 {
229     LV_ASSERT_NULL(timer);
230     timer->repeat_count = repeat_count;
231 }
232 
lv_timer_set_auto_delete(lv_timer_t * timer,bool auto_delete)233 void lv_timer_set_auto_delete(lv_timer_t * timer, bool auto_delete)
234 {
235     LV_ASSERT_NULL(timer);
236     timer->auto_delete = auto_delete;
237 }
238 
lv_timer_set_user_data(lv_timer_t * timer,void * user_data)239 void lv_timer_set_user_data(lv_timer_t * timer, void * user_data)
240 {
241     LV_ASSERT_NULL(timer);
242     timer->user_data = user_data;
243 }
244 
lv_timer_reset(lv_timer_t * timer)245 void lv_timer_reset(lv_timer_t * timer)
246 {
247     LV_ASSERT_NULL(timer);
248     timer->last_run = lv_tick_get();
249     lv_timer_handler_resume();
250 }
251 
lv_timer_enable(bool en)252 void lv_timer_enable(bool en)
253 {
254     state.lv_timer_run = en;
255     if(en) lv_timer_handler_resume();
256 }
257 
lv_timer_core_deinit(void)258 void lv_timer_core_deinit(void)
259 {
260     lv_timer_enable(false);
261 
262     lv_ll_clear(timer_ll_p);
263 }
264 
lv_timer_get_idle(void)265 uint32_t lv_timer_get_idle(void)
266 {
267     return state.idle_last;
268 }
269 
lv_timer_get_time_until_next(void)270 uint32_t lv_timer_get_time_until_next(void)
271 {
272     return state.timer_time_until_next;
273 }
274 
lv_timer_get_next(lv_timer_t * timer)275 lv_timer_t * lv_timer_get_next(lv_timer_t * timer)
276 {
277     if(timer == NULL) return lv_ll_get_head(timer_ll_p);
278     else return lv_ll_get_next(timer_ll_p, timer);
279 }
280 
lv_timer_handler_run_in_period(uint32_t period)281 LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler_run_in_period(uint32_t period)
282 {
283     static uint32_t last_tick = 0;
284 
285     if(lv_tick_elaps(last_tick) >= period) {
286         last_tick = lv_tick_get();
287         return lv_timer_handler();
288     }
289     return 1;
290 }
291 
lv_timer_get_user_data(lv_timer_t * timer)292 void * lv_timer_get_user_data(lv_timer_t * timer)
293 {
294     return timer->user_data;
295 }
296 
lv_timer_get_paused(lv_timer_t * timer)297 bool lv_timer_get_paused(lv_timer_t * timer)
298 {
299     return timer->paused;
300 }
301 
302 /**********************
303  *   STATIC FUNCTIONS
304  **********************/
305 
306 /**
307  * Execute timer if its remaining time is zero
308  * @param timer pointer to lv_timer
309  * @return true: execute, false: not executed
310  */
lv_timer_exec(lv_timer_t * timer)311 static bool lv_timer_exec(lv_timer_t * timer)
312 {
313     if(timer->paused) return false;
314 
315     bool exec = false;
316     if(lv_timer_time_remaining(timer) == 0) {
317         /* Decrement the repeat count before executing the timer_cb.
318          * If any timer is deleted `if(timer->repeat_count == 0)` is not executed below
319          * but at least the repeat count is zero and the timer can be deleted in the next round*/
320         int32_t original_repeat_count = timer->repeat_count;
321         if(timer->repeat_count > 0) timer->repeat_count--;
322         timer->last_run = lv_tick_get();
323         LV_TRACE_TIMER("calling timer callback: %p", *((void **)&timer->timer_cb));
324 
325         if(timer->timer_cb && original_repeat_count != 0) {
326             LV_PROFILER_TIMER_BEGIN_TAG("timer_cb");
327             timer->timer_cb(timer);
328             LV_PROFILER_TIMER_END_TAG("timer_cb");
329         }
330 
331         if(!state.timer_deleted) {
332             LV_TRACE_TIMER("timer callback %p finished", *((void **)&timer->timer_cb));
333         }
334         else {
335             LV_TRACE_TIMER("timer callback finished");
336         }
337 
338         LV_ASSERT_MEM_INTEGRITY();
339         exec = true;
340     }
341 
342     if(state.timer_deleted == false) { /*The timer might be deleted by itself as well*/
343         if(timer->repeat_count == 0) { /*The repeat count is over, delete the timer*/
344             if(timer->auto_delete) {
345                 LV_TRACE_TIMER("deleting timer with %p callback because the repeat count is over", *((void **)&timer->timer_cb));
346                 lv_timer_delete(timer);
347             }
348             else {
349                 LV_TRACE_TIMER("pausing timer with %p callback because the repeat count is over", *((void **)&timer->timer_cb));
350                 lv_timer_pause(timer);
351             }
352         }
353     }
354 
355     return exec;
356 }
357 
358 /**
359  * Find out how much time remains before a timer must be run.
360  * @param timer pointer to lv_timer
361  * @return the time remaining, or 0 if it needs to be run again
362  */
lv_timer_time_remaining(lv_timer_t * timer)363 static uint32_t lv_timer_time_remaining(lv_timer_t * timer)
364 {
365     /*Check if at least 'period' time elapsed*/
366     uint32_t elp = lv_tick_elaps(timer->last_run);
367     if(elp >= timer->period)
368         return 0;
369     return timer->period - elp;
370 }
371 
372 /**
373  * Call the ready lv_timer
374  */
lv_timer_handler_resume(void)375 static void lv_timer_handler_resume(void)
376 {
377     /*If there is a timer which is ready to run then resume the timer loop*/
378     state.timer_time_until_next = 0;
379     if(state.resume_cb) {
380         state.resume_cb(state.resume_data);
381     }
382 }
383 
lv_timer_handler_set_resume_cb(lv_timer_handler_resume_cb_t cb,void * data)384 void lv_timer_handler_set_resume_cb(lv_timer_handler_resume_cb_t cb, void * data)
385 {
386     state.resume_cb = cb;
387     state.resume_data = data;
388 }
389