diff --git a/srv/task.c b/srv/task.c index 72efc46..d76b281 100644 --- a/srv/task.c +++ b/srv/task.c @@ -9,99 +9,50 @@ //--includes-------------------------------------------------------------------- #include "task.h" -#include "../drv/stk.h" #include "error.h" -#include "debug.h" //--local definitions----------------------------------------------------------- #define MAX_TASK_NB 10 -struct TaskContext { - Task function; - uint32_t delay_ms; - uint8_t state; -}; - -void task_callback(void); - //--local variables------------------------------------------------------------- -static struct TaskContext task_list[MAX_TASK_NB]; +static struct Task task_list[MAX_TASK_NB]; static uint8_t task_nb; //--public functions------------------------------------------------------------ -void task_start_scheduler(void) +void task_schedule(uint32_t elapsed_ms) { - while (1) { - uint32_t delay = UINT32_MAX; + for (uint8_t i = 0; i < task_nb; ++i) { + if (task_list[i].function != nullptr) { - bool task_runned = false; - for (uint8_t i = 0; i < task_nb; ++i) { - if (task_list[i].function != nullptr) { - if (task_list[i].delay_ms == 0) { - task_runned = true; - debug_trace("%u", 1); - debug_trace("%u", i + 2); - struct TaskReturn ret - = task_list[i].function(task_list[i].state); - debug_trace("%u", i + 2); - debug_trace("%u", 1); - if (ret.state == _TASK_COUNT_EXIT) { - task_list[i].function = nullptr; - } else { - task_list[i].delay_ms = ret.delay_ms; - task_list[i].state = ret.state; - } + if (task_list[i].state.is_active + || task_list[i].state.delay <= 0) { + task_list[i].function(&task_list[i].state); + if (task_list[i].state.count == _TASK_COUNT_EXIT) { + task_list[i].function = nullptr; } - if (delay > task_list[i].delay_ms) { - delay = task_list[i].delay_ms; - } - } - } - - if (task_runned) { - break; - } - - if (delay > 0) { - debug_trace("%u", 1); - debug_trace("%u", 0); - stk_configure(delay * 1000, task_callback); - stk_start(); - __asm("wfi"); - stk_stop(); - uint32_t stk_delay = stk_read_us(); - if (stk_delay != 0) { - delay = stk_delay; + } else { + task_list[i].state.delay -= elapsed_ms; } - for (uint8_t i = 0; i < task_nb; ++i) { - if (task_list[i].function != nullptr) { - task_list[i].delay_ms -= delay; - } - } - - debug_trace("%u", 0); - debug_trace("%u", 1); } } - - //never returns } -void task_start(Task task) +void task_start(TaskFunction function) { for (uint8_t i = 0; i < MAX_TASK_NB; ++i) { if (task_list[i].function == nullptr) { - task_list[i].function = task; - task_list[i].delay_ms = 0; - task_list[i].state = 0; + task_list[i].function = function; + task_list[i].state.delay = 0; + task_list[i].state.count = 0; + task_list[i].state.is_active = false; ++task_nb; return; @@ -111,11 +62,12 @@ void task_start(Task task) error_trigger("task list is full"); } -void task_stop(Task task) +void task_stop(TaskFunction function) { for (uint8_t i = 0; i < task_nb; ++i) { - if (task_list[i].function == task) { - task_list[i].function(_TASK_COUNT_CLEANUP); + if (task_list[i].function == function) { + task_list[i].state.count = _TASK_COUNT_CLEANUP & 0x7F; + task_list[i].function(&task_list[i].state); task_list[i].function = nullptr; return; @@ -125,10 +77,10 @@ void task_stop(Task task) error_trigger("task does not exist"); } -bool task_is_running(Task task) +bool task_is_running(TaskFunction function) { for (uint8_t i = 0; i < task_nb; ++i) { - if (task_list[i].function == task) { + if (task_list[i].function == function) { return true; } } @@ -136,10 +88,3 @@ bool task_is_running(Task task) return false; } - -//--local functions------------------------------------------------------------- - -void task_callback(void) { - stk_stop(); -} - diff --git a/srv/task.h b/srv/task.h index 435cca3..4f5e208 100644 --- a/srv/task.h +++ b/srv/task.h @@ -17,79 +17,107 @@ //--type definitions------------------------------------------------------------ -struct TaskReturn { - uint32_t delay_ms; - uint8_t state; +struct TaskState { + int32_t delay; + uint8_t count:7; + uint8_t is_active:1; }; -typedef struct TaskReturn(*Task)(uint8_t); +typedef void(*TaskFunction)(struct TaskState*); + +struct Task { + TaskFunction function; + struct TaskState state; +}; //--functions------------------------------------------------------------------- -#define TASK(fct_name) struct TaskReturn fct_name(uint8_t __task_state) +#define TASK(fct_name) void fct_name(struct TaskState* restrict __task_state) -#define TASK_ENTRY \ - _TASK_COUNT_INIT; \ - switch (__task_state) { +#define TASK_ENTRY \ + _TASK_COUNT_INIT; \ + switch (__task_state->count) { -#define TASK_CLEANUP \ - case (_TASK_COUNT_CLEANUP): \ +#define TASK_CLEANUP \ + case (_TASK_COUNT_CLEANUP): \ /* fall through */ -#define TASK_EXIT \ - } \ - return (struct TaskReturn){0, _TASK_COUNT_EXIT}; +#define TASK_EXIT \ + } \ + __task_state->count = _TASK_COUNT_EXIT; \ + return; + +#define TASK_TIMEOUT #define TASK_YIELD() _TASK_YIELD(_TASK_COUNT_INCR) #define TASK_SLEEP(delay_ms) _TASK_SLEEP(delay_ms, _TASK_COUNT_INCR) -#define TASK_WAIT_UNTIL(cond) _TASK_WAIT_UNTIL(cond, _TASK_COUNT_INCR) +#define TASK_YIELD_UNTIL(cond) _TASK_YIELD_UNTIL(cond, _TASK_COUNT_INCR) +#define TASK_SLEEP_UNTIL(cond, delay_ms) \ + _TASK_SLEEP_UNTIL(cond, delay_ms, _TASK_COUNT_INCR) #define TASK_EXECUTE(task) _TASK_EXECUTE(task, _TASK_COUNT_INCR) -void task_start_scheduler(void); +void task_schedule(uint32_t elapsed_ms); -void task_start(Task task); -void task_stop(Task task); -bool task_is_running(Task task); +void task_declare(); + +void task_start(TaskFunction task); +void task_stop(TaskFunction task); +bool task_is_running(TaskFunction task); //--internal_functions---------------------------------------------------------- #define _TASK_COUNT_INIT enum { TASK_COUNTER_BASE = __COUNTER__ } #define _TASK_COUNT_INCR (uint8_t)(__COUNTER__ - TASK_COUNTER_BASE - 1) -#define _TASK_COUNT_EXIT UINT8_MAX +#define _TASK_COUNT_EXIT (UINT8_MAX & 0x7F) #define _TASK_COUNT_CLEANUP (UINT8_MAX - 1) -#define _TASK(fct_name) - -#define _TASK_YIELD(count) do { \ - return (struct TaskReturn){0, count}; \ - case (count): \ - /* fall through */ \ +#define _TASK_YIELD(count_val) do { \ + __task_state->count = count_val; \ + return; \ + case (count_val): \ + /* fall through */ \ } while (0) -#define _TASK_SLEEP(delay_ms, count) do { \ - return (struct TaskReturn){delay_ms, count}; \ - case (count): \ - /* fall through */ \ +#define _TASK_SLEEP(delay_ms, count_val) do { \ + __task_state->count = count_val; \ + __task_state->delay = delay_ms; \ + return; \ + case (count_val): \ + /* fall through */ \ } while (0) -#define _TASK_WAIT_UNTIL(cond, count) do { \ - case (count): \ - if (!(cond)) { \ - return (struct TaskReturn){0, count}; \ - } \ - /* fall through */ \ +#define _TASK_YIELD_UNTIL(cond, count_val) do { \ + __task_state->count = count_val; \ + case (count_val): \ + if (!(cond)) { \ + return; \ + } \ + /* fall through */ \ } while (0) -#define _TASK_EXECUTE(task, count) do { \ - task_start(Task task); \ - return (struct TaskReturn){0, count); \ - case (count): \ - if (task_is_running(task)) { \ - return (struct TaskReturn){0, count}; \ - } \ - /* fall through */ \ +#define _TASK_SLEEP_UNTIL(cond, delay_ms, count_val) do { \ + __task_state->count = count_val; \ + __task_state->delay = delay_ms; \ + __task_state->is_active = true; \ + case (count_val): \ + if (!(cond) && __task_state->delay >= 0) { \ + return; \ + } \ + __task_state->is_active = false; \ + /* fall through */ \ + } while (0) + +#define _TASK_EXECUTE(task, count_val) do { \ + __task_state->count = count_val; \ + task_start(Task task); \ + return; \ + case (count_val): \ + if (task_is_running(task)) { \ + return; \ + } \ + /* fall through */ \ } while (0) #endif //_task_h_