Simplify task module

This commit is contained in:
Steins7 2024-07-06 22:43:50 +02:00
parent 7cb33f65a5
commit b7951f2211
2 changed files with 93 additions and 120 deletions

View File

@ -9,99 +9,50 @@
//--includes-------------------------------------------------------------------- //--includes--------------------------------------------------------------------
#include "task.h" #include "task.h"
#include "../drv/stk.h"
#include "error.h" #include "error.h"
#include "debug.h"
//--local definitions----------------------------------------------------------- //--local definitions-----------------------------------------------------------
#define MAX_TASK_NB 10 #define MAX_TASK_NB 10
struct TaskContext {
Task function;
uint32_t delay_ms;
uint8_t state;
};
void task_callback(void);
//--local variables------------------------------------------------------------- //--local variables-------------------------------------------------------------
static struct TaskContext task_list[MAX_TASK_NB]; static struct Task task_list[MAX_TASK_NB];
static uint8_t task_nb; static uint8_t task_nb;
//--public functions------------------------------------------------------------ //--public functions------------------------------------------------------------
void task_start_scheduler(void) void task_schedule(uint32_t elapsed_ms)
{ {
while (1) {
uint32_t delay = UINT32_MAX;
bool task_runned = false;
for (uint8_t i = 0; i < task_nb; ++i) { for (uint8_t i = 0; i < task_nb; ++i) {
if (task_list[i].function != nullptr) { if (task_list[i].function != nullptr) {
if (task_list[i].delay_ms == 0) {
task_runned = true; if (task_list[i].state.is_active
debug_trace("%u", 1); || task_list[i].state.delay <= 0) {
debug_trace("%u", i + 2); task_list[i].function(&task_list[i].state);
struct TaskReturn ret if (task_list[i].state.count == _TASK_COUNT_EXIT) {
= 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; task_list[i].function = nullptr;
}
} else { } else {
task_list[i].delay_ms = ret.delay_ms; task_list[i].state.delay -= elapsed_ms;
task_list[i].state = ret.state;
}
}
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;
}
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) { for (uint8_t i = 0; i < MAX_TASK_NB; ++i) {
if (task_list[i].function == nullptr) { if (task_list[i].function == nullptr) {
task_list[i].function = task; task_list[i].function = function;
task_list[i].delay_ms = 0; task_list[i].state.delay = 0;
task_list[i].state = 0; task_list[i].state.count = 0;
task_list[i].state.is_active = false;
++task_nb; ++task_nb;
return; return;
@ -111,11 +62,12 @@ void task_start(Task task)
error_trigger("task list is full"); 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) { for (uint8_t i = 0; i < task_nb; ++i) {
if (task_list[i].function == task) { if (task_list[i].function == function) {
task_list[i].function(_TASK_COUNT_CLEANUP); task_list[i].state.count = _TASK_COUNT_CLEANUP & 0x7F;
task_list[i].function(&task_list[i].state);
task_list[i].function = nullptr; task_list[i].function = nullptr;
return; return;
@ -125,10 +77,10 @@ void task_stop(Task task)
error_trigger("task does not exist"); 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) { for (uint8_t i = 0; i < task_nb; ++i) {
if (task_list[i].function == task) { if (task_list[i].function == function) {
return true; return true;
} }
} }
@ -136,10 +88,3 @@ bool task_is_running(Task task)
return false; return false;
} }
//--local functions-------------------------------------------------------------
void task_callback(void) {
stk_stop();
}

View File

@ -17,21 +17,27 @@
//--type definitions------------------------------------------------------------ //--type definitions------------------------------------------------------------
struct TaskReturn { struct TaskState {
uint32_t delay_ms; int32_t delay;
uint8_t state; 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------------------------------------------------------------------- //--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 \ #define TASK_ENTRY \
_TASK_COUNT_INIT; \ _TASK_COUNT_INIT; \
switch (__task_state) { switch (__task_state->count) {
#define TASK_CLEANUP \ #define TASK_CLEANUP \
case (_TASK_COUNT_CLEANUP): \ case (_TASK_COUNT_CLEANUP): \
@ -39,55 +45,77 @@ typedef struct TaskReturn(*Task)(uint8_t);
#define TASK_EXIT \ #define TASK_EXIT \
} \ } \
return (struct TaskReturn){0, _TASK_COUNT_EXIT}; __task_state->count = _TASK_COUNT_EXIT; \
return;
#define TASK_TIMEOUT
#define TASK_YIELD() _TASK_YIELD(_TASK_COUNT_INCR) #define TASK_YIELD() _TASK_YIELD(_TASK_COUNT_INCR)
#define TASK_SLEEP(delay_ms) _TASK_SLEEP(delay_ms, _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) #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_declare();
void task_stop(Task task);
bool task_is_running(Task task); void task_start(TaskFunction task);
void task_stop(TaskFunction task);
bool task_is_running(TaskFunction task);
//--internal_functions---------------------------------------------------------- //--internal_functions----------------------------------------------------------
#define _TASK_COUNT_INIT enum { TASK_COUNTER_BASE = __COUNTER__ } #define _TASK_COUNT_INIT enum { TASK_COUNTER_BASE = __COUNTER__ }
#define _TASK_COUNT_INCR (uint8_t)(__COUNTER__ - TASK_COUNTER_BASE - 1) #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_COUNT_CLEANUP (UINT8_MAX - 1)
#define _TASK(fct_name) #define _TASK_YIELD(count_val) do { \
__task_state->count = count_val; \
#define _TASK_YIELD(count) do { \ return; \
return (struct TaskReturn){0, count}; \ case (count_val): \
case (count): \
/* fall through */ \ /* fall through */ \
} while (0) } while (0)
#define _TASK_SLEEP(delay_ms, count) do { \ #define _TASK_SLEEP(delay_ms, count_val) do { \
return (struct TaskReturn){delay_ms, count}; \ __task_state->count = count_val; \
case (count): \ __task_state->delay = delay_ms; \
return; \
case (count_val): \
/* fall through */ \ /* fall through */ \
} while (0) } while (0)
#define _TASK_WAIT_UNTIL(cond, count) do { \ #define _TASK_YIELD_UNTIL(cond, count_val) do { \
case (count): \ __task_state->count = count_val; \
case (count_val): \
if (!(cond)) { \ if (!(cond)) { \
return (struct TaskReturn){0, count}; \ return; \
} \ } \
/* fall through */ \ /* fall through */ \
} while (0) } while (0)
#define _TASK_EXECUTE(task, count) do { \ #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); \ task_start(Task task); \
return (struct TaskReturn){0, count); \ return; \
case (count): \ case (count_val): \
if (task_is_running(task)) { \ if (task_is_running(task)) { \
return (struct TaskReturn){0, count}; \ return; \
} \ } \
/* fall through */ \ /* fall through */ \
} while (0) } while (0)