Add back task features in a simplified way

This commit is contained in:
Steins7 2024-07-09 11:53:05 +02:00
parent b7951f2211
commit 173e16eb2e
2 changed files with 132 additions and 36 deletions

View File

@ -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;
}

View File

@ -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): \