From 173e16eb2e771b4aaee62d8d61b5c176bbdd8f40 Mon Sep 17 00:00:00 2001 From: Steins7 Date: Tue, 9 Jul 2024 11:53:05 +0200 Subject: [PATCH] Add back task features in a simplified way --- srv/task.c | 84 +++++++++++++++++++++++++++++++++++++++++++----------- srv/task.h | 84 +++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 132 insertions(+), 36 deletions(-) diff --git a/srv/task.c b/srv/task.c index d76b281..54989cb 100644 --- a/srv/task.c +++ b/srv/task.c @@ -10,36 +10,50 @@ #include "task.h" #include "error.h" +#include "../drv/stk.h" //--local definitions----------------------------------------------------------- #define MAX_TASK_NB 10 +static bool execute_task(struct Task* restrict task, uint8_t triggers); +static void callback_stk(void); +static void callback_rtc(void); + //--local variables------------------------------------------------------------- static struct Task task_list[MAX_TASK_NB]; static uint8_t task_nb; +static volatile bool stk_irq; +static volatile bool rtc_irq; +static volatile uint32_t timestamp; //--public functions------------------------------------------------------------ -void task_schedule(uint32_t elapsed_ms) +void task_start_scheduler(void) { - for (uint8_t i = 0; i < task_nb; ++i) { - if (task_list[i].function != nullptr) { + stk_configure(1000, callback_stk); + //TODO: configure RTC - 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; - } - } else { - task_list[i].state.delay -= elapsed_ms; - } + while (true) { + uint8_t triggers = stk_irq << 0 | rtc_irq << 1; + stk_irq = false; + rtc_irq = false; + bool stk_needed = false; + for (uint8_t i = 0; i < task_nb; ++i) { + stk_needed |= execute_task(&task_list[i], triggers); + } + + if (stk_needed) { + stk_start(); + __asm("wfi"); + } else { + stk_stop(); + //TODO: enter deep sleep } } } @@ -50,9 +64,8 @@ void task_start(TaskFunction function) if (task_list[i].function == nullptr) { task_list[i].function = function; - task_list[i].state.delay = 0; + task_list[i].state.timestamp = 0; task_list[i].state.count = 0; - task_list[i].state.is_active = false; ++task_nb; return; @@ -66,8 +79,8 @@ void task_stop(TaskFunction function) { for (uint8_t i = 0; i < task_nb; ++i) { 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].state.count = _TASK_COUNT_CLEANUP & 0x1F; + task_list[i].function(&task_list[i].state, timestamp); task_list[i].function = nullptr; return; @@ -88,3 +101,42 @@ bool task_is_running(TaskFunction function) return false; } + +//--local functions------------------------------------------------------------- + +static bool execute_task(struct Task* restrict task, uint8_t triggers) +{ + if (task->function != nullptr) { + if (task->state.trigger == TASK_TRIGGER_ANY) { + task->function(&task->state, timestamp); + } else { + if ((task->state.trigger & triggers) != 0) { + + if (task->state.timestamp <= timestamp) { + task->state.timestamp = 0; + } + + if ((task->state.timestamp == 0) || + task->state.timeout_mode) { + task->function(&task->state, + timestamp); + } + } + } + + return (task->state.trigger & TASK_TRIGGER_STK) != 0; + } + + return false; +} + +static void callback_stk(void) +{ + stk_irq = true; + ++timestamp; +} + +static void callback_rtc(void) +{ + rtc_irq = true; +} diff --git a/srv/task.h b/srv/task.h index 4f5e208..ff4f183 100644 --- a/srv/task.h +++ b/srv/task.h @@ -17,13 +17,21 @@ //--type definitions------------------------------------------------------------ -struct TaskState { - int32_t delay; - uint8_t count:7; - uint8_t is_active:1; +enum TaskTrigger { + TASK_TRIGGER_ANY, + TASK_TRIGGER_STK, + TASK_TRIGGER_RTC, + TASK_TRIGGER_BOTH, }; -typedef void(*TaskFunction)(struct TaskState*); +struct TaskState { + uint32_t timestamp; + uint8_t count:5; + enum TaskTrigger trigger:2; + uint8_t timeout_mode:1; +}; + +typedef void(*TaskFunction)(struct TaskState*, uint32_t); struct Task { TaskFunction function; @@ -33,10 +41,12 @@ struct Task { //--functions------------------------------------------------------------------- -#define TASK(fct_name) void fct_name(struct TaskState* restrict __task_state) +#define TASK(fct_name) void fct_name(struct TaskState* restrict __task_state, \ + uint32_t __task_time) #define TASK_ENTRY \ _TASK_COUNT_INIT; \ + (void*) __task_time; \ switch (__task_state->count) { #define TASK_CLEANUP \ @@ -45,19 +55,22 @@ struct Task { #define TASK_EXIT \ } \ - __task_state->count = _TASK_COUNT_EXIT; \ + __task_state->count = _TASK_COUNT_EXIT & 0x1F; \ return; -#define TASK_TIMEOUT +#define TASK_TIMEOUT (__task_state->timeout == 0) #define TASK_YIELD() _TASK_YIELD(_TASK_COUNT_INCR) -#define TASK_SLEEP(delay_ms) _TASK_SLEEP(delay_ms, _TASK_COUNT_INCR) +#define TASK_PAUSE(delay_ms) _TASK_PAUSE(delay_ms, _TASK_COUNT_INCR) +#define TASK_SLEEP(delay_s) _TASK_SLEEP(delay_s, _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_PAUSE_UNTIL(cond, delay_ms) \ + _TASK_PAUSE_UNTIL(cond, delay_ms, _TASK_COUNT_INCR) +#define TASK_SLEEP_UNTIL(cond, delay_s) \ + _TASK_SLEEP_UNTIL(cond, delay_s, _TASK_COUNT_INCR) #define TASK_EXECUTE(task) _TASK_EXECUTE(task, _TASK_COUNT_INCR) -void task_schedule(uint32_t elapsed_ms); +void task_start_scheduler(void); void task_declare(); @@ -70,19 +83,30 @@ bool task_is_running(TaskFunction task); #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 & 0x7F) +#define _TASK_COUNT_EXIT (UINT8_MAX & 0x3F) #define _TASK_COUNT_CLEANUP (UINT8_MAX - 1) #define _TASK_YIELD(count_val) do { \ __task_state->count = count_val; \ + __task_state->trigger = TASK_TRIGGER_ANY; \ return; \ case (count_val): \ /* fall through */ \ } while (0) -#define _TASK_SLEEP(delay_ms, count_val) do { \ +#define _TASK_PAUSE(delay_ms, count_val) do { \ __task_state->count = count_val; \ - __task_state->delay = delay_ms; \ + __task_state->timestamp = __task_time + delay_ms; \ + __task_state->trigger = TASK_TRIGGER_STK; \ + return; \ + case (count_val): \ + /* fall through */ \ + } while (0) + +#define _TASK_SLEEP(delay_s, count_val) do { \ + __task_state->count = count_val; \ + __task_state->timestamp = __task_time + delay_s * 1000; \ + __task_state->trigger = TASK_TRIGGER_RTC; \ return; \ case (count_val): \ /* fall through */ \ @@ -90,6 +114,7 @@ bool task_is_running(TaskFunction task); #define _TASK_YIELD_UNTIL(cond, count_val) do { \ __task_state->count = count_val; \ + __task_state->trigger = TASK_TRIGGER_ANY; \ case (count_val): \ if (!(cond)) { \ return; \ @@ -97,20 +122,39 @@ bool task_is_running(TaskFunction task); /* fall through */ \ } while (0) -#define _TASK_SLEEP_UNTIL(cond, delay_ms, count_val) do { \ +#define _TASK_PAUSE_UNTIL(cond, delay_ms, count_val) do { \ __task_state->count = count_val; \ - __task_state->delay = delay_ms; \ - __task_state->is_active = true; \ + __task_state->timestamp = __task_time + delay_ms; \ + __task_state->trigger = TASK_TRIGGER_STK; \ + __task_state->timeout_mode = true; \ + } \ case (count_val): \ - if (!(cond) && __task_state->delay >= 0) { \ + if (!(cond) && __task_state->timestamp != 0) { \ return; \ + } else { \ + __task_state->timeout_mode = false; \ + } \ + /* fall through */ \ + } while (0) + +#define _TASK_SLEEP_UNTIL(cond, delay_s, count_val) do { \ + __task_state->count = count_val; \ + __task_state->timestamp = __taks_time + delay_s * 1000; \ + __task_state->trigger = TASK_TRIGGER_RTC; \ + __task_state->timeout_mode = true; \ + } \ + case (count_val): \ + if (!(cond) && __task_state->timestamp != 0) { \ + return; \ + } else { \ + __task_state->timeout_mode = false; \ } \ - __task_state->is_active = false; \ /* fall through */ \ } while (0) #define _TASK_EXECUTE(task, count_val) do { \ __task_state->count = count_val; \ + __task_state->trigger = TASK_TRIGGER_ANY; \ task_start(Task task); \ return; \ case (count_val): \