diff options
Diffstat (limited to 'src/libs/lvgl/src/lv_misc/lv_task.c')
| m--------- | src/libs/lvgl | 0 | ||||
| -rw-r--r-- | src/libs/lvgl/src/lv_misc/lv_task.c | 415 |
2 files changed, 0 insertions, 415 deletions
diff --git a/src/libs/lvgl b/src/libs/lvgl new file mode 160000 +Subproject 23430cf20e32294549fff9b2879a9466dacc19b diff --git a/src/libs/lvgl/src/lv_misc/lv_task.c b/src/libs/lvgl/src/lv_misc/lv_task.c deleted file mode 100644 index 147ada6..0000000 --- a/src/libs/lvgl/src/lv_misc/lv_task.c +++ /dev/null @@ -1,415 +0,0 @@ -/** - * @file lv_task.c - * An 'lv_task' is a void (*fp) (struct _lv_task_t* param) type function which will be called periodically. - * A priority (5 levels + disable) can be assigned to lv_tasks. - */ - -/********************* - * INCLUDES - *********************/ -#include <stddef.h> -#include "lv_task.h" -#include "../lv_misc/lv_debug.h" -#include "../lv_hal/lv_hal_tick.h" -#include "lv_gc.h" - -/********************* - * DEFINES - *********************/ -#define IDLE_MEAS_PERIOD 500 /*[ms]*/ -#define DEF_PRIO LV_TASK_PRIO_MID -#define DEF_PERIOD 500 - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static bool lv_task_exec(lv_task_t * task); -static uint32_t lv_task_time_remaining(lv_task_t * task); - -/********************** - * STATIC VARIABLES - **********************/ -static bool lv_task_run = false; -static uint8_t idle_last = 0; -static bool task_deleted; -static bool task_list_changed; -static bool task_created; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -/** - * Init the lv_task module - */ -void _lv_task_core_init(void) -{ - _lv_ll_init(&LV_GC_ROOT(_lv_task_ll), sizeof(lv_task_t)); - - /*Initially enable the lv_task handling*/ - lv_task_enable(true); -} - -/** - * Call it periodically to handle lv_tasks. - * @return the time after which it must be called again - */ -LV_ATTRIBUTE_TASK_HANDLER uint32_t lv_task_handler(void) -{ - LV_LOG_TRACE("lv_task_handler started"); - - /*Avoid concurrent running of the task handler*/ - static bool already_running = false; - if(already_running) return 1; - already_running = true; - - if(lv_task_run == false) { - already_running = false; /*Release mutex*/ - return 1; - } - - static uint32_t idle_period_start = 0; - static uint32_t busy_time = 0; - - uint32_t handler_start = lv_tick_get(); - - /* Run all task from the highest to the lowest priority - * If a lower priority task is executed check task again from the highest priority - * but on the priority of executed tasks don't run tasks before the executed*/ - lv_task_t * task_interrupter = NULL; - lv_task_t * next; - bool end_flag; - do { - end_flag = true; - task_deleted = false; - task_created = false; - task_list_changed = false; - LV_GC_ROOT(_lv_task_act) = _lv_ll_get_head(&LV_GC_ROOT(_lv_task_ll)); - while(LV_GC_ROOT(_lv_task_act)) { - /* The task might be deleted if it runs only once ('once = 1') - * So get next element until the current is surely valid*/ - next = _lv_ll_get_next(&LV_GC_ROOT(_lv_task_ll), LV_GC_ROOT(_lv_task_act)); - - /*We reach priority of the turned off task. There is nothing more to do.*/ - if(LV_GC_ROOT(_lv_task_act)->prio == LV_TASK_PRIO_OFF) { - break; - } - - /*Here is the interrupter task. Don't execute it again.*/ - if(LV_GC_ROOT(_lv_task_act) == task_interrupter) { - task_interrupter = NULL; /*From this point only task after the interrupter comes, so - the interrupter is not interesting anymore*/ - LV_GC_ROOT(_lv_task_act) = next; - continue; /*Load the next task*/ - } - - /*Just try to run the tasks with highest priority.*/ - if(LV_GC_ROOT(_lv_task_act)->prio == LV_TASK_PRIO_HIGHEST) { - lv_task_exec(LV_GC_ROOT(_lv_task_act)); - } - /*Tasks with higher priority than the interrupted shall be run in every case*/ - else if(task_interrupter) { - if(LV_GC_ROOT(_lv_task_act)->prio > task_interrupter->prio) { - if(lv_task_exec(LV_GC_ROOT(_lv_task_act))) { - if(!task_created && !task_deleted) { - /*Check all tasks again from the highest priority */ - task_interrupter = LV_GC_ROOT(_lv_task_act); - end_flag = false; - break; - } - } - } - } - /* It is no interrupter task or we already reached it earlier. - * Just run the remaining tasks*/ - else { - if(lv_task_exec(LV_GC_ROOT(_lv_task_act))) { - if(!task_created && !task_deleted) { - task_interrupter = LV_GC_ROOT(_lv_task_act); /*Check all tasks again from the highest priority */ - end_flag = false; - break; - } - } - } - - /*If a task was created or deleted then this or the next item might be corrupted*/ - if(task_created || task_deleted) { - task_interrupter = NULL; - break; - } - - if(task_list_changed) { - task_interrupter = NULL; - end_flag = false; - break; - } - - LV_GC_ROOT(_lv_task_act) = next; /*Load the next task*/ - } - } while(!end_flag); - - uint32_t time_till_next = LV_NO_TASK_READY; - next = _lv_ll_get_head(&LV_GC_ROOT(_lv_task_ll)); - while(next && next->prio != LV_TASK_PRIO_OFF) { - uint32_t delay = lv_task_time_remaining(next); - if(delay < time_till_next) - time_till_next = delay; - - next = _lv_ll_get_next(&LV_GC_ROOT(_lv_task_ll), next); /*Find the next task*/ - } - - busy_time += lv_tick_elaps(handler_start); - uint32_t idle_period_time = lv_tick_elaps(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(); - } - - already_running = false; /*Release the mutex*/ - - LV_LOG_TRACE("lv_task_handler ready"); - return time_till_next; -} -/** - * Create an "empty" task. It needs to initialized with at least - * `lv_task_set_cb` and `lv_task_set_period` - * @return pointer to the created task - */ -lv_task_t * lv_task_create_basic(void) -{ - return lv_task_create(NULL, DEF_PERIOD, DEF_PRIO, NULL); -} - -/** - * Create a new lv_task - * @param task_xcb a callback which is the task itself. It will be called periodically. - * (the 'x' in the argument name indicates that its not a fully generic function because it not follows - * the `func_name(object, callback, ...)` convention) - * @param period call period in ms unit - * @param prio priority of the task (LV_TASK_PRIO_OFF means the task is stopped) - * @param user_data custom parameter - * @return pointer to the new task - */ -lv_task_t * lv_task_create(lv_task_cb_t task_xcb, uint32_t period, lv_task_prio_t prio, void * user_data) -{ - lv_task_t * new_task = NULL; - lv_task_t * tmp; - - /*Create task lists in order of priority from high to low*/ - tmp = _lv_ll_get_head(&LV_GC_ROOT(_lv_task_ll)); - - /*It's the first task*/ - if(NULL == tmp) { - new_task = _lv_ll_ins_head(&LV_GC_ROOT(_lv_task_ll)); - LV_ASSERT_MEM(new_task); - if(new_task == NULL) return NULL; - } - /*Insert the new task to proper place according to its priority*/ - else { - do { - if(tmp->prio <= prio) { - new_task = _lv_ll_ins_prev(&LV_GC_ROOT(_lv_task_ll), tmp); - LV_ASSERT_MEM(new_task); - if(new_task == NULL) return NULL; - break; - } - tmp = _lv_ll_get_next(&LV_GC_ROOT(_lv_task_ll), tmp); - } while(tmp != NULL); - - /*Only too high priority tasks were found. Add the task to the end*/ - if(tmp == NULL) { - new_task = _lv_ll_ins_tail(&LV_GC_ROOT(_lv_task_ll)); - LV_ASSERT_MEM(new_task); - if(new_task == NULL) return NULL; - } - } - task_list_changed = true; - - new_task->period = period; - new_task->task_cb = task_xcb; - new_task->prio = prio; - - new_task->repeat_count = -1; - new_task->last_run = lv_tick_get(); - - new_task->user_data = user_data; - - task_created = true; - - return new_task; -} - -/** - * Set the callback the task (the function to call periodically) - * @param task pointer to a task - * @param task_cb the function to call periodically - */ -void lv_task_set_cb(lv_task_t * task, lv_task_cb_t task_cb) -{ - task->task_cb = task_cb; -} - -/** - * Delete a lv_task - * @param task pointer to task created by task - */ -void lv_task_del(lv_task_t * task) -{ - _lv_ll_remove(&LV_GC_ROOT(_lv_task_ll), task); - task_list_changed = true; - - lv_mem_free(task); - - if(LV_GC_ROOT(_lv_task_act) == task) task_deleted = true; /*The active task was deleted*/ -} - -/** - * Set new priority for a lv_task - * @param task pointer to a lv_task - * @param prio the new priority - */ -void lv_task_set_prio(lv_task_t * task, lv_task_prio_t prio) -{ - if(task->prio == prio) return; - - /*Find the tasks with new priority*/ - lv_task_t * i; - _LV_LL_READ(LV_GC_ROOT(_lv_task_ll), i) { - if(i->prio <= prio) { - if(i != task) _lv_ll_move_before(&LV_GC_ROOT(_lv_task_ll), task, i); - break; - } - } - - /*There was no such a low priority so far then add the node to the tail*/ - if(i == NULL) { - _lv_ll_move_before(&LV_GC_ROOT(_lv_task_ll), task, NULL); - } - task_list_changed = true; - - task->prio = prio; -} - -/** - * Set new period for a lv_task - * @param task pointer to a lv_task - * @param period the new period - */ -void lv_task_set_period(lv_task_t * task, uint32_t period) -{ - task->period = period; -} - -/** - * Make a lv_task ready. It will not wait its period. - * @param task pointer to a lv_task. - */ -void lv_task_ready(lv_task_t * task) -{ - task->last_run = lv_tick_get() - task->period - 1; -} - -/** - * Set the number of times a task will repeat. - * @param task pointer to a lv_task. - * @param repeat_count -1 : infinity; 0 : stop ; n>0: residual times - */ -void lv_task_set_repeat_count(lv_task_t * task, int32_t repeat_count) -{ - task->repeat_count = repeat_count; -} - -/** - * Reset a lv_task. - * It will be called the previously set period milliseconds later. - * @param task pointer to a lv_task. - */ -void lv_task_reset(lv_task_t * task) -{ - task->last_run = lv_tick_get(); -} - -/** - * Enable or disable the whole lv_task handling - * @param en: true: lv_task handling is running, false: lv_task handling is suspended - */ -void lv_task_enable(bool en) -{ - lv_task_run = en; -} - -/** - * Get idle percentage - * @return the lv_task idle in percentage - */ -uint8_t lv_task_get_idle(void) -{ - return idle_last; -} - -/** - * Iterate through the tasks - * @param task NULL to start iteration or the previous return value to get the next task - * @return the next task or NULL if there is no more task - */ -lv_task_t * lv_task_get_next(lv_task_t * task) -{ - if(task == NULL) return _lv_ll_get_head(&LV_GC_ROOT(_lv_task_ll)); - else return _lv_ll_get_next(&LV_GC_ROOT(_lv_task_ll), task); -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -/** - * Execute task if its the priority is appropriate - * @param task pointer to lv_task - * @return true: execute, false: not executed - */ -static bool lv_task_exec(lv_task_t * task) -{ - bool exec = false; - - if(lv_task_time_remaining(task) == 0) { - task->last_run = lv_tick_get(); - if(task->task_cb) task->task_cb(task); - - /*Delete if it was a one shot lv_task*/ - if(task_deleted == false) { /*The task might be deleted by itself as well*/ - if(task->repeat_count > 0) { - task->repeat_count--; - } - if(task->repeat_count == 0) { - lv_task_del(task); - } - } - exec = true; - } - - return exec; -} - -/** - * Find out how much time remains before a task must be run. - * @param task pointer to lv_task - * @return the time remaining, or 0 if it needs to be run again - */ -static uint32_t lv_task_time_remaining(lv_task_t * task) -{ - /*Check if at least 'period' time elapsed*/ - uint32_t elp = lv_tick_elaps(task->last_run); - if(elp >= task->period) - return 0; - return task->period - elp; -} |
